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

相关推荐
louis.D.5 分钟前
Git 本地单线速查
单片机
小李不想当小白27 分钟前
PCB结构与组成(PCB设计入门学习笔记)
经验分享·笔记·单片机·嵌入式硬件·学习·pcb工艺·pcb
新晨单片机设计1 小时前
S004R-基于STM32单片机智能门禁系统(密码、指纹、人脸、刷卡、蓝牙)【Proteus仿真+Keil程序+原理图】
stm32·单片机·嵌入式硬件·proteus
至为芯1 小时前
PY32F071至为芯支持32位ARM内核的高主频MCU单片机
单片机·集成电路·芯片
桀人1 小时前
MCU系统架构——总线——统一编址
stm32·单片机·嵌入式硬件
可乐鸡翅好好吃2 小时前
通讯协议--硬件模拟和软件模拟
stm32·嵌入式硬件
Zw-awa2 小时前
STM32F103C8T6 最小系统板:从型号差异到启动方式
stm32
新思维软件2 小时前
基于边缘计算与多模态感知的服药依从性系统|X604261
嵌入式硬件·物联网开发
朝发如雪11 小时前
快速掌握单片机基础(3)(PWM)(通信协议基础)(串口通信时序与参数)(电气特性与电平标准)(51单片机UART寄存器配置)(串口应用层协议)
单片机
天空'之城13 小时前
单片机基础核心知识点汇总(四十)
单片机·嵌入式硬件