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

相关推荐
代码游侠12 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
xuxg200515 小时前
4G 模组 AT 命令解析框架课程正式发布
stm32·嵌入式·at命令解析框架
CODECOLLECT16 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen17 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠19 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_19 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技1 天前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计1 天前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
風清掦1 天前
【江科大STM32学习笔记-05】EXTI外部中断11
笔记·stm32·学习
小龙报1 天前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机