今天上午看《stm32威望攻略》中关于R15寄存器中有些内容不了解,查了查资料,原来是这样。
这里有一个他人的问题。
我把Nor Flash里的一个函数代码数据(函数首地址是:0x6400EC10)拷贝到RAM的 0x2000FC00,
然后把0x2000FC00加载给PC指针(为了让代码在RAM里运转),接着就呈现了Hard Fault
Exception,而用 IAR 单步履行的时分能正常运转。一同我将一个函数地址值赋给一个unsigned int
变量之后发现主动加了1。关于这些问题先看威望攻略里是怎样说的吧。
一,PC指针(程序计数器R15)(威望攻略)
R15是程序计数器,在汇编代码中称为“PC指针”。由于CM3内部运用了指令流水线,读PC时回来的值
是当时指令的地址+4。比如说:
0x1000: MOV R0, PC ; R0 = 0x1004
假如向PC中写数据,就会引起一次程序的分支(可是不更新LR寄存器)。CM3中的指令至少是半字
对齐的,所以PC的LSB总是读回0。可是,在分支时,无论是直接写PC的值仍是运用分支指令,都必
须确保加载到PC的数值是奇数(即LSB=1),用以标明这是在Thumb状态下履行。假使写了0,则视
为妄图转入ARM形式,CM3将发生一个fault反常。这些能够总结为读PC指针时,回来LSB总是为0;
写PC指针时,一定要确保LSB为奇数。
二,函数地址(自己总结的)
正如上面所说,写PC指针的时分有必要确保LSB为奇数,假如履行跳转指令的时分,将一个函数指针
加载给PC,这时分就有必要确保这个函数地址的LSB为奇数,并且还有必要是(4*n+1)(n=0,1,2,3)
这样的奇数,只要这样运转程序才不会跑飞。在今后的编程中,假如履行函数跳转的时分,一定要
确保这个函数地址的低四位的值为(4*n+1)(n=0,1,2,3)。
根据上面两点,就能够很好的解说所呈现的问题了,假如将0x2000FC00加载给PC指针,肯定会呈现
Hard Fault Exception,由于 0x2000FC00 的 LSB = 0;可是假如将 0x2000FC01加载给PC指针,程
序就能正常运转了,这就应证了威望攻略里所说的写PC指针的时分有必要确保加载给PC的值的LSB为1
。
而之前的为什么用IAR单步履行能成功,原因是IAR的调试器做了处理,使得每一次调试的时分对PC
指针的LSB做了一个奇偶改换;当全速运转的时分,调试器不论用了,直接由CPU接收,这个时分将
函数地址加载给PC的值的LSB为偶数,当然导致程序跑飞了。
还有为什么将一个函数地址值赋给一个unsigned int 变量之后会主动加一呢,这个是Cortex-M3的一
个特性,也就是说读取一个函数地址值回来的LSB为0,当赋值给一个变量的时分会加1,这是为了将
这个变量值加载给PC指针之后确保PC指针的LSB为1。
问题解决了,期望对碰到相同问题的朋友能有所协助。一同假如总结的欠好,我们能够一同沟通沟通。
可是,这个部分又是怎样了解的呢?