关于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。
问题解决了,希望对碰到同样问题的朋友能有所帮助。同时如果总结的不好,大家可以一起交流交流。
但是,这个部分又是怎么理解的呢?
stm32R15寄存 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)