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 允许应用程序在不同的模式下使用不同的堆栈,提供更好的灵活性和安全性。

相关推荐
某林2122 小时前
ROS2与STM32通信详解
stm32·单片机·嵌入式硬件
EVERSPIN4 小时前
MCU微控制器,N32H47x高性能MCU机器人关节控制方案
单片机·嵌入式硬件·机器人·mcu微控制器
0南城逆流04 小时前
【STM32】知识点介绍三:哈希算法详解
stm32·嵌入式硬件·哈希算法
云山工作室4 小时前
基于STM32单片机的正激式开关电源设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·课程设计·毕设
芯希望5 小时前
芯伯乐700mA线性稳压器XBLW L78M05H/L78M12H:稳定可靠,简化电源设计
单片机·嵌入式硬件
lingzhilab6 小时前
零知IDE——STM32F407VET6驱动SHT40温湿度传感器与ST7789实现智能环境监测系统
stm32·单片机·嵌入式硬件
贝塔实验室7 小时前
Altium Designer 6.3 PCB LAYOUT教程(四)
驱动开发·嵌入式硬件·硬件架构·硬件工程·信息与通信·基带工程·pcb工艺
星辰pid8 小时前
stm32的gpio模式到底该怎么选择?(及iic,spi,定时器原理介绍)
stm32·单片机·嵌入式硬件
brave and determined9 小时前
可编程逻辑器件学习(day3):FPGA设计方法、开发流程与基于FPGA的SOC设计详解
嵌入式硬件·fpga开发·soc·仿真·电路·时序·可编程逻辑器件
axuan126519 小时前
10.【NXP 号令者RT1052】开发——实战-RT 看门狗(RTWDOG)
单片机·嵌入式硬件·mcu