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........
最终:
扩展阅读:
CmBacktrace在keil上的移植
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即可。