u-boot第一阶段分析(四)

注:本次分析的u-boot是九鼎官方的u-boot代码
下载地址:链接:http://pan.baidu.com/s/1gfpDZqj 密码:7cqe


上一章说了lowlevel_init.S,现在重新回到start.S中。

1.再次设置栈

ldr	sp, _TEXT_PHY_BASE	
sub	sp, sp, #12
mov	fp, #0

(1)之前在调用lowlevel_init程序前设置过1次栈(start.S 284-287行),那时候因为DDR尚未初始化,因此程序执行都是在SRAM中,所以在SRAM中分配了一部分内存作为栈。本次因为DDR已经被初始化了,为了防止SRAM中栈不够用,因此要把栈挪移到DDR中,所以要重新设置栈,这是第二次(start.S 297-299行);
(2)这里实际设置的栈的地址是33E00000,分析代码可以得出:
_TEXT_PHY_BASE的字面意思是代码段物理地址基地址的意思,用SI我们可以查看到:

_TEXT_PHY_BASE:
	.word	CFG_PHY_UBOOT_BASE

通过SI可以继续查到:#define CFG_PHY_UBOOT_BASE MEMORY_BASE_ADDRESS + 0x3e00000
其中MEMORY_BASE_ADDRESS值为30000000;

2.再次判断当前地址以决定是否重定位

ldr	r0, =0xff000fff
bic	r1, pc, r0		
ldr	r2, _TEXT_BASE	
bic	r2, r2, r0		
cmp     r1, r2                  
beq     after_copy

(1)再次使用与lowlevel.init.S中相同的代码来判断当前地址是在SRAM中还是DDR中,不过和上一次目的不一样。
上一次判断是为了决定是否要执行初始化时钟和DDR的代码;这一次判断是为了决定是否进行uboot的重定位;
(2)冷启动时当前情况是uboot的前一部分(16kb或者8kb)开机自动从SD卡加载到SRAM中正在运行,uboot的第二部分(其实第二部分是整个uboot)还躺在SD卡的某个扇区开头的N个扇区中。此时uboot的第一阶段已经即将结束了(第一阶段该做的事基本做完了),结束之前要把第二部分加载到DDR中链接地址处(33E00000),这个加载过程就叫重定位。

3.重定位

#if defined(CONFIG_EVT1)
	/* If BL1 was copied from SD/MMC CH2 */
	ldr	r0, =0xD0037488
	ldr	r1, [r0]
	ldr	r2, =0xEB200000
	cmp	r1, r2
	beq     mmcsd_boot
#endif

	ldr	r0, =INF_REG_BASE
	ldr	r1, [r0, #INF_REG3_OFFSET]
	cmp	r1, #BOOT_NAND		/* 0x0 => boot device is nand */
	beq	nand_boot
	cmp	r1, #BOOT_ONENAND	/* 0x1 => boot device is onenand */
	beq	onenand_boot
	cmp     r1, #BOOT_MMCSD
	beq     mmcsd_boot
	cmp     r1, #BOOT_NOR
	beq     nor_boot
	cmp     r1, #BOOT_SEC_DEV
	beq     mmcsd_boot

(1)首先这里的D0037488这个内存地址在SRAM中,这个地址中的值是被硬件自动设置的,代表的是哪个SD卡通道。硬件根据我们实际电路中SD卡在哪个通道中,会将这个地址中的值设置为相应的数字。譬如我们从SD0通道启动时,这个值为EB000000;从SD2通道启动时,这个值为EB200000。
(2)代码中将D0037488中的值与EB200000想比较,如果相等则跳转到mmcsd_boot,否则继续运行下面的代码。
(3)我们在start.S的260行确定了从MMCSD启动,

/* SD/MMC BOOT */
cmp     r2, #0xc
moveq   r3, #BOOT_MMCSD	

然后又在278行将#BOOT_MMCSD写入了INF_REG3寄存器中存储着,

ldr	r0, =INF_REG_BASE
str	r3, [r0, #INF_REG3_OFFSET]

然后又在322行读出来,再和#BOOT_MMCSD去比较,确定是从MMCSD启动,最终跳转到mmcsd_boot函数中去执行重定位动作。

ldr	r1, [r0, #INF_REG3_OFFSET]
cmp     r1, #BOOT_MMCSD
beq     mmcsd_boot

所以不管怎样,最终都会跳转到mmcsd_boot处运行。

mmcsd_boot:
    bl      movi_bl2_copy
	b       after_copy

真正的重定位是通过调用movi_bl2_copy函数完成的,在uboot/cpu/s5pc11x/movi.c中,是一个C语言的函数。

你可能感兴趣的:(嵌入式开发)