STM32关于我遇到的HardFault_Handler的处理
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容量的芯片。
更多推荐
所有评论(0)