STM32关于我遇到的HardFault_Handler的处理

前言

最近都没怎么写博客,主要原因是新赛季了得上分,从今天开始,博客恢复正常更新

关于HardFault_Handler

为什么会产生HardFault_Handler

这个错误的产生原因有
1.由调试事件触发
2.由总线错误,存储器管理错误或使用错误而产生
这个错误的产生是由于HardFault寄存器状态发生改变所导致,这两个原因看上去说的很玄乎,实际上这个问题大家应该都不陌生,最常出现这个问题的原因一般是数据越界啦,堆栈溢出啦,等等,解决的方法网上也有不少,但是很多都没有解决掉我当时的问题,不得不说这个BUG真的是秒啊。

出现HardFault_Handler怎么办

遇到之后没有必要手忙脚乱,这个问题其实并不难解决,因为HardFault_Handler的存在意义并不是为了让你的程序卡死,而是为了帮助你解决程序的问题,可以按照以下步骤进行
1.找到IDE的Registers界面,keil和STM32CUBEIDE都有该界面,GDB有没有我不太清楚,不过GDB我记得是也是可以查看LR的值的
2.然后查看LR寄存器的值,该寄存器只有六种值是正常情况,具体可参考M4权威指南193页。这里给出一个表格

LR寄存器的值意义
0xFFFFFFF9或者0xFFFFFFE9线程在使用主栈时,LR寄存器被设置为EXC_RETURN
0xFFFFFFFD或者0xFFFFFFED线程在使用进程栈时,LR寄存器被设置为EXC_RETURN
0xFFFFFFF1或者0xFFFFFFE1无法判断主栈还是进程栈,但一定是发生了中断嵌套才产生的

在这里插入图片描述

需要注意的是,进入HardFault_Handler错误处理的原因并不是LR寄存器导致的,而是HardFault寄存器导致的,LR只是在发生错误前进行现场保存而已。LR寄存器只是我们查询问题所在的“指路器”
当问题是在中断处理导致的时候,LR寄存器的值为0xFFFFFFF9或者0xFFFFFFE9时(也就是上述表格的前两种情况),问题是在由中断事件到中断处理的过程中产生的,而在值为0xFFFFFFF1或者0xFFFFFFE1 的时候,问题是在中断处理被另一中断打断时才发生的,所以才会认为LR的值为0xFFFFFFF1或者0xFFFFFFE1 的时候一定是发生了中断嵌套。下图是M4指南第194页的说明(日常拍照敷衍)。

日常懒得搞图之我直接拍照
3.根据LR的寄存器的值判断是主栈还是线程栈导致的问题,,如果是主栈就继续查看MSP寄存器,如果是进程栈,那么久查看PSP寄存器。
在这里插入图片描述

4.根据MSP寄存器或者PSP寄存器的记录,将其值在编译器的Memory Browser中查看其具体地址,一般是0x80开头的
在这里插入图片描述

5.打开Disassembly,在里面可以找到具体是哪一行代码导致的该问题。
这样就可以查到到底是哪一行出现了问题。
在这里插入图片描述

以上处理方法在网上很多博主都有提及,所有的界面都可以在STM32cubeide的Windows->show view->other里面找到。但是这种处理只能处理前两种情况,第三种情况LR寄存器的值为0xFFFFFFF1的时候是不太有效的,这时候就需要自己去查一下中断嵌套了。
在这里插入图片描述

我遇到的HardFault_Handler

我再进行FLASH读写功能的模块一直没有出现问题,但最近移植进了一个新的功能模块后,只要进行flash的读写就会卡死在HardFault_Handler,我按照上述步骤查询到LR的值为0xFFFFFFF1,这种情况是因为我们在FLASH读写时没有关闭总中断导致的,至于之前为什么没问题我也不是很清楚,所以我们可以在加上总中断后问题本该是解决的,但是我已然进入到了HardFault_Handler里。
不过这并不是之前的中断嵌套问题没有解决,而是因为在移植进新的模块后,有两个地方都会导致HardFault_Handler。
在这个时候我再次查看LR寄存器的值,此时他的值已经有0xFFFFFFF1变为了0xFFFFFFFD,于是我对问题进行了定位,可是定位到的语句只是一句memcpy函数,并且程序在没有移植新模块是该函数也从没有发生越界,当时搞的我一头雾水,难道是HardFault_Handler出现问题了吗?于是只能把问题定位在了sram越界上,我们知道ST的SRAM是分为连续两块的,如过一个结构体存储跨过了这两块的分界线,也是会报越界的,但是很遗憾,经过计算后,我的SRAMd的最终地址是在45k的位置,并没有到达48k,那么问题到底出在哪里呢?
后来通过单步调试发现,确实是卡死在memcpy函数,但是是传递第一组64字节数据的时候就直接卡死,如果是SRAM越界的话,那么必定是运行一段时间后才会发生越界。所以一定是一开始就发生了问题。
最后问题查明是因为新模块移植后,由于代码量增大,代码在所占空间上涨了40k,导致写入FLASH的起始地址已经处在了代码的存储区,从而导致了越界错误,修改了FLASH的起始地址后,卡死问题也就解决了。

教训

以后写FLASH存储的时候,应该从后往前写,如果发现要写入的FLASH地址有值,则报FLASH内存不足错误,应当考虑更高FLASH容量的芯片。

  • 70
    点赞
  • 234
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白我超可爱的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值