新建一个STMF103C8T6 CUMX工程:只是使能SWD口,其他保存默认。
代码
代码运行进入Harldfault
程序转bin文件:
fromelf --text -a -c --output=Divisor.dis Divisor\Divisor.axf首先声明,除数为0进入HardFault的前提条件是 把SCB_CCR寄存器bit4置1才会进入HardFault。
Jlink命令工具:
输入:
1.USB
2.HALT 单片机停止工作
3.这里是STM32F103C8 输入单片机相关信息,和连接模式这里选择SWD
4.然后回车
看到PC执行08000ACA,SP 指向2000063C
打开反汇编代码:看到0800ACA是Hardfault函数,说明程序已经死了。
现在查找原因为什么进入Hardfault
5.把栈里的内容保存到电脑savebin f:/RAM.bin 0x20000000 0x10000
f:是我电脑的F盘, RAM.bin是文件名字; 0x20000000 是栈基地址;0x10000是栈大小。把整个栈的内存全部保存下来。
6.打开RAM.bin文件,0x2 后面7个0
定位到SP 2000063C
首先要明确一个机制:
Cortex-M 的异常自动压栈(Exception Stacking)
当 (Cortex-Mx)发生硬件异常(例如 HardFault、内存越界、取指错误)时,硬件会自动将 8 个寄存器( R0, R1, R2, R3, R12, LR,PC,xPSR,)压入当前使用的栈(MSP 或 PSP)。
LR: 08000B29; PC :08000294; XPSR:61000000
我们看一下PC :08000294
进入Hardfault,是Caculate函数执行的;我们查一下LR: 08000B29是保存的Caculate函数的返回地址:
为什么0x8000b29,汇编时08000b28 ?
直接回答:Thumb 模式。
0x08000B29的 LSB 为 1。实际指令位于0x08000B28。
代码思路来自郭天祥。
注意:代码优化为0
如果代码不优化时,会警告除数为0
../Core/Src/main.c(59): warning: C4018W: division by zero: /
return val1 / val2;