_TEXT_BASE:
.word TEXT_BASE // 这个TEXT_BASE是在uboot1.1.6/board/smdk2410/config.mk内定义的,TEXT_BASE = 0x33F80000。config.mk内有注释,这个地址是规划用来运行uboot的SDRAM区域开始地址。所以这个地址定义在这里主要是给链接器使用的,让链接器在链接时,重定位步骤中,将uboot代码重定位到这个地址(重定位涉及到某些指令的指令码修改,因为有一些指令是位置相关的)。
.globl lowlevel_init // lowlevel_init 函数完成的功能只有一个,那就是初始化SDRAM。初始化过程跟2440启动代码中的init.S中的初始化过程完全一样,说白了就是配置SDRAM控制器的13个寄存器内容。配置成什么样的值呢?一般来说要根据板子上实际用的SDRAM来确定。但是因为大家基本都是用现代的内存,所以基本上用的是一套配置参数。这里不想讲这些配置参数什么意思,只是重点分析这个函数的配置过程和技巧。
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 // 使用objdump查看可知,SMRDATA链接后地址为0x33f80430,而_TEXT_BASE 处存放的即是链接重定位时的基地址0x33f80000,所以r0-r1得到0x430,这就是SMRDATA这个数据结构在uboot可执行文件中相对于零点的偏移量。不管从nand还是nor启动,总之uboot可执行档起初都是在零地址开始的空间内的。所以这里r0-r1得到的即是启动时SMRDATA在nand/nor中的绝对地址,从这个内存地址(这里的内存不是SDRAM,而是SRAM或者norflash)去寻址即可读出SRMDATA数值。
ldr r1, _TEXT_BASE
sub r0, r0, r1
ldr r1, =BWSCON /* Bus Width Status Controller */
add r2, r0, #13*4
0:
ldr r3, [r0], #4 // 这里是一个循环来完成从SMRDATA到BWSCON开始的地址连续的13个SDRAM配置相关寄存器的设置
str r3, [r1], #4 // r3是值中转寄存器,r2和r0的对比来判断13个是否已完成,r0指向SMRDATA源,r1指向目标寄存器地址
cmp r2, r0 // 这里的关键其实就是理解SMRDATA的寻找过程。因为链接时重定位了,所以SMRDATA的地址直接引用的话,指向的将是他将来被加载
bne 0b // 到SDRAM后对应的地址。而这里初始化SDRAM时代码还在SRAM(对应nand启动)或nor(对应norflash启动)中,这些都是重定位之前
// 的地址,所以要通过上面的-TEXT_BASE的值来得到SMRDATA重定位之前的地址。
/* everything is fine now */
mov pc, lr
.ltorg
/* the literal pools origin */
SMRDATA:
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
.word 0x32
.word 0x30
.word 0x30
总结:
1、代码链接时的重定位,让代码中使用位置相关代码时情况变的复杂起来了。这一块要彻底想通透,是需要花一些时间的。
2、objdump工具确实很有用,可以让你看到重定位后的符号和地址的对应关系,建议大家好好利用。
3、上面的r0-r1 = 0x430 < 4K,可见这个安排nand/nor启动都是支持的。如果启动部分比较大,SMRDATA的绝对地址(即相当于_start的地址)大于了4K,则这个代码就不能使用nand启动了。因为nand启动时只能映射前4k代码到SRAM。而nor启动则没有这个限制,因为nor启动在SDRAM运行代码前可支配的地址空间是0到norflash大小。
阅读(1408) | 评论(0) | 转发(0) |