分类: LINUX
2010-06-17 22:22:42
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */
相信大家移植的时候都对这段代码比较熟悉,我在以前的博文中曾经说过从sdram启动时需要定义一个CONFIG_SKIP_RELOCATE_UBOOT宏,使代码不执行上面的这一段。但是这次我却使用了这段代码。
我们重点关注两行代码:
adr r0, _start
ldr r1, _TEXT_BASE
第一行中的_start是一个标号,定义在start.S的开头,系统复位或者刚上电时代码执行的地方;第二行中的_TEXT_BASE也是一个标号,这个标号地址处放的值是定义在board/xxxx/config.mk文件中的TEXT_BASE的值,我这里设置为0x33f00000,你可以根据自己的需要来进行调整。上面那段代码是比较这两个值,如果相同则不拷贝,直接执行;若不同,则把剩下的后面的代码拷贝到TEXT_BASE所表示的地址处,然后再执行。如果在这里我们看不出来这两行代码是什么意思,我们可以来看看反汇编后的代码,结果如下:
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
33f000ec: e24f00f4 sub r0, pc, #244 ; 0xf4
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
33f000f0: e51f10b8 ldr r1, [pc, #-184] ; 33f00040 <_TEXT_BASE>
cmp r0, r1 /* don't reloc during debug */
33f000f4: e1500001 cmp r0, r1
beq stack_setup
33f000f8: 0a000007 beq 33f0011c
第一行被翻译成了sub r0, pc, #244,意思就是把当前pc中的值减去244,放入r0中。而当前pc的值,根据arm的流水线指令执行规则,pc在此处的值应该是在这行代码的前面8个Bytes处;第二行代码很好理解,还是以前一样的指令,表示把_TEXT_BASE这个地址处的值放入r1中,而_TEXT_BASE这个地址处的值由下列代码决定:
_TEXT_BASE:
.word TEXT_BASE
即这个地址处的值就是我刚才说到的在一个config.mk文件里面定义的,我这里为0x33f00000,而这个_TEXT_BASE的地址却不是由我们决定,它由编译器进行分配;但是我们并不需要关心它的地址,我们只需要关心这个地址处的值是多少就行了。
好了,现在假设我们把编译好的二进制文件下载到地址0x31000000处,然后开始执行这个loader,当运行到上面提到的第一行代码处时,pc的值应该是0x310000ec+8即为0x310000f4,然后用这个值减去244即为0x31000000,就是我们运行的新的loader开始的地址;而第二行程序中r1得到的值为0x33f00000,然后进行比较,结果当然是不同了,那么下面就会执行一段搬运代码的过程,将0x31000000处的代码搬运到TEXT_BASE指定的0x33f00000处,然后再执行下面的程序,最终会跳转到0x33f000000后面的地址中执行程序。
由上面的分析可知,如果我们本来就把待运行的loader下载到0x33f00000处,将不会执行那一段搬运过程。
因此可以得出结论:从sdram启动时,可以不屏蔽掉relocate这段代码。但是实际应用时要注意以下问题:一是待运行的loadr不能下载到现在的loader所使用的地址范围内;二是如果待运行的loader下载到的开始地址如果与运行的开始地址不同,要保证下载时loader的结尾处不能占到运行时loader的开始位置处。
下面是我一年多前写的一篇从sdram启动u-boot的博文,供大家参考: