在使用SDRAM时涉及代码复制,PC跳转执行涉及的位置无关码,位置有关码
.gloable _start
_start:
bl disable_watchdog @关狗
bl memctl_set @设置存储控制器
bl copy2sdram
ldr pc,=on_sdram
halt_loop:
b halt_loop @在此空循环,不做任何事,但是main里面一般有循环的话,语句就执行不到这里
on_sdram:
ldr sp, =0x34000000
bl main
disable_watchdog:
ldr r0, =0x53000000
mov r1, 0x0
str r1, [r0]
mov pc, lr
……
在makefile文件里
arm-linux-ld -Ttext 0x30000000 head.o leds.o -o sdram_elf
这句说明,程序生成代码sdram_elf的链接地址是0x30000000,而此地址就是SDRAM的起始地址
下面看看代码执行过程:
上电后,无条件将存储flash中前4K代码拷到片内RAM中执行,从PC指向0开始
第一条语句,bl disable_watchdog 是位置无关指令,因此PC指向0执行这一条语句
第二条语句,bl memctl_set是位置无关指令,因此PC值+4执行这一条语句(32位芯片,所以一条语句占据4个字节)
第三条语句,bl copy2sdram是位置无关指令,因此PC再+4,执行复制指令,执行片内RAM中copy2sdram代码块儿(此块儿是将片内RAM中代码复制到SDRAM中),此块代码执行后,0x30000000里面就有代码啦,在这之前,虽然链接地址(约定的程序存放地址)在0x30000000,但是代码还没复制到0x30000000,那为什么约定了代码要存放在那里,现在代码还没有在那里,而我们之前3条语句却能正确执行呢??那是因为前三条语句bl指令,是位置无关码,即链接地址不管怎么写,都是在0开始执行(开机自动复制4K到片内RAM嘛,没遇到位置有关码之前,都是在片内RAM中执行)。
第四条语句,ldr pc,=on_sdram是位置有关指令,因此PC(新地址)=PC(链接地址)+PC(下一条语句PC值),链接地址在makefile中指定了0x30000000,下一条PC值为0x00000010(每条PC加4,下一条+16即0x10),所以PC值变为0x30000010,即跳转到SDRAM中去执行了
浙公网安备 33010602011771号