Uboot启动流程分析(基于u-boot1.1.4).doc
- 文档编号:610129
- 上传时间:2023-04-29
- 格式:DOC
- 页数:15
- 大小:142KB
Uboot启动流程分析(基于u-boot1.1.4).doc
《Uboot启动流程分析(基于u-boot1.1.4).doc》由会员分享,可在线阅读,更多相关《Uboot启动流程分析(基于u-boot1.1.4).doc(15页珍藏版)》请在冰点文库上搜索。
Uboot启动流程分析(基于u-boot1.1.4)
先分析一下u-boot启动的两个阶段,分别对应start.S和board.c这两个文件。
先看board/smsk2410/u-boot.lds这个链接脚本,可以知道目标程序的各部分链接顺序。
OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm","elf32-arm","elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
.=0x00000000;/*指定可执行image文件的全局入口点,通常这个地址都放在ROM(flash)0x0位置。
必须使编译器知道这个地址,通常都是修改此处来完成*/
.=ALIGN(4);
.text:
{
cpu/arm920t/start.o(.text)
*(.text)
}
.=ALIGN(4);
.rodata:
{*(.rodata)}
.=ALIGN(4);
.data:
{*(.data)}
.=ALIGN(4);
.got:
{*(.got)}
.=.;
__u_boot_cmd_start=.;
.u_boot_cmd:
{*(.u_boot_cmd)}
__u_boot_cmd_end=.;
.=ALIGN(4);
__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
strr1,[r0]
#ifdefined(CONFIG_S3C2410)
ldrr1,=0x3ff
ldrr0,=INTSUBMSK
strr1,[r0]
#endif
/*FCLK:
HCLK:
PCLK=1:
2:
4*/;;FCLK用于CPU,HCLK用于AHB,PCLK用于APB
/*defaultFCLKis120MHz!
*/
ldrr0,=CLKDIVN;;根据硬件手册来设置CLKDIVN寄存器
movr1,#3;;用户手册的推荐值
strr1,[r0]
#endif/*CONFIG_S3C2400||CONFIG_S3C2410*/
/*这些初始化代码在系统重起的时候执行,运行时热复位从RAM中启动不执行*/
/*
*wedosys-criticalinitsonlyatreboot,
*notwhenbootingfrom
*/
#ifndefCONFIG_SKIP_LOWLEVEL_INIT
blcpu_init_crit;;跳转去初始化CPU
#endif
;;#ifdefCONFIG_INIT_CRITICAL原文中的,估计是1.1.16版本的
;;blcpu_init_crit
;;#endif
/*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/smsk2410/u-boot.lds内容?
subr2,r3,r2/*r2得到armboot的大小*/
addr2,r0,r2/*r2得到要复制代码的末尾地址*/
copy_loop:
/*重新定位代码*/;;开始循环拷贝启动的代码到RAM中
ldmia{r3-r10}/*从源地址[r0]复制*/;;r0指向_start(=0)
stmia{r3-r10}/*复制到目的地址[r1]*/;;r1指向_TEXT_BASE(=0x33F80000)
cmpr0,r2/*复制数据块直到源数据末尾地址[r2]*/
blecopy_loop
;;这里附上u-boot各存储区域的映射图,从网上找的,这下对于这几个地址的位置就一目了然了,对于我这种菜鸟真的是好图啊!
/*初始化堆栈等*/
stack_setup:
ldrr0,_TEXT_BASE/*上面是128KiB重定位的u-boot*/
subr0,r0,#CFG_MALLOC_LEN/*向下是内存分配空间*/
subr0,r0,#CFG_GBL_DATA_SIZE/*然后是bdinfo结构体地址空间*/
#ifdefCONFIG_USE_IRQ
subr0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif ;;这些宏定义在/include/configs/smdk2410.h中:
#defineCFG_MALLOC_LEN (CFG_ENV_SIZE+128*1024) ;;64K+128K=0xC0
#defineCFG_ENV_SIZE 0x10000 /*TotalSizeofEnvironmentSector64k*/
#defineCONFIG_STACKSIZE (128*1024) /*regularstack128k*/
#defineCFG_GBL_DATA_SIZE 128 /*sizeinbytesreservedforinitialdata*/
用0x33F8000–0xC0–0x80得到_TEXT_BASE向下(低地址)的堆栈指针sp的起点地址
subsp,r0,#12/*为abort-stack预留3个字*/ ;;得到最终sp指针初始值
clear_bss:
ldrr0,_bss_start/*找到bss段起始地址*/
ldrr1,_bss_end/*bss段末尾地址*/
movr2,#0x00000000/*清零*/
clbss_l:
strr2,[r0]/*bss段地址空间清零循环...*/
addr0,r0,#4
cmpr0,r1
bneclbss_l
/*跳转到start_armboot函数入口,_start_armboot字保存函数入口指针*/
ldrpc,_start_armboot
_start_armboot:
.wordstart_armboot;;start_armboot函数在lib_arm/board.c中实现
2.Stage2:
lib_arm/board.c
此文件是u-bootStage2部分,入口为Stage1最后调用的start_armboot函数。
注意上面最后ldr到pc的是_start_armboot这个地址,而非start_armboot变量。
start_armboot是U-Boot执行的第一个C语言函数,完成系统初始化工作,进入主循环,处理用户输入的命令。
voidstart_armboot(void)
{
DECLARE_GLOBAL_DATA_PTR;
//此宏定义了一个gd_t类型的指针*gd,并指名用r8寄存器来存储:
#defineDECLARE_GLOBAL_DATA_PTRregistervolatilegd_t*gdasm("r8")
ulongsize;
init_fnc_t**init_fnc_ptr;
char*s;
/*Pointeriswritablesinceweallocatedaregisterforit 上面那个宏的作用*/
gd=(gd_t*)(_armboot_start-CFG_MALLOC_LEN-sizeof(gd_t));
//此C语句引用的是start.S中的地址标号_armboot_start,但是得到的却是其中所指的变量_start的值(在RAM中,_start=0x33F80000)。
Ps:
_armboot_start:
.word_start
//gd是全局变量,位置在堆栈区以下(低地址):
typedefstructglobal_data{
bd_t*bd;
unsignedlongflags;
unsignedlongbaudrate;
unsignedlonghave_console;/*serial_init()wascalled*/
unsignedlongreloc_off;/*RelocationOffset*/ //此变量有什么用?
unsignedlongenv_addr;/*AddressofEnvironmentstruct*/
unsignedlongenv_valid;/*ChecksumofEnvironmentvalid?
*/
unsignedlongfb_base;/*baseaddressofframebuffer*/
#ifdefCONFIG_VFD
unsignedcharvfd_type;/*displaytype*/
#endif
#if0
unsignedlongcpu_clk;/*CPUclockinHz!
*/
unsignedlongbus_clk;
unsignedlongram_size;/*RAMsize*/
unsignedlongreset_status;/*resetstatusregisteratboot*/
#endif
void**jt;/*jumptable*/
}gd_t;
/*compileroptimizationbarrierneededforGCC>=3.4*/
__asm____volatile__("":
:
:
"memory");
memset((void*)gd,0,sizeof(gd_t));
gd->bd=(bd_t*)((char*)gd-sizeof(bd_t)); //得到bd的起点
memset(gd->bd,0,sizeof(bd_t));
monitor_flash_len=_bss_start-_armboot_start;
/*顺序执行init_sequence数组中的初始化函数*/
for(init_fnc_ptr=init_sequence;*init_fnc_ptr;++init_fnc_ptr){
if((*init_fnc_ptr)()!
=0){
hang();
}
}
/*配置可用的Flash*/
size=flash_init(); //初始化Norflash的函数,函数实现在下面
display_flash_config(size); //打印到控制台:
Flash:
512kB
/*_armboot_start在u-boot.lds链接脚本中定义*/
mem_malloc_init(_armboot_start-CFG_MALLOC_LEN); //将CFG_MALLOC_LEN区域用memset函数清零(直接往目的地址写0)
/*配置环境变量,重新定位*/
env_relocate(); //刚才的初始化函数中有一个是env_init(),根据CRC校验来初始化gd->env_addr变量(自己设定的还是初始值),此函数是作用是将环境变量值从某个flash和RAM之间的拷贝。
下图描述了ENV的初始化过程:
/*从环境变量中获取IP地址,放到全局变量gd中*/
gd->bd->bi_ip_addr=getenv_IPaddr("ipaddr");
/*以太网接口MAC地址,放到全局变量gd中,实现过程有待研究*/
{
inti;
ulongreg;
char*s,*e;
uchartmp[64];
i=getenv_r("ethaddr",tmp,sizeof(tmp));
s=(i>0)?
tmp:
NULL;
for(reg=0;reg<6;++reg){
gd->bd->bi_enetaddr[reg]=s?
simple_strtoul(s,&e,16):
0;
if(s)
s=(*e)?
e+1:
e;
}
}
devices_init();/*获取列表中的设备*/
jumptable_init();
console_init_r();/*完整地初始化控制台设备*/
enable_interrupts();/*使能例外处理*/
/*通过环境变量初始化*/
if((s=getenv("loadaddr"))!
=NULL){
load_addr=simple_strtoul(s,NULL,16);
}
//以上几个初始化函数有待研究
/*main_loop()总是试图自动
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Uboot 启动 流程 分析 基于 boot1 1.4