遇到hardfault怎么办?

文章目录

  • [HardFault 分析教程](#HardFault 分析教程)
    • [1. 定位HardFault产生的位置](#1. 定位HardFault产生的位置)
      • [1.1 先修基础知识](#1.1 先修基础知识)
      • [1.2 C语言版本](#1.2 C语言版本)
      • [1.3 汇编语言版本](#1.3 汇编语言版本)
      • [1.4 操作方法](#1.4 操作方法)
    • [2. 分析HardFault原因](#2. 分析HardFault原因)
      • [2.1 Chinese version](#2.1 Chinese version)

HardFault 分析教程

Teach you how to locate HardFault and analyze its causes(教你如何定位HardFault,并分析HardFault的原因)

1. 定位HardFault产生的位置

操作方法:把你的void HardFault_Handler(void) 替换成下摆你这段代码,然后在hardfault处打断点,单步执行就可以找到问题原因处

1.1 先修基础知识

参考文档-HardFault定位方法


总结:根据单片机进中断,寄存器压栈情况,压栈时候把LR寄存器值(存储着返回来要执行的程序地址)也压进去了,那只需要在hardfault ISR里边把LR值取出来赋值给PC就可以定位到引发hardfault的地方,如下面操作,不过这个只是定位到了引发hardfault的位置,下一步还需要结合hradfault状态寄存器分析产生的具体原因

1.2 C语言版本

注意!! 下边的MSP值+0X1C为存 LR的值,这个不同核心单片机有区别,M3核的理论上来说加0X14就可以了,但是M0核得+0x1C,实践得出来的结果

c 复制代码
// Return the R13(Stack Pointer)
__ASM unsigned int __Get_SP_Value(void)
{
    mov r0, r13 //R13(SP)
    bx lr
}

void (*f1)(void);
unsigned int result;

void HardFault_Handler(void)
{
    //实际操作Arm Coretex-M0核心的是+0x1C,M3核的是+0X14
    result = __Get_SP_Value()+0x14;
    f1 = *( (unsigned int*)result );
    f1();
    while (1);
}

1.3 汇编语言版本

注意!! 下边的MSP值+0X1C为存 LR的值,这个不同核心单片机有区别,M3核的理论上来说加0X14就可以了,但是M0核得+0x1C,实践得出来的结果

armasm 复制代码
;把你的起始.s文件内的HardFault_Handler代码换成下边这个

HardFault_Handler\
                PROC
                add   r0, sp, #0x14     
                ldr   r1, [r0]          
                blx   r1                
                B       .
                ENDP

1.4 操作方法

当产生了hardfault后,选择上述1.2或者1.3的代码方案后,debug 在hardfult处打断点执行到hardfault ISR处之后再单步执行,就可以找到出问题的地方了


2. 分析HardFault原因

分析产生HardFault的原因(需要具体代码具体分析仔细崩溃处的代码的问题)

hardfault产生的原因有很多,例如访问非法地址了,函数指针变量为NULL,然后直接运行了,总共包含以下几种

  1. 内存访问错误
  • 访问了未映射的内存区域。

  • 对只读内存区域执行写操作。

  • 访问了无效的内存地址(如NULL指针解引用)。

  1. 堆栈溢出:
  • 如果任务或中断的堆栈空间不足,可能导致堆栈溢出,进而破坏内存或触发HardFault。
  1. 未对齐的内存访问:
  • 某些STM32系列要求特定的数据类型在内存中对齐。未对齐的访问可能触发HardFault。
  1. 错误的异常处理:
  • 如果在异常处理程序中再次发生异常,且没有正确处理,可能会导致HardFault。
  1. 中断优先级配置错误:
  • 如果配置了错误的中断优先级,可能导致不可屏蔽中断(NMI)或HardFault。
  1. 非法指令或状态:
  • 执行了未定义的指令。

  • 尝试切换到无效的处理器模式。

  1. 外设配置错误:
  • 错误地配置或使用了外设,如未启用时钟就访问外设寄存器。
  1. 电源问题:
  • 不稳定的电源可能导致处理器行为异常,从而触发HardFault。
  1. 软件错误:
  • 逻辑错误、数组越界、类型转换错误等编程错误也可能导致HardFault。

但是这些太笼统了,太废话了,具体是哪个呢?? 那还得看HardFault状态寄存器(HFSR)以及其他相关的故障状态寄存器,如配置管理故障状态寄存器(CFSR)、内存管理故障状态寄存器(MMFSR)、总线故障状态寄存器(BFSR)和使用故障状态寄存器(UFSR)。

下图是HardFault状态寄存器,引发hardfault了可以看看这个寄存器值,然后再仔细检查下代码


2.1 Chinese version

相关推荐
XiaoLeisj18 分钟前
【MyBatis】深入解析 MyBatis XML 开发:增删改查操作和方法命名规范、@Param 重命名参数、XML 返回自增主键方法
xml·java·数据库·spring boot·sql·intellij-idea·mybatis
dleei1 小时前
MySql安装及SQL语句
数据库·后端·mysql
信徒_1 小时前
Mysql 在什么样的情况下会产生死锁?
android·数据库·mysql
嘴对嘴编程2 小时前
oracle数据泵操作
数据库·oracle
·薯条大王8 小时前
MySQL联合查询
数据库·mysql
morris13110 小时前
【redis】redis实现分布式锁
数据库·redis·缓存·分布式锁
hycccccch11 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
这个懒人11 小时前
深入解析Translog机制:Elasticsearch的数据守护者
数据库·elasticsearch·nosql·translog
Yan-英杰12 小时前
【百日精通JAVA | SQL篇 | 第二篇】数据库操作
服务器·数据库·sql
NineData12 小时前
NineData云原生智能数据管理平台新功能发布|2025年3月版
数据库