单片机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 编译;

相关推荐
bai_lan_ya4 分钟前
stm32定时器中断和外部中断
stm32·单片机·嵌入式硬件
玄奕子21 分钟前
GPT对话知识库——在STM32的平台下,通过SPI读取和写入Flash的步骤。
stm32·单片机·gpt·嵌入式·嵌入式驱动
夜间去看海1 小时前
基于单片机的温度和烟雾检测
单片机·嵌入式硬件·温度烟雾
星汇极客1 小时前
【星汇极客】单片机竞赛之2024睿抗机器人大赛-火线速递赛道(持续更新)
stm32·单片机·嵌入式硬件·机器人
嵌联驰2 小时前
【S32K3 RTD MCAL 篇1】 K344 KEY 控制 EMIOS PWM
单片机
Daemon.Chen2 小时前
【STM32开发之寄存器版】(五)-窗口看门狗WWDG
stm32·单片机·嵌入式硬件
嵌入式杂谈4 小时前
STM32中断编程详解:配置外部中断和中断服务例程
stm32·单片机·嵌入式硬件
光子物联单片机5 小时前
传感器模块编程实践(三)舵机+超声波模块融合DIY智能垃圾桶模型
stm32·单片机·嵌入式硬件·mcu
嵌入式杂谈7 小时前
STM32中断编程指南:NVIC和中断优先级
stm32·单片机·嵌入式硬件
xiaobuding_QAQ8 小时前
自用Proteus(8.15)常用元器件图示和功能介绍(持续更新...)
单片机·嵌入式硬件·学习·proteus