关于stm32中R15寄存器的理解

今天上午看《stm32权威指南》中关于R15寄存器中有些内容不理解,查了查资料,原来是这样。

关于stm32中R15寄存器的理解_第1张图片

这里有一个别人的问题。



我把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。

问题解决了,希望对碰到同样问题的朋友能有所帮助。同时如果总结的不好,大家可以一起交流交流。



但是,这个部分又是怎么理解的呢?


你可能感兴趣的:(Cortex-M3)