Board logo

标题: stm32 hard fault及堆栈探究(2) [打印本页]

作者: yuyang911220    时间: 2015-4-28 21:29     标题: stm32 hard fault及堆栈探究(2)

在Time_Display()中通过用sprintf将地址赋值给变量(即代码中注视掉的sprintf语句),并在LCD上显示的办法观察到,栈内的变量分布情况为:

可以看出,栈从内存地址高位向低位生长,参数在栈底,变量按照定义的顺序依次往上摞。系统给buf多留了两字节的空间,其余变量(包括函数参数timevar和局部变量TXX)在内存中依次紧密排列,没有出现windows中将函数回退地址的入栈时间放于参数之后,使参数和变量之间有四字节空隙的情况。这说明函数的回退地址和一些寄存器的入栈保存另有其他时机。同时注意到,代码中有用sprintf取得变量地址的语句时,工作正常,不会进入hardfault。因此有必要比较两段代码对内存空间造成的影响。
1. 进入hard fault是在Time_Show()函数一个循环执行完毕时。因此有必要看一下汇编,了解具体对寄存器和内存的数据读写操作:
[cpp] view plaincopy


在这一段中,R4存放变量TimeDisplay的地址,R0为TimeDisplay的值。循环的最后一步,寄存器R4中的地址加0作为新地址,R5从内存中的该新地址取值存入。如果R4指向的地址非法,则读取该地址很有可能产生hard fault。
2.查看Time_Display()的汇编
(1)添加了显示变量地址的代码,而无hard fault的情况。
主循环的起始部分汇编代码如下,每次进入循环只需将Time_Display()时入栈的回退地址弹出作为PC。
[cpp] view plaincopy


刚进入Time_Display()时的汇编代码如下,进入时将R0和LR寄存器压入栈中。
[cpp] view plaincopy


此时STM32芯片寄存器和内存的情况如下图所示。




根绝汇编中把R0和LR压入栈中的指令,对应LR和R0的值,在局部变量所在内存空间寻找,可以发现LR最先入栈,接着是函数参数和其余变量,这和最开始打印出的各变量地址也是吻合的。因此,如果buf越界不是太多,只是改写了其余局部变量的数据,不影响回退地址。另外,查看函数所有汇编代码,没有对R4的操作。至函数执行完成并返回,R4的值始终为0x20000000。综上,函数可以继续执行而不会出错。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0