单片机bug调试- HardFault_Handler硬件中断调试解决

#单片机bug调试- HardFault_Handler硬件中断调试解决

目录

[1. HardFault_Handler中断产生的主要原因](#1. HardFault_Handler中断产生的主要原因 "#T_lable1")
[2. HardFault_Handler 关键寄存器说明](#2. HardFault_Handler 关键寄存器说明 "#T_lable2")
[3. 分析HardFault_Handler硬件中断一般步骤](#3. 分析HardFault_Handler硬件中断一般步骤 "#T_lable3")

1. HardFault_Handler中断产生的主要原因

HardFault_Handler硬件中断,是单片机中经常出现的一种异常问题。出现 HardFault_Handler 的原因主要有3类:

  • 内存溢出或者访问越界:由于程序中申请的内存超出了系统的可用内存,或者申请的内存在使用过程中未被正确释放。这种情况会导致系统无法为其他请求分配足够的内存,甚至可能导致系统崩溃。访问了数组范围之外的内存位置或使用野指针,也会导致HardFault_Handler错误。
  • 堆栈溢出:通常发生在函数调用或数组访问时。当函数内部的数组过大,或者递归调用层次太深时,就可能发生堆栈越界。
  • 硬件故障:如果硬件出现故障,例如电源干扰、连接器故障或传感器故障等,可能会导致HardFault_Handler错误。

在单片机的HardFault_Handler 异常处理中,不同的单片机系列处理机制可能会有所不同,这取决于具体的MCU系列和其内部架构,需要看对应的内核手册。 不过STM32系列的异常处理机制大致相似,按照本文方法若不能解决问题,就需要详细查看对应的内核手册(R13、R14、R15的作用)。

2. HardFault_Handler 关键寄存器说明

出现HardFault异常时,会进入HardFault_Handler中断处理程序。此时,MSP和PSP有两个特殊的寄存器,它们用于存储堆栈指针,帮助开发者定位和解决问题。

2.1 MSP寄存器(主堆栈指针)

主要用于非中断相关的操作,如主程序运行、用户任务等。

  • 在异常处理过程中,MSP作为栈顶指针使用(主堆栈的初始地址),用于保存和恢复异常发生时的寄存器值。
  • 在正常处理过程中,MSP用于临时存储数据、保存函数调用时的参数等。

2.2 PSP寄存器(进程堆栈指针)

主要用于嵌套中断处理和多任务环境。

  • 在嵌套中断处理中,PSP用于保存和恢复中断前的堆栈环境,以便中断处理程序能够正确地执行。
  • 在多任务环境中,每个任务都有自己的PSP,用于保存任务的上下文(如CPU寄存器),以便任务切换时能够正确地恢复执行。
  • 其它正常情况下,PSP也可以用于其他需要临时存储数据的场景。

当发生异常时内核将R0、R1、R2、R3、R12、Returnaddress、PSR、LR寄存器依次入栈到MSP或PSP,以保存当前执行的上下文。

地址解释:

  • R0、R1、R2、R3:通用寄存器,通常用于传递参数和保存临时数据;
  • R12: 这也是一个通用寄存器,用于保存临时数据;
  • Returnaddress: 保存了当前函数调用后的地址,这通常是指发生异常前将要执行的指令的地址;
  • PSR (Program Status Register):程序状态寄存器,保存了CPSR的当前值;
  • LR (Link Register): 链接寄存器,保存了异常发生前的返回地址。

异常时,内核将当前执行的上下文数据按特定顺序入栈到堆栈指针,只要我们找到Returnaddress地址的位置,就可定位到出现异常的大致位置。查看保存有异常数据的堆栈指针是MSP,还是PSP,需要根据R14(LR)的数值而定。

3. 分析HardFault_Handler硬件中断一般步骤

Coretex-M3和Coretex-M4架构中,R14(LR)数值及其代表含义:

  • LR = 0xFFFFFFF9,MSP指向的地址保存有异常信息;(使用FPU时,LR=0xFFFFFFE9)
  • LR = 0xFFFFFFFD,PSP指向的地址保存有异常信息;(使用FPU时,LR=0xFFFFFFED)
  • LR = 0xFFFFFFF1,表示中断返回时从MSP堆栈恢复寄存器值,中断返回后进入Handler模式,使用MSP堆栈;(使用FPU时,LR=0xFFFFFFE1)

以下使用Coretex-M3内核架构,进行异常分析,

3.1 保护现场:

出现异常时,不要复位设备,保持当前设备运行的异常环境,能更大概率找到问题。若开启了看门狗,超时就会硬件复位,要复现并找到该问题,需要将看门狗进行关闭并重新烧写程序,等待问题复现。

3.2 使用KEIL进入Debug调试

若进入调试界面后,没有 Registers 窗口,就点击KEIL-->View-->Registers Windown 就会弹出该窗口。

3.3 Registers 窗口查看R14(LR),确认保存异常数据的堆栈指针

3.4 在Memory1窗口 查看栈帧内容

Memory1 窗口未显示,就点击KEIL-->View-->Memory Windowns-->Memory1 就会弹出该窗口。

3.5 使用 Disassembly Window 反汇编窗口 定位异常区域

Disassembly 反汇编窗口未显示,就点击KEIL-->View-->Disassembly Windown 就会弹出该窗口。

通过MSP堆栈指针指向的地址0x20002B10 记录的上下文信息,查找Returnaddress地址定位到异常程序代码处,可分析出产生HardFault_Handler中断的原因 是由于函数内部数组 buf[50] 只有50个字节大小,但使用buf时操作了100个字节大小,导致了数组越界错误。

3.6 LR寄存器等于其它值

LR寄存器保存了异常发生时的返回地址。如果由于外部信号干扰或电源问题导致异常,这个返回地址可能不准确或MSP的值与预期的函数堆栈位置不匹配,这可能表明异常发生时堆栈已经被破坏。需结合窗口工具 KEIL-->View-->Call Stack ,KEIL-->Peripherals-->Core Peripherals-->Fault Reports 进行具体异常分析。

配置KEIL进行在线调试的参考链接: blog.csdn.net/weixin_4317...

针对某些 xxx.uvprojx 工程,在使用KEIL进行Debug在线调试时,打了断点,当退出调试时KEIL会卡死,需要使用任务管理器强制结束任务才能退出。

出现该问题的原因是,xxx.uvprojx 工程建立不是在本电脑上创建的,是从其他电脑拷贝到本电脑编译运行调试的,存在的配置文件与本电脑不匹配; 或工程路径里面存在中文路径。解决措施:

  • 关闭KEIL工程,拷贝一份工程出来并重命名,路径中不包含中文;

  • xxx.uvprojx 同目录下,删除文件 xxx.scvdxxx.uvguix.Administratorxxx.uvguix.zuozhxxx.uvoptx注意不要删除 xxx.uvprojx ;

  • 打开 xxx.uvprojx 工程,进入Target 界面重新对该工程进行配置,并 Rebuild 编译;

相关推荐
智商偏低2 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen3 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森5 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白5 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D5 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术8 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt9 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘9 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang9 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n12 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件