随笔 - 730  文章 - 2  评论 - 12  阅读 - 92万

keil遇到hardfault时原因的查找

 

当硬件仿真遇到hardfault会:依次将 xPSR、PC、LR、R12以及 R3~R0的8个寄存器压栈。参考2

1 首先通过LR(看LR的BIT2是0还是1)判断出异常产生时当前使用的SP是MSP还是PSP。此时LR 会被更新为异常返回时需要使用的特殊值(EXC_RETURN)定义如下:

 

 2 根据SP对应的堆栈值查看内存,根据压栈的8个寄存器顺序找到出错时的PC值(倒数第二个)。

 3 goto PC寄存器位置。

进入响应的中断软件陷阱中void HardFault_Handler(void),此时通过view-registers中的

1 如果STACK=MSP,则查看SP的堆栈值,在memrory窗口输入sp的值回车,在地址内容之后的第21字节开始的4个字节为LR的值,在堆栈调用窗口右击选择show callee code,在反汇编窗口右击选择show code at address,输入LR的值然后回车,就是发生hardfault前的调用大致位置,仔细查找即可,

一般都是因为数组越界,访问了超过范围或者未定义的地址,或者利用字符串库函数或者内存操作库函数时出现的情况。扩展参考

 或者用

CmBacktrace +addr2line定位hardfault:

其中addr2line(addr2line (它是标准的 GNU Binutils 中的一部分)是一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具)可全盘搜索,然后将其放到C盘WINDOWS下,在ENV中添加软件包,在keil-mdk中设置axf输出(注意output下的bin和user下axf名字要一致),然后在出现hard fault后,在win 的命令行中切换到项目axf文件所在的文件夹,然后按照cmbacktrace中的提示在命令行中运行addr2line -e........

 

 最终:

《HardFault的诊断.pdf》:

复制代码
 1 /*
 2 **无操作系统只用MSP;带操作系统中断用 MSP,任务用 PSP;
 3 **SP究竟是MSP还是PSP,取决于LR.2(1=MSP;0=PSP.
 4 **将下述代码分别放入一个hard_fault_handler.c文件和
 5 **HardFault_Handler.s文件,再用cmbacktrace分析
 6 **/
 7 
 8 
 9 
10 /*建独立文件hard_fault_handler.c**/
11 void hard_fault_handler (unsigned int * hardfault_args)
12 {  
13     unsigned int stacked_r0;  
14     unsigned int stacked_r1;  
15     unsigned int stacked_r2;  
16     unsigned int stacked_r3;  
17     unsigned int stacked_r12;  
18     unsigned int stacked_lr;  
19     unsigned int stacked_pc;  
20     unsigned int stacked_psr;  
21     
22     stacked_r0 = ((unsigned long) hardfault_args[0]);  
23     stacked_r1 = ((unsigned long) hardfault_args[1]);  
24     stacked_r2 = ((unsigned long) hardfault_args[2]);  
25     stacked_r3 = ((unsigned long) hardfault_args[3]);  
26     stacked_r12 = ((unsigned long) hardfault_args[4]);  
27     stacked_lr = ((unsigned long) hardfault_args[5]);  
28     stacked_pc = ((unsigned long) hardfault_args[6]);  
29     stacked_psr = ((unsigned long) hardfault_args[7]);
30     
31     printf ("\n\n[Hard fault handler - all numbers in hex]\n");  
32     printf ("R0 = %x\n", stacked_r0);  
33     printf ("R1 = %x\n", stacked_r1);  
34     printf ("R2 = %x\n", stacked_r2);  
35     printf ("R3 = %x\n", stacked_r3);  
36     printf ("R12 = %x\n", stacked_r12);  
37     printf ("LR [R14] = %x subroutine call return address\n", stacked_lr);  
38     printf ("PC [R15] = %x program counter\n", stacked_pc);  
39     printf ("PSR = %x\n", stacked_psr);  
40     printf ("BFAR = %x\n", (*((volatile unsigned long *)(0xE000ED38))));  
41     printf ("CFSR = %x\n", (*((volatile unsigned long *)(0xE000ED28))));  
42     printf ("HFSR = %x\n", (*((volatile unsigned long *)(0xE000ED2C))));  
43     printf ("DFSR = %x\n", (*((volatile unsigned long *)(0xE000ED30))));  
44     printf ("AFSR = %x\n", (*((volatile unsigned long *)(0xE000ED3C))));  
45     printf ("SCB_SHCSR = %x\n", SCB->SHCSR);   
46     while (1);
47 }
48 
49 ;建独立文件“HardFault_Handler.s”
50 HardFault_Handler:
51                     TST LR, #4
52                     ITE EQ
53                     MRSEQ R0, MSP
54                     MRSNE R0, PSPB 
55                     hard_fault_handler_c
View Code
复制代码

 

扩展阅读:

CmBacktrace在keil上的移植

STM32 HardFault_Handler调试总结

 

 

 

 RTT相关处理

Tracealyzer:支持FreeRTOS、Keil RTX5、Linux、On Time RTOS-32、ThreadX、µC/OS-III、VxWorks

 

Segger提供了一种分析CortexM内核芯片HardFault的方法:文档,相关软件。总体思路:屏蔽软件工程自己的hardfuault_hander,在它提供的软件(汇编或C)中修改_Continue让其退出hardfualut_hander后基本就是错误位置。

_Continue = 0u;

while (_Continue == 0u) { }

 

 

 

 

 当发生异常,会将保存上述寄存器到当前堆栈,LR.bit2的决定是主堆栈还是线程栈,其它28位都为1加载到PC.

Imprecise Bus Fault一般是由于写无效的地址,由于PC比实际写总线时间超前一点,所以要适当回退找到错误位置。

 lr为连接寄存器里面保存的是调用子程序之前的PC的值。 因为 CM3 内部 使用了指令流水线,读 PC 时返回的值是当前指令的地址+4 ,所以进入异常之前自动加载到lr的值也为调用子程序前的指令地址+4。由于PC的最低位保存ARM/Thumb 运行状态,Cortex-M3只能运行在Thumb 状态,即LSB = 1。所以我们想要找到出错误程序的指令位置, 只需要对打印出来的lr的值减去5即可。

posted on   杰瑞鼠  阅读(8194)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2018-07-03 软件模拟I2C时输入与输出切换
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示