单片机bug调试:解决HardFault_Handler硬件中断问题的方法

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

目录

  1. HardFault_Handler中断产生的主要原因
  2. HardFault_Handler 关键寄存器说明
  3. 分析HardFault_Handler硬件中断一般步骤

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进行在线调试的参考链接

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

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

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

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

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

  • 物联沃分享整理
    物联沃-IOTWORD物联网 » 单片机bug调试:解决HardFault_Handler硬件中断问题的方法

    发表评论