STM32 HardFault 调试定位

Cortex-M3/M4/M7 Fault Exceptions

问题的产生

无论是在什么平台,什么环境下写代码,都免不了利用一些工具去调试Bug。诸如在Windows下利用vs开发,会使用IDE集成的调试器,或者在linux下进行C开发,使用gdb打印段错误的栈信息。而使用Keil进行嵌入式编程的时候,我们也会遇到很多诸如‘段错误’的情况,这个时候我们就需要利用环境的工具去了解发生了什么样的问题,然后定位问题发生的位置,并解决问题。

理论背景

大部分嵌入式设备使用的STM32芯片采用的都是Cortex-M3核,架构采用错误异常的机制来检测问题,当核心检测到一个错误时,异常中断会被触发,并且核心会跳转到相应的异常终端处理函数执行,错误异常的终端分为以下四种:

  1. HardFault
  2. MemManage
  3. BusFault
  4. UsageFault

锁定问题的位置

区分这些错误对问题的解决意义不大(一般的情况下默认的配置只会开启HardFault错误)。举个例子,当你手写了一个双向链表去动态申请空间存储你的业务信息,结果你发现程序刚在板子上在线仿真就死了的时候,你心里清楚肯定是你的代码哪里有了问题,只是你想知道代码是死了在哪里。你暂停程序执行之后,你会发现程序进入了下边的中断处理程序:

>void HardFault_Handler(void)
>{
>  /* Go to infinite loop when Hard Fault exception occurs */
>       while (1)
  		{
  		}
>}

这个时候我们按照正常的调试步骤,去菜单栏View中找到Call Stack Window,打算看看自己bug的位置的时候,却赫然发现Call Stack中只有HardFault_Handler一个函数的栈信息。从View中打开Registers Window,可以看到LR的值为0xFFFFFFF9,显然这是一个非法的值,IDE无法通过这个地址还原到上一级的代码段,所以显示的只有当前函数的信息,因为Cortex-M3的堆栈寄存器是banked,所以观察LR的Bit[2]位,其为0,所以当前的堆栈指针用的是MSP,点开View中的Memory Windows,将MSP的地址输入Address文本框,根据下图中找到在异常之前压入栈的信息:
在这里插入图片描述
找到LR,在汇编的视图右键打开Show Disassembly at Address,输入从堆栈中找到了LR寄存器内的地址信息,往上退一个指令,或者就是这个指令导致了程序进入了异常。

原创文章 21 获赞 29 访问量 2万+

猜你喜欢

转载自blog.csdn.net/geek_liyang/article/details/83510518