有工程师调试代码发现一个问题,IAR中把堆栈设小了,导致堆栈溢出,进入hardfault。我检查了下,堆栈溢出这个事实是存在的,但是堆栈溢出的结果和现象和我以前对于ARM的理解不一样了。
以前的理解:堆栈栈底不停的PUSH,即使超出了stack的范围,哪怕是修改了和栈底相邻的变量的值,也不会立即产生hardfault或者发现程序异常,而是在pop回来或者其他程序开始取得相邻变量的值的时候发生错误。所以以前要去查hardfault发生错误的位置,或者是程序功能错误,是不太好查的。下面是IAR的一些经验之谈
Debugging a HardFault on Cortex-M | IAR Systems
但是这次在IAR+LPC55调试过程中发现的hardfault出现情况是不同的,单步汇编代码能够看到感知一旦越界立即就会产生hardfault。
因为LPC55是较新的ARMV8M内核,查阅cortex_m33_trm_的技术手册,可以看到想比以前多了两个寄存器,MSPLIM和PSPLIM,正是这两个寄存器限制了stack越界的行为。
LPC55的初始化启动文件中明确设置了这个寄存器。
现在描述下这个寄存器的实测行为:首先CFSR中的STKOF被置位了,这个就是stack overflow的标记
使用IAR的View > Fault exception viewer可以看到
- DisableGlobalIRQ无法屏蔽这个hardfault行为的产生;
- 在第一次压栈,超过MSPLIM的时候,就产生hardfault,且没有压成功;
- 在hardfault_handler中,还会继续压栈,这时候不止没有压成功,还会从hardfault中跳出,直接将PC指征指向为一个非法地址;
这个设计的好处是大家不再会遭受堆栈溢出的痛苦了,但是我自己还是有一些遗留问题
遗留问题:
以前大家可能会在hardfault中加入一些处理程序,比如
- 软件复位
- 追踪堆栈压栈以确定产生hardfault的代码位置;
- RTOS是如何处理这个问题的?
但是目前这种情况下,hardfault都无法正常进入,点解??