全部博文(2005)
分类:
2007-05-17 16:18:38
ARM中的跳转地址是怎么回事!(作者:gliethttp)
跳转指令用于实现程序顺序执行时的函数跳转,在ARM程序中有两种方法可以实现程序流程的跳转:
<1>使用专门的跳转指令
<2>直接向当前地址计数器PC写入预跳转的绝对地址值
通过向当前地址计数器PC写入预跳转的绝对地址值,可以实现在4GB连续的线性地址空间中的任意子程序调用跳转
ARM专用的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,一共有4个:
<1> B 跳转指令
<2> BL 带返回的跳转指令,子程序执行完成后会有mov pr,lr指令,以便返回到函数调用处继续执行
<3> BLX 带返回和状态切换的跳转指令,跳转的同时实现ARM态和Thumb态的切换,并且返回地址入lr(C程序子函数调用时)
<4> BX 带状态切换的跳转指令,跳转的同时实现ARM态和Thumb态的切换
可以看到“ARM专门的跳转指令”均是进行相对地址跳转(即:相对于当前执行处PC地址,向前、向后跳),因此,可以使用这一
特性完成程序自己在Flash中将自己拷贝到SDRAM然后运行的自启动工作。
开发环境:ADS1.2
硬件环境:
CPU - at91rm9200
Flash - 0x10000000 (程序存储地址)
SDRAM - 0x20000000 (SDRAM起始地址)
ADS配置:
ARM Linker->Output/RO Base
将RO Base设置成0x20000000,RW Base空着不管,
那么编译器会把RO和RW段均以0x20000000为起始地址进行程序链接
记得前面的“ARM专门的跳转指令”吧,虽然我们这里编译地址为0x20000000,但是当我们把编译好的bin文件下载到0x10000000地址(启动后,未Remap前,被CPU认成0x0地址)Init.s中的B、BL相对地址跳转均还能够正常运行,所以我们就可以很安全的在Init.s中实现将Flash中运行的自身拷贝到SDRAM中,然后继续运行!最后使用ldr pc,=0xabcdefgh就可以跳转到SDRAM内存中执行刚才拷贝的自身程序了!
参考代码: #define xsrc_base 0x10000000 #define xdst_base 0x20000000 extern uint32 Image$$RO$$Base; extern uint32 Image$$ZI$$Limit; void xCopy2SDRAM(void) {uint32 *src,*dst; uint32 i; uint32 dot; uint32 xcode_size = (uint32)&Image$$ZI$$Limit - (uint32)&Image$$RO$$Base; uint32 xdot_size; src = (uint32*)xsrc_base; dst = (uint32*)xdst_base; xcode_size /= 4; xcode_size += 1; xdot_size = (xcode_size/10); for(i = 0,dot = 0;i < xcode_size;i++) { *dst++ = *src++; dot++; if(dot >= xdot_size) { dot = 0; xxxdprintf("."); } } } |
chinaunix网友2009-08-19 09:53:04
将ro设置成为0x20000000,不是指定了程序的运行地址为RAM(也包括xCopy2SDRAM),是这样吗?如果在我写的scatter中的abc.c,我写的函数也都是没有使用全局变量之类的,应该也是地址无关的阿,为什么用scatter指定的运行地址,使用BL就会跳转到ram中运行呢?
chinaunix网友2009-08-19 09:47:36
这个我清楚,我不清楚的是xCopy2SDRAM为什么是地址无关的?它为什么用BL调用还是在flash中运行?它怎么不用复制到RAM中才能运行?如果Main函数也不用全局变量之类的,虽然设置0x20000000,是不是也可以直接调用,还是会在FLASH中运行?
chinaunix网友2009-08-19 08:57:38
原来博主在线,感谢您的不吝赐教!!不过我还是有点不明白,ro为0x20000000,所有的函数链接地址不是都是以 0x20000000为基址,怎么说是地址无关呢?上面两种情况有什么区别?希望您能解释的详细些,这个问题困扰了我很久,我将不胜感激!