我在看U-BOOT的lowlevel_init.S文件时看到以下代码:
lowlevel_init:
ldr r0, =SMRDATA
ldr r1, _TEXT_BASE
sub r0, r0, r1
ldr r1, =BWSCON
add r2, r0, #13*4
0:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne 0b
mov pc, lr
这段代码完结了U-BOOT的内存控制器部分的寄存器初始化,总共13个寄存器,对U-BOOT来最重要的便是SDRAM的初始化,明显没有这部分代码,当U-BOOT从NAND FLASH中发动的时分,START.S文件是无法完结代码的relocate的。我们SDRAM没初始化,用不了。
要了解这段代码主要是搞清楚LDR的两种用法。
ldr r0, =SMRDATA的效果是让r0等于U-BOOT编译时现已确认下来的SMRDATA这块内存缓冲池的开端地址。
ldr r1, _TEXT_BASE的效果则是让r1等于_TEXT_BASE这个标号地点的内存晒干的内容,也便是 TEXT_BASE。关于MINI2440开发板来说这个值等于 TEXT_BASE = 0x33F80000(\board\samsung\mini2440\config.mk)这个地址是
我们TEXT_BASE实践的地址现在应该是FLASH的0地址(或许内部4KSRAM的0地址),所以第三条指令 sub r0, r0, r1 ,完结了核算SMRDATA当时在arm地址空间里的实践拜访地址。
接下去便是经过
ldr r3, [r0], #4 ;从r0这个地址里取一个32bit的数据,放到r3,并将r0+4,指向下一个内存池里的数据。
str r3, [r1], #4 ;这条指令完结了把r3里的数据赋值给r1所怂恿的地址。r1的地址经过下面这几句完结。以此装备完从0x48000000开端的CPU内部寄存器的值。这样SDRAM就开端作业了。今后便是正常拜访0x30000000开端的地址空间了。
#define BWSCON 0x48000000
ldr r1, =BWSCON /* Bus Width Status Controller */
上面的这个装备代码是无法在将U-BOOT直接用OPENJTAG下载到OPENJTAG中时作业的。我们当下载到内存中的时分,SDRAM的地址是随机的,至少不是从0开端的,这样得到的SMRDATA地点的地址按上面的方法是得不到的,所以需求一条在运行时地址与方位无关的指令。这便是 adr指令。下面代码便是改善后的:
lowlevel_init:
/* memory control configuration */
/* make r0 relative the current location so that it */
/* reads SMRDATA out of FLASH rather than memory ! */
ldr r0, =SMRDATA
ldr r1, =lowlevel_init /*编译时确认的地址*/
sub r0, r0, r1 /* r0 = r0 -r1 , r0 = SMRDATA相关于lowlevel_init的偏移值 */
adr r3, lowlevel_init /*方位无关*/
add r0,r0,r3 /*r0 = r0 +r3 ,r0寄存的是当时SMRDATA的实践地址*/
ldr r1, =BWSCON /* Bus Width Status Controller */
add r2, r0, #13*4
0:
ldr r3, [r0], #4
str r3, [r1], #4
cmp r2, r0
bne 0b