下面是接着上一篇继续分析:
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) /*设置调用c语言函数的堆栈并以八字节对齐*/
bic sp, sp, #7 /*8字节对齐*/
ldr r0,=0x00000000 /*设置传递给board_init_f的参数r0=0*/
bl board_init_f /*跳转到c语言函数中继续执行,该函数在\u-boot-2011.03\arch\arm\lib\board.c中定义*/
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
*/
/*在board_init_f的最后中调用relocate_code (addr_sp, id, addr)函数*/
.globl relocate_code /*定义一个全局变量relocate_code*/
/*保存传过来的参数根据arm调用标准,r0,r1,r2分别对应addr_sp,id,addr*/
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
/* 设置堆栈*/
stack_setup:
mov sp, r4 /*首先把r4 (传过来的第一个参数)放到sp中*/
adr r0, _start /*把代码段的开始地址放到r0中*/
cmp r0, r6 /*比较r0,r6是否相等*/
beq clear_bss /*如果相等就不用重定位,证明已经在内存中 ,直接跳到clear _bss标号处*/
/*下面的几行代码是把代码段重定位到内存中*/
mov r1, r6 /* r1 <- scratch for copy_loop */
ldr r3, _bss_start_ofs
add r2, r0, r3 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r9-r10} /* copy from source address [r0] */
stmia r1!, {r9-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
blo copy_loop
#ifndef CONFIG_PRELOADER
/*
* fix .rel.dyn relocations
*/
ldr r0, _TEXT_BASE /* 把_TEXT_BASE的标号地址(链接地址0x33F8000)的放入r0中*/
sub r9, r6, r0 /* 把重定位后的偏移地址放入r9中 */
ldr r10, _dynsym_start_ofs /* 把__dynsym_start段重定位链接地址*/
add r10, r10, r0 /* r10 <- sym table in FLASH */
ldr r2, _rel_dyn_start_ofs /* 把__rel_dyn_start段重定位链接地址*/
add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
ldr r3, _rel_dyn_end_ofs /* 把 __rel_dyn_end段重定位链接地址*/
add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
fixloop:
ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
add r0, r0, r9 /* r0 <- location to fix up in RAM */
ldr r1, [r2, #4]
and r7, r1, #0xff
cmp r7, #23 /* relative fixup? */
beq fixrel
cmp r7, #2 /* absolute fixup? */
beq fixabs
/* ignore unknown type of fixup */
b fixnext
fixabs:
/* absolute fix: set location to (offset) symbol value */
mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
add r1, r10, r1 /* r1 <- address of symbol in table */
ldr r1, [r1, #4] /* r1 <- symbol value */
add r1, r1, r9 /* r1 <- relocated sym addr */
b fixnext
fixrel:
/* relative fix: increase location by offset */
ldr r1, [r0]
add r1, r1, r9
fixnext:
str r1, [r0]
add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
cmp r2, r3
blo fixloop
#endif
clear_bss: /*清除bss段*/
#ifndef CONFIG_PRELOADER
ldr r0, _bss_start_ofs /*bss段的开始偏移地址*/
ldr r1, _bss_end_ofs /*bss段的结束偏移地址*/
mov r4, r6 /*重定位bss代码段的地址 */
add r0, r0, r4
add r1, r1, r4
mov r2, #0x00000000 /* clear*/
/*循环清除bss段*/
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
/*下面的两行代码是为AT91RM9200而设计的led显示状态*/
bl coloured_LED_init
bl red_LED_on
#endif
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
#ifdef CONFIG_NAND_SPL
ldr r0, _nand_boot_ofs
mov pc, r0
_nand_boot_ofs:
.word nand_boot
#else
ldr r0, _board_init_r_ofs /*把标号为_board_init_r_ofs的地址加载进r0*/
adr r1, _start /*把 _start的地址加载进r1*/
add lr, r0, r1 /*把r1,r2相加后的结果放入lr链接寄存器中*/
add lr, lr, r9 /*把lr加上r9的结果放入lr中*/
/*relocate_code (addr_sp, id, addr)函数传递的后两个参数放入r0,r1, 重新传给board_init_r (gd_t *id, ulong dest_addr)函数*/
mov r0, r5 /* gd_t */
mov r1, r6 /* dest_addr */
/* jump to it ... */
mov pc, lr /*跳转到函数board_init_r (gd_t *id, ulong dest_addr)中开始执行,该函数定义在\u-boot-2011.03\arch\arm\lib\board.c中*/
_board_init_r_ofs:
.word board_init_r - _start
#endif
/*__rel_dyn_start,__rel_dyn_end,__dynsym_start在uboot.lds中定义*/
_rel_dyn_start_ofs:
.word __rel_dyn_start - _start /* 计算出__rel_dyn_start的偏移地址*/
_rel_dyn_end_ofs:
.word __rel_dyn_end - _start /* 计算出__rel_dyn_end的偏移地址*/
_dynsym_start_ofs:
.word __dynsym_start - _start /* 计算出__dynsym_start的偏移地址*/
/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
* flush v4 I/D caches 刷新指令和数据缓存,TLB缓存表
*/
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
/*
* disable MMU stuff and caches 关闭mmu
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init.S in your board directory.
*/
mov ip, lr
bl lowlevel_init /*对内存进行初始化*/
mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
/*
*************************************************************************
*
* Interrupt handling 中断处理程序
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72
#define S_OLD_R0 68
#define S_PSR 64
#define S_PC 60
#define S_LR 56
#define S_SP 52
#define S_IP 48
...................................
..................................
start.S文件就分析到此。也是uboot执行的第一阶段的代码。以后会接着对后续流程继续跟踪。