STM32硬件错误进入HardFault_Handle()函数的解决办法
本文章是为了解决程序异常运行时进入HardFault_Handle()函数的解决办法。我将从发现问题到如何解决问题全过程描述清楚。方便在项目过程中遇到相似问题的同行做参考使用。
项目背景:为了实现同时给多块大疆无人机T60电池充电的功能,多电池充电可以实现无人机不间断作业,由于大疆电池箱卖得属实昂贵,所以决定自己做一个优于大疆电池箱的充电管理产品。
问题描述:当电池插入的时候程序异常进入HardFault_Handle()函数导致程序死机,这种异常是程序无法挽回的异常,如果产品没有特殊要求在这个函数里面可以让软件重启来解决当前问题。但是这种解决问题的方法治标不治本。如果遇到一些产品是不能让程序自动重启那么这种方法是不可行的。
解决过程:刚开始我也为是硬件干扰导致的,因为我在硬件IO口检测处与MCU直连,中间就加了一个防阻尼电阻,IO口处没有加去耦电容。
电路如下图:
于是我在以上电路的基础加了信号隔离,因为电池插入的时候只有这几个IO口和MCU直连的,所以我怀疑问题出在这里,我用示波器测量插入电池的时候信号也确实有一个尖峰信号,但没有超过IO口承受的最大值,所以怀疑是硬件这里的问题。
电路如下图:
当PCB打样回来我重新测试的时候发现问题还是会复现,程序异常进入HardFault_Handle。所以问题大概率不在硬件上面,那么软件出错的概率就变大了,但是程序进入HardFault_Handle主要有以下两个原因导致:
- 内存溢出或者访问越界。
- 堆栈溢出。
于是我在程序中修改堆栈的大小来测试是否是堆栈溢出导致。下图是默认值,将堆栈改大。
修改完之后发现问题依然存在,那么就不是堆栈溢出导致。那么就只能进入仿真查找问题,就是在HardFault_Handle()函数打一个断点,然后程序停止的时候看SP指针的地址是多少。
然后再内存中查看当前地址的值,在查找地址前面要加上0X因为是16进制。
1.在汇编区域单击右键然后选择 Show Disassembly at Address
2.在输入SP指针地址里面以08开头的地址
如下图
这个段地址就是程序进入前或者进入后的地址,如果一个地址不是那么继续往后搜索内存中是低位在前,而搜索时候要高位在前地址前都要加0X,而且地址是4个字节(32位机)。如图:
然后就会跳到地址所在的函数。汇编区域会显示程序地址然后看函数是否有内存溢出或者访问越界。
我发现这个函数如果形参len小于2的时候那么就会导致内存访问越界,然后导致异常中断。这是自己程序不严谨导致的错误,然后再程序中加上一些容错处理后在测试,发现问题解决不会进HardFault_Handle()函数。
当成程序进入HardFault_Handle()异常中断因该首先考虑是否是
- 内存溢出或者访问越界。
- 堆栈溢出。
作者:硬核笔记