STM32 产生Hard Fault 调试方法

STM32 产生hard-fault 调试方法

需求

当STM32 产生Hard Fault的时候我们希望可以打印出一些重要的寄存器信息,然后定位代码出错的地方。

参考

https://github.com/ferenc-nemeth/arm-hard-fault-handler

原理

STM32代码运行的时候一般在是main函数while(1)中循环的运行代码,在运行代码的过程中突然发生了Hard Fault错误,则会产生一个中断。中断产生的时候CPU会将一些重要的寄存器压入栈中,这个动作是CPU自动运行的,无需代码控制。那么我们就可以在中断的服务函数里面获取栈的地址,然后将重要的寄存器信息打印出来即可。

备注:STM32有两个栈指针,分别是MSP和PSP,所以在HardFault_Handler中需要判断产生中断之前使用的是MSP还是PSP。

下面是核心代码。
void HardFault_Handler(void)
{
  __asm volatile
  (
      "TST    LR, #0b0100;      "
      "ITE    EQ;               "			   //判断堆栈指针使用的是MSP还是PSP。
      "MRSEQ  R0, MSP;          "              // 如果是MSP则将MSP的值放在R0,作为ReportHardFault函数的第一个参数。
      "MRSNE  R0, PSP;          "			  // 如果是MSP则将MSP的值放在R0,作为ReportHardFault函数的第一个参数。
      "MOV    R1, LR;           "			    // 将LR的值放在R1寄存器,作为ReportHardFault函数的第二个参数。
      "B      ReportHardFault;  "             //跳转到ReportHardFault函数,在这个函数可以打印出产生hard fault时候的堆栈信息。
  );
}

备注:
1、LR保存的是产生中断的时候CPU下一步要执行的指令,可以通过使用 BX LR 指令返回,这会触发硬件恢复之前保存的上下文。
2、在STM32中,产生中断的时候,CPU会将一些重要的寄存器数据压入堆栈中,这些寄存器是r0、r1、r2、r3、r12、lr、pc、psr。
所以我们HardFault_Handler中断函数中第一时间就获取SP的值,从而找到产生中断的时候堆栈的指针的值是多少,
从而打印出产生Hard Fault时候代码运行到那里。

void ReportHardFault(uint32_t *stack_frame, uint32_t exc)
{
  uint32_t r0   = stack_frame[0];			//备注:stack_frame是产生中断的时候,将重要的寄存器压栈后的地址。
  uint32_t r1   = stack_frame[1];
  uint32_t r2   = stack_frame[2];
  uint32_t r3   = stack_frame[3];
  uint32_t r12  = stack_frame[4];
  uint32_t lr   = stack_frame[5];
  uint32_t pc   = stack_frame[6];
  uint32_t psr  = stack_frame[7];
  
  uint32_t hfsr = SCB->HFSR;     //这是重要的错误寄存器信息,可以查找数据手册知道产生什么错误。
  uint32_t cfsr = SCB->CFSR;
  uint32_t mmar = SCB->MMFAR;
  uint32_t bfar = SCB->BFAR;
  uint32_t afsr = SCB->AFSR;

 //下面的代码将堆栈的信息打印出来。
}

背景知识补充

MSP 和 PSP

在 STM32 微控制器中,MSP(Main Stack Pointer)和 PSP(Process Stack Pointer)是两个用于管理堆栈的指针。它们是 ARM Cortex-M 处理器架构的一部分,用于在不同模式下进行堆栈操作管理。

MSP(Main Stack Pointer)

MSP(Main Stack Pointer) 是主堆栈指针。

通常用于系统模式或特权模式下的堆栈操作。

在复位后,处理器默认使用 MSP 作为堆栈指针。

一般情况下,操作系统或裸机程序中的中断服务程序和异常处理程序使用 MSP。

PSP(Process Stack Pointer)

PSP(Process Stack Pointer) 是进程堆栈指针。

通常用于用户模式或线程模式下的堆栈操作。

在使用操作系统(例如 FreeRTOS)时,每个任务或线程可以使用 PSP 进行独立的堆栈管理,从而实现任务的隔离。

PSP 允许应用程序在不同的模式下使用不同的堆栈,提供更好的灵活性和安全性。

相关推荐
析木不会编程1 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉5 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名6775 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普6 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣6 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室6 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费6 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
qq_397562318 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
liyinuo20178 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
艺术家天选9 小时前
STM32点亮LED灯
stm32·单片机·嵌入式硬件