Uboot启动流程分析(基于u-boot1.1.4)Word文档格式.doc
《Uboot启动流程分析(基于u-boot1.1.4)Word文档格式.doc》由会员分享,可在线阅读,更多相关《Uboot启动流程分析(基于u-boot1.1.4)Word文档格式.doc(15页珍藏版)》请在冰豆网上搜索。
必须使编译器知道这个地址,通常都是修改此处来完成*/
.=ALIGN(4);
.text:
cpu/arm920t/start.o(.text)
*(.text)
}
.rodata:
{*(.rodata)}
.data:
{*(.data)}
.got:
{*(.got)}
.=.;
__u_boot_cmd_start=.;
.u_boot_cmd:
{*(.u_boot_cmd)}
__u_boot_cmd_end=.;
__bss_start=.;
.bss:
{*(.bss)}
_end=.;
第一个要链接的是cpu/arm920t/start.o,那么U-Boot的入口指令一定位于这个程序中。
下面详细分析一下程序跳转和函数的调用关系以及函数实现。
1.Stage1:
cpu/arm920t/start.S
这个汇编程序是U-Boot的入口程序,开头就是复位向量的代码。
U-Boot启动代码流程图
_start:
breset//复位向量;
;
设置异常向量表
ldrpc,_undefined_instruction
ldrpc,_software_interrupt
ldrpc,_prefetch_abort
ldrpc,_data_abort
ldrpc,_not_used
ldrpc,_irq//中断向量
ldrpc,_fiq//中断向量
…
/*theactualresetcode*/
reset:
//复位启动子程序
/*设置CPU为SVC32模式*/
mrsr0,cpsr
bicr0,r0,#0x1f;
位清除,将某些位的值置0:
r0=r0AND(!
0x1f)
orrr0,r0,#0xd3;
逻辑或,将r0与立即数进行逻辑或,放在r0中(第一个)
msrcpsr,r0
/*关闭看门狗*/
/*turnoffthewatchdog*/
#ifdefined(CONFIG_S3C2400)
#definepWTCON0x15300000
#defineINTMSK0x14400008/*Interupt-Controllerbaseaddresses*/
#defineCLKDIVN0x14800014/*clockdivisorregister*/
#elifdefined(CONFIG_S3C2410)
#definepWTCON0x53000000
#defineINTMSK0x4A000008/*Interupt-Controllerbaseaddresses*/
#defineINTSUBMSK0x4A00001C
#defineCLKDIVN0x4C000014/*clockdivisorregister*/
#endif
#ifdefined(CONFIG_S3C2400)||defined(CONFIG_S3C2410)
ldrr0,=pWTCON
movr1,#0x0
strr1,[r0]
/*禁止所有中断和设置CPU频率*/
/*
*maskallIRQsbysettingallbitsintheINTMR-default
*/
movr1,#0xffffffff
ldrr0,=INTMSK
#ifdefined(CONFIG_S3C2410)
ldrr1,=0x3ff
ldrr0,=INTSUBMSK
#endif
/*FCLK:
HCLK:
PCLK=1:
2:
4*/;
FCLK用于CPU,HCLK用于AHB,PCLK用于APB
/*defaultFCLKis120MHz!
*/
ldrr0,=CLKDIVN;
根据硬件手册来设置CLKDIVN寄存器
movr1,#3;
用户手册的推荐值
#endif/*CONFIG_S3C2400||CONFIG_S3C2410*/
/*这些初始化代码在系统重起的时候执行,运行时热复位从RAM中启动不执行*/
*wedosys-criticalinitsonlyatreboot,
*notwhenbootingfrom
#ifndefCONFIG_SKIP_LOWLEVEL_INIT
blcpu_init_crit;
跳转去初始化CPU
#ifdefCONFIG_INIT_CRITICAL原文中的,估计是1.1.16版本的
blcpu_init_crit
/*CPU和RAM两个关键的初始化子程序*/
/*初始化CPU*/
cpu_init_crit:
*flushv4I/Dcaches设置CP15
movr0,#0
mcrp15,0,r0,c7,c7,0/*flushv3/v4cache*/;
使I/Dcache失效:
将寄存器r0的数据传送到协处理器p15的c7中。
C7寄存器位对应cp15中的cache控制寄存器
mcrp15,0,r0,c8,c7,0/*flushv4TLB*/;
使TLB操作寄存器失效:
将r0数据送到cp15的c8、c7中。
C8对应TLB操作寄存器
*disableMMUstuffandcaches禁止MMU和caches
mrcp15,0,r0,c1,c0,0;
先把c1和c0寄存器的各位置0(r0=0)
bicr0,r0,#0x00002300@clearbits13,9:
8(--V---RS)
bicr0,r0,#0x00000087@clearbits7,2:
0(B----CAM);
这里我本来有个疑问:
为什么要分开设置。
因为arm汇编要求的立即数格式所决定的
orrr0,r0,#0x00000002@setbit2(?
?
)(A)Align;
上一条已经设置bit1为0,这一条又设置为1?
?
orrr0,r0,#0x00001000@setbit12(I)I-Cache
mcrp15,0,r0,c1,c0,0;
用上面(见下面)设定的r0的值设置c1?
(cache类型寄存器)和c0(control字寄存器),以下为c0的位定义
bit8:
0=DisableSystemprotection
bit9:
0=DisableROMprotection
bit0:
0=MMUdisabled
bit1:
0=Faultcheckingdisabled禁止纠错
bit2:
0=Datacachedisabled
bit7:
0=Little-endianoperation
bit12:
1=Instructioncacheenabled
/*配置内存区控制寄存器?
有待分析,是1.1.4版本的
*beforerelocating,wehavetosetupRAMtiming
*becausememorytimingisboard-dependend,youwill
*findalowlevel_init.Sinyourboarddirectory.
movip,lr
bllowlevel_init;
位于board/smdk2410/lowlevel_init.S:
用于完成芯片存储器的初始化,执行完成后返回
movlr,ip
movpc,lr
relocate:
/*把U-Boot重新定位到RAM*/
adrr0,_start/*r0是代码的当前位置*/;
adr伪指令,汇编器自动通过当前PC的值算出如果执行到_start时PC的值,放到r0中:
当此段在flash中执行时r0=_start=0;
当此段在RAM中执行时_start=_TEXT_BASE(在board/smdk2410/config.mk中指定的值为0x33F80000,即u-boot在把代码拷贝到RAM中去执行的代码段的开始)
ldrr1,_TEXT_BASE/*测试判断是从Flash启动,还是RAM*/;
此句执行的结果r1始终是0x33FF80000,因为此值是又编译器指定的(ads中设置,或-D设置编译器参数)
cmpr0,r1/*比较r0和r1,调试的时候不要执行重定位*/
beqstack_setup/*如果r0等于r1,跳过重定位代码*/
/*准备重新定位代码*/;
以上确定了复位启动代码是在flash中执行的(是系统重启,而不是软复位),就需要把代码拷贝到RAM中去执行,以下为计算即将拷贝的代码的长度
ldrr2,_armboot_start;
前面定义了,就是_start
ldrr3,_bss_start;
所谓bss段,就是未被初始化的静态变量存放的地方,这个地址是如何的出来的?
根据board/sms