J斌(´・ω・`)  

出现问题的现象

在用Keil对STM32的程序进行仿真时,程序有时候回跑飞,停止仿真程序会停在HardFault_Handler函数里的死循环while(1)中。这说明STM32出现了硬件错误。

------------------------------------- 图 1 -------------------------------------
STM32出现HardFault_Handler故障的原因主要有两个方面:

  1. 内存溢出或者访问越界。
  2. 堆栈溢出。

出现问题后查找问题点的方法

方法1:

① 发生异常后先查看LR寄存器中的值,确定当时使用堆栈为MSP还是PSP。

在Keil菜单栏点击【view】->【Registers Window】打开寄存器窗口,查看 R14(LR) 的值。
若R14(LR) = 0xFFFFFFE9, 查看 MSP(主堆栈指针)的值;
若R14(LR) = 0xFFFFFFFD, 查看 PSP(进程栈指针)的值。

------------------------------------- 图 2 -------------------------------------
上图的R14(LR) = 0xFFFF FFFD,则查看 PSP(进程栈指针)的值。

② 找到相应堆栈的指针,在内存中查看相应堆栈里的内容。

由于异常发生时,内核将R0~R3、R12、R14(LR)、PC、XPRS寄存器依次入栈,其中R14(LR)即为发生异常前PC将要执行的下一条指令地址。
注意:寄存器均是32位、且STM32是小端模式。(参考Cortex_M3权威指南)


------------------------------------- 图 3 -------------------------------------

从 图2 可看到SP的值为 0x200019A8,在Keil菜单栏点击【view】->【Memory Windows】->【Memory1】,在【Address】地址栏中输入SP的值 0x200019A8,然后查看堆栈里面的值依次是 R0~R3、R12、R14(LR)、PC、XPRS。

------------------------------------- 图 4 -------------------------------------
显然堆栈后第21个字节到24字节即为LR,图4显示该地址为0x08008263 即为异常前PC将要执行的下一条指令地址。

③ 找到将要执行下一条指令的位置

在Keil菜单栏中点击【view】->【Disassembly Window】,在【Disassembly Window】窗口中右击,在下拉菜单中选择【Show Disassembly at Address...】。在弹出框【Show Code at Address】的地址框中输入地址 0x08008263 进行搜索,然后就会找到相对应的代码。

------------------------------------- 图 5 -------------------------------------

方法2

① 在中断函数HardFault_Handler里的while(1)处打个断点


------------------------------------- 图 6 -------------------------------------

② 返回到出错的函数位置

在Keil菜单栏点击【view】->【Call Stack Window】,弹出【Call Stack + Locals】对话框,右键点击对话框中的【HardFault_Handler】,选择【Show Caller Code】,就会跳到出错的函数位置。

------------------------------------- 图 5 -------------------------------------

posted on 2020-11-07 17:09  J斌(´・ω・`)  阅读(6114)  评论(3编辑  收藏  举报