全部博文(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 08:36:47
非常感谢!! 那这种情况和您文章中所描述的情况不一样的吗?您文章中设置ro为0x20000000,xCopy2SDRAM函数的运行地址不是也是在RAM中。
chinaunix网友2009-08-18 19:51:09
;LOAD_ROM 0X10000000 ;{ ; RO 0X10000000 ; { ; 91x_vect.o(Vect,+FIRST) ; *( +RO ) ; } ; RW 0X20000a00 ; { ; *( +RW ) ; } ; ZI +0 ; { ; *( +ZI ) ; } ; EXEC_RAM 0X20000000 0XA00 ; { ; abc.o(+RO) ; } ;} 这是我写的scatter文件,为什么我在启动代码中调用abc.c中的函数会跳到ram中运行,在启动代码中使用BL 不是不能长跳转吗?