关于stm32 HardFault_Handler 异常的处理死机

本文介绍了RTOS系统中出现死机及HardFault_Handler硬件异常的原因及排查方法。总结了四大常见问题:堆栈分配不足、数组溢出、非法指针使用及临界区管理不当,并提供了调试步骤和预防措施。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在系统开发的时候,出现了HardFault_Handler硬件异常,也就是死机,尤其是对于调用了os的一系统,程序量大,检测堆栈溢出,以及数组溢出等,找了半天发现什么都没有的情况下,估计想死的心都有了。如果 有些程序开始的时候一切没有问题,但是运行几个小时候,会发现死机了,搞个几天下来估计蛋都碎了一地吧。。。
一般来说运行操作系统   是以下几个问题
1.开始的时候给ucos分配的堆栈太小了,随着项目做多了,这类问题一般很容易解决
#define TASK_IO_SIZE   300
#define TASK_IO_PRIO 6
OS_STK   TASK_IO_STK[TASK_IO_SIZE];
比如修改300到 1000,做开发的时候 如果ram允许,尽量大些,免的麻烦

2.数组溢出
这类问题一般在通信中,接受数据的时候,特别是长度不定的时候
比如协议为       :开始   功能码   长度   数据1   数据2 。。结束
长度决定了后面的数据多少,在分配接受缓冲的时候    ,突然来了个错误的长度比如255
但是我们分配buffer[100],只定义了100,这样数组就溢出了 
所有在放数据之前要对长度进行判断是否合理,以后 如果有长度 或者索引就要想到溢出。。

3.使用了非法的指针 ,比如空指针 ,编译对的 但是运行就错了
u8 *p = null;
*p = 1;            把0地址的数据强制设置为1,   不错才怪

4.使用 OS_ENTER_CRITICAL();
使用了 OS_ENTER_CRITICAL(); 却忘了OS_EXIT_CRITICAL(); 退出临界区
特别是在这个函数OS_ENTER_CRITICAL();   调用了子函数 也有的这类情况,很容易忘记关闭的这样就造成了“死机现象”
因此如果调用的话   建议在函数中加入OS_CPU_SR   cpu_sr = 0u;局部变量 在管理临界区    os的内核程序也是这么用的   ,而且要注意,临界区一般用于全局变量的写操作,时间要非常快的,任务中的变量可以不用添加 。

常见的就上面几种了,说说硬件异常了 怎么来发现,这个才是主要的
举个例子:
a.仿真,运行程序的时候点红色X进入异常
关于stm32 <wbr> <wbr>HardFault_Handler <wbr>异常的处理 <wbr>死机,估计这是网上最全的吧

b.调出堆栈窗口,也就是黑匣子
关于stm32 <wbr> <wbr>HardFault_Handler <wbr>异常的处理 <wbr>死机,估计这是网上最全的吧

c.查找问题
关于stm32 <wbr> <wbr>HardFault_Handler <wbr>异常的处理 <wbr>死机,估计这是网上最全的吧

d.找出出错的函数
关于stm32 <wbr> <wbr>HardFault_Handler <wbr>异常的处理 <wbr>死机,估计这是网上最全的吧

e.解决问题
关于stm32 <wbr> <wbr>HardFault_Handler <wbr>异常的处理 <wbr>死机,估计这是网上最全的吧

f   一些思考
很久之前在研究stm32 库源码的时候   发现基本上   每个函数进入之前都做了参数的检测,当初还觉得检查不检查貌似没什么大的作用,自己使用的时候注意就好了,现在是不是改变看法了吗?编程的时候很多问题,在参数检查的时候被过滤掉了,这样在开发大型项目的时候,可以给您免去很多不必要的麻烦,反而会提供开发效率哦

当然网上也有很多,检查寄存器LR SP等地址 来反推出最后运行的汇编函数调用地址的,但是肯定没有上面的直观。
### STM32 运行死机的原因及解决方案 #### 一、硬件与时钟配置问题 STM32 死机的一个常见原因是硬件配置不当,特别是时钟设置不正确。如果芯片主时钟未开启或时钟晶振配置与实际使用的晶振不符,则可能导致系统不稳定甚至死机[^2]。 为了防止此类情况发生,建议仔细核对并按照官方文档中的指导完成时钟树的初始化工作。确保所选外部晶体频率匹配数据表规定范围,并通过调试工具验证PLL输出稳定可靠。 #### 二、堆栈溢出引发异常 另一个容易被忽视的因素是由于过度分配局部变量而导致的堆栈溢出现象。当应用程序尝试创建过大的数组或其他大型对象时,可能会超出默认设定好的栈空间界限(对于某些型号而言,默认值可能是1KB),从而触发HardFault中断处理函数(HardFault_Handler)[^3]。 针对这个问题的有效措施包括但不限于: - **优化全局/静态变量声明位置**:尽量减少大尺寸的数据结构放在函数内部作为自动变量; - **调整链接脚本中Stack Size参数**:根据项目需求适当增加可用堆栈容量; ```c /* 修改Linker Script (.ld 文件) 中 Stack_Size 定义 */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 20K /* Adjusted size here */ } ... __stack_size = DEFINED(__STACK_SIZE__) ? __STACK_SIZE__ : 0x500; /* Example value */ ``` - **启用浮点单元(FPU)**:如果是基于Cortex-M系列MCU开发且涉及大量浮点运算的话,请确认已使能相应外设支持以避免不必要的额外开销影响性能表现。 #### 三、软件层面潜在缺陷排查 除了上述两点之外,还有许多因素也可能引起STM32设备无响应的状态,比如无限循环等待事件、资源竞争条件等并发编程陷阱。因此强烈推荐开发者深入学习目标平台架构特性及其配套库API用法的同时也要掌握基本故障诊断技巧,如利用串口打印日志辅助定位具体卡顿环节所在之处。 另外值得注意的是,在编写固件代码之前应当充分理解ARM Cortex内核的工作原理以及各类异常向量表项的作用机制,这有助于快速识别并修复由非法指令执行等原因造成的崩溃状况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值