经典Uboot4启动流程代码注释.docx

上传人:b****7 文档编号:11201572 上传时间:2023-02-25 格式:DOCX 页数:32 大小:173.92KB
下载 相关 举报
经典Uboot4启动流程代码注释.docx_第1页
第1页 / 共32页
经典Uboot4启动流程代码注释.docx_第2页
第2页 / 共32页
经典Uboot4启动流程代码注释.docx_第3页
第3页 / 共32页
经典Uboot4启动流程代码注释.docx_第4页
第4页 / 共32页
经典Uboot4启动流程代码注释.docx_第5页
第5页 / 共32页
点击查看更多>>
下载资源
资源描述

经典Uboot4启动流程代码注释.docx

《经典Uboot4启动流程代码注释.docx》由会员分享,可在线阅读,更多相关《经典Uboot4启动流程代码注释.docx(32页珍藏版)》请在冰豆网上搜索。

经典Uboot4启动流程代码注释.docx

经典Uboot4启动流程代码注释

U-Boot启动第一阶段代码分析:

(1)设置异常向量(cpu/arm920t/start.S)

.globl_start

_start:

bstart_code/*复位*/

ldrpc,_undefined_instruction/*未定义指令向量*/

ldrpc,_software_interrupt/*软件中断向量*/

ldrpc,_prefetch_abort/*预取指令异常向量*/

ldrpc,_data_abort/*数据操作异常向量*/

ldrpc,_not_used/*未使用*/

ldrpc,_irq/*irq中断向量*/

ldrpc,_fiq/*fiq中断向量*/

/*中断向量表入口地址*/

_undefined_instruction:

.wordundefined_instruction

_software_interrupt:

.wordsoftware_interrupt

_prefetch_abort:

.wordprefetch_abort

_data_abort:

.worddata_abort

_not_used:

.wordnot_used

_irq:

.wordirq

_fiq:

.wordfiq

.balignl16,0xdeadbeef

(2)CPU进入SVC模式(cpu/arm920t/start.S)

start_code:

/*setthecputoSVC32mode*/

mrsr0,cpsr

bicr0,r0,#0x1f/*工作模式位清零*/

orrr0,r0,#0xd3/*工作模式位设置为“10011”(管理模式),并将中断禁止位和快中断禁止位置1*/

msrcpsr,r0

(3)设置控制寄存器地址(cpu/arm920t/start.S)

#ifdefined(CONFIG_S3C2400)

#definepWTCON0x15300000

#defineINTMSK0x14400008

#defineCLKDIVN0x14800014

#else/*s3c2410与s3c2440下面4个寄存器地址相同*/

#definepWTCON0x53000000/*WATCHDOG控制寄存器地址*/

#defineINTMSK0x4A000008/*INTMSK寄存器地址*/

#defineINTSUBMSK0x4A00001C/*INTSUBMSK寄存器地址*/

#defineCLKDIVN0x4C000014/*CLKDIVN寄存器地址*/

#endif

(4)关闭看门狗(cpu/arm920t/start.S)

ldrr0,=pWTCON

movr1,#0x0

strr1,[r0]/*看门狗控制器的最低位为0时,看门狗不输出复位信号*/

(5)屏蔽中断(cpu/arm920t/start.S)

/*maskallIRQsbysettingallbitsintheINTMR–default*/

movr1,#0xffffffff/*某位被置1则对应的中断被屏蔽*/

ldrr0,=INTMSK/*中断源寄存器*/

strr1,[r0]

#ifdefined(CONFIG_S3C2440)

ldrr1,=0x7fff

ldrr0,=INTSUBMSK/*子中断源寄存器*/

strr1,[r0]

#endif

(6)设置MPLLCON、PLLCON、CLKDIVN(cpu/arm920t/start.S)

#ifdefined(CONFIG_S3C2440)【这个变量在哪里定义?

#defineMPLLCON0x4C000004

#defineUPLLCON0x4C000008

ldrr0,=CLKDIVN

movr1,#5

strr1,[r0]

ldrr0,=MPLLCON

ldrr1,=0x7F021

strr1,[r0]

ldrr0,=UPLLCON

ldrr1,=0x38022

strr1,[r0]

#else

/*FCLK:

HCLK:

PCLK=1:

2:

4*/

/*defaultFCLKis120MHz!

*/

ldrr0,=CLKDIVN

movr1,#3

strr1,[r0]

#endif

CPU上电几毫秒后,晶振输出稳定,FCLK=Fin(晶振频率),CPU开始执行指令。

但实际上,FCLK可以高于Fin,为了提高系统时钟,需要用软件来启用PLL。

这就需要设置CLKDIVN,MPLLCON,UPLLCON这3个寄存器。

(7)关闭MMU,cache(cpu/arm920t/start.S)

#ifndefCONFIG_SKIP_LOWLEVEL_INIT【是不是跳过低水平初始化?

blcpu_init_crit【它不是函数,它是个代码段,在start.S】

#endif

cpu_init_crit这段代码在U-Boot正常启动时才需要执行,若将U-Boot从RAM中启动则应该注释掉这段代码。

下面分析一下cpu_init_crit到底做了什么:

320#ifndefCONFIG_SKIP_LOWLEVEL_INIT

321cpu_init_crit:

322/*

323*使数据cache与指令cache无效*/

324*/

325movr0,#0

326mcrp15,0,r0,c7,c7,0/*向c7写入0将使ICache与DCache无效*/

327mcrp15,0,r0,c8,c7,0/*向c8写入0将使TLB失效*/

328

329/*

330*禁止MMU的功能和高速缓存

331*/

332mrcp15,0,r0,c1,c0,0/*读出控制寄存器到r0中*/

333bicr0,r0,#0x00002300@clearbits13,9:

8(--V---RS)

334bicr0,r0,#0x00000087@clearbits7,2:

0(B----CAM)

335orrr0,r0,#0x00000002@setbit2(A)Align

336orrr0,r0,#0x00001000@setbit12(I)I-Cache

337mcrp15,0,r0,c1,c0,0/*保存r0到控制寄存器*/

339/*

340*在拷贝代码之前,必须设置RAM的时序

341*因为内存的时序是板时效关系,你会发现lowlevel_init.S,在你的板子目录。

343*/

344movip,lr

345

346bllowlevel_init【位置=/board/GT2440/lowlevel_init.S】

347

348movlr,ip

349movpc,lr

350#endif/*CONFIG_SKIP_LOWLEVEL_INIT*/

代码中的c0,c1,c7,c8都是ARM920T的协处理器CP15的寄存器。

其中c7是cache控制寄存器,c8是TLB控制寄存器。

325~327行代码将0写入c7、c8,使Cache,TLB内容无效。

第332~337行代码关闭了MMU。

这是通过修改CP15的c1寄存器来实现的。

(8)初始化RAM控制寄存器(board/samsung/mini2440/lowlevel_init.S)

由于内存初始化是依赖于开发板的,因此lowlevel_init的代码一般放在board下面相应的目录中。

45#defineBWSCON0x48000000/*13个存储控制器的开始地址*/

……

129_TEXT_BASE:

130.wordTEXT_BASE

132.globllowlevel_init

133lowlevel_init:

134/*存储器控制设置*/

135/*maker0relativethecurrentlocationsothatit*/

136/*readsSMRDATAoutofFLASHratherthanmemory!

*/

137ldrr0,=SMRDATA

138ldrr1,_TEXT_BASE

139subr0,r0,r1/*SMRDATA减_TEXT_BASE就是13个寄存器的偏移地址*/

140ldrr1,=BWSCON/*BusWidthStatusController*/

141addr2,r0,#13*4

1420:

143ldrr3,[r0],#4/*将13个寄存器的值逐一赋值给对应的寄存器*/

144strr3,[r1],#4

145cmpr2,r0

146bne0b

147

148/*现在一切都很好*/

149movpc,lr

150

151.ltorg

152/*文字池起源*/

153

154SMRDATA:

/*下面是13个寄存器的值*/

155.word……

156.word……

……

lowlevel_init初始化了13个寄存器来实现RAM时钟的初始化。

lowlevel_init函数对于U-Boot从NANDFlash或NORFlash启动的情况都是有效的。

board/samsung/mini2440/lowlevel_init.o将被链接到cpu/arm920t/start.o后面,因此board/samsung/mini2440/lowlevel_init.o也在U-Boot的前4KB的代码中。

由于NORFlash的开始地址是0,而U-Boot的加载到内存的起始地址是TEXT_BASE,SMRDATA标号在Flash的地址就是SMRDATA-TEXT_BASE。

(9)复制U-Boot第二阶段代码到RAM(cpu/arm920t/start.S)[配置nand启动]

cpu/arm920t/start.S原来的代码是只支持从NORFlash启动的,经过修改现在U-Boot在NORFlash和NANDFlash上都能启动了,实现的思路是这样的:

blbBootFrmNORFlash/*判断U-Boot是在NANDFlash还是NORFlash启动*/

cmpr0,#0/*r0存放bBootFrmNORFlash函数返回值,若返回0表

示NANDFlash启动,否则表示在NORFlash启动*/

beqnand_boot/*跳转到NANDFlash启动代码*/

/*NORFlash启动的代码*/

Bstack_setup/*跳过NANDFlash启动的代码*/

nand_boot:

/*NANDFlash启动的代码*/

stack_setup:

/*其他代码*/

bBootFrmNORFlash函数在board/samsung/mini2440/nand_read.c中定义。

intbBootFrmNORFlash(void)

{

volatileunsignedint*pdw=(volatileunsignedint*)0;

unsignedintdwVal;

dwVal=*pdw;/*先记录下原来的数据*/

*pdw=0x12345678;

if(*pdw!

=0x12345678)/*写入失败,说明是在NORFlash启动*/

{

return1;

}

else/*写入成功,说明是在NANDFlash启动*/

{

*pdw=dwVal;/*恢复原来的数据*/

return0;

}

}

下面来分析NORFlash启动部分代码:

208adrr0,_start/*r0<-currentpositionofcode*/

209ldrr1,_TEXT_BASE/*testifwerunfromflashorRAM*/

/*判断U-Boot是否是下载到RAM中运行,若是,则不用再复制到RAM中了,这种情况通常在调试U-Boot时才发生*/

210cmpr0,r1/*_start等于_TEXT_BASE说明是下载到RAM中运行*/

211beqstack_setup

212/*以下直到nand_boot标号前都是NORFlash启动的代码*/

213ldrr2,_armboot_start

214ldrr3,_bss_start

215subr2,r3,r2/*r2<-sizeofarmboot*/

216addr2,r0,r2/*r2<-sourceendaddress*/

217/*搬运U-Boot自身到RAM中*/

218copy_loop:

219ldmiar0!

{r3-r10}/*从地址为[r0]的NORFlash中读入8个字的数据*/

220stmiar1!

{r3-r10}/*将r3至r10寄存器数据复制给地址为[r1]的内存*/

221cmpr0,r2/*untilsourceendaddreee[r2]*/

222blecopy_loop

223bstack_setup/*跳过NANDFlash启动的代码*/

下面再来分析NANDFlash启动部分代码:

nand_boot:

movr1,#NAND_CTL_BASE

ldrr2,=((7<<12)|(7<<8)|(7<<4)|(0<<0))

strr2,[r1,#oNFCONF]/*设置NFCONF寄存器*/

/*设置NFCONT,初始化ECC编/解码器,禁止NANDFlash片选*/

ldrr2,=((1<<4)|(0<<1)|(1<<0))

strr2,[r1,#oNFCONT]

ldrr2,=(0x6)/*设置NFSTAT*/

strr2,[r1,#oNFSTAT]

/*复位命令,第一次使用NANDFlash前复位*/

movr2,#0xff

strbr2,[r1,#oNFCMD]

movr3,#0

/*为调用C函数nand_read_ll准备堆栈*/

ldrsp,DW_STACK_START

movfp,#0

/*下面先设置r0至r2,然后调用nand_read_ll函数将U-Boot读入RAM*/

ldrr0,=TEXT_BASE/*目的地址:

U-Boot在RAM的开始地址*/

movr1,#0x0/*源地址:

U-Boot在NANDFlash中的开始地址*/

movr2,#0x30000/*复制的大小,必须比u-boot.bin文件大,并且必须是NANDFlash块大小的整数倍,这里设置为0x30000(192KB)*/

blnand_read_ll/*跳转到nand_read_ll函数,开始复制U-Boot到RAM*/

tstr0,#0x0/*检查返回值是否正确*/

beqstack_setup

bad_nand_read:

loop2:

bloop2//infiniteloop

.align2

DW_STACK_START:

.wordSTACK_BASE+STACK_SIZE-4

其中NAND_CTL_BASE,oNFCONF等在include/configs/mini2440.h中定义如下:

#defineNAND_CTL_BASE0x4E000000//NANDFlash控制寄存器基址

#defineSTACK_BASE0x33F00000//栈基地址baseaddressofstack

#defineSTACK_SIZE0x8000//栈长度

#defineoNFCONF0x00/*NFCONF相对于NAND_CTL_BASE偏移地址*/

#defineoNFCONT0x04/*NFCONT相对于NAND_CTL_BASE偏移地址*/

#defineoNFADDR0x0c/*NFADDR相对于NAND_CTL_BASE偏移地址*/

#defineoNFDATA0x10/*NFDATA相对于NAND_CTL_BASE偏移地址*/

#defineoNFCMD0x08/*NFCMD相对于NAND_CTL_BASE偏移地址*/

#defineoNFSTAT0x20/*NFSTAT相对于NAND_CTL_BASE偏移地址*/

#defineoNFECC0x2c/*NFECC相对于NAND_CTL_BASE偏移地址*/

(10)设置堆栈(cpu/arm920t/start.S)

/*设置堆栈*/

stack_setup:

ldrr0,_TEXT_BASE/*upper128KiB:

relocateduboot*/

subr0,r0,#CONFIG_SYS_MALLOC_LEN/*堆区*/

subr0,r0,#CONFIG_SYS_GBL_DATA_SIZE/*跳过全局数据区*/

#ifdefCONFIG_USE_IRQ

subr0,r0,#(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

subsp,r0,#12/*从中断栈删除3字*/

(11)清除BSS段(cpu/arm920t/start.S)

clear_bss:

ldrr0,_bss_start/*BSS段开始地址,在u-boot.lds中指定*/

ldrr1,_bss_end/*BSS段结束地址,在u-boot.lds中指定*/

movr2,#0x00000000

clbss_l:

strr2,[r0]/*将bss段清零*/

addr0,r0,#4

cmpr0,r1

bleclbss_l

(12)跳转到第二阶段代码入口(cpu/arm920t/start.S)

ldrpc,_start_armboot

_start_armboot:

.wordstart_armboot/*跳转到第二阶段代码入口start_armboot处*/

U-Boot启动第二阶段代码分析:

voidstart_armboot(void);//(lib_arm/board.c)236行,是第二阶段代码的入口;

staticintdisplay_banner(void);//(lib_arm/board.c)

staticintdisplay_dram_config(void);//(lib_arm/board.c)

staticvoiddisplay_flash_config(ulongsize);//(lib_arm/board.c)

voidmain_loop(void);//(common/main.c)

这些函数在start_armboot()函数中被调用,用紫色标记出来了。

===================================================================================

U-Boot使用了一个结构体gd_t来存储全局数据区的数据,这个结构体在include/asm-arm/global_data.h中定义如下:

typedefstructglobal_data{

bd_t*bd;

unsignedlongflags;

unsignedlongbaudrate;

unsignedlonghave_console;/*串口初始化是被调用*/

unsignedlongreloc_off;/*重定位偏移*/

unsignedlongenv_addr;/*环境变量结构体的地址*/

unsignedlongenv_valid;/*环境变量校验有效吗?

*/

unsignedlongfb_base;/*帧缓冲器得基地址*/

#ifdefCONFIG_VFD

unsignedcharvfd_type;/*显示类型*/

#endif

#if0

unsignedlongcpu_clk;/*CPU时钟*/

unsignedlongbus_clk;

unsignedlongram_size;/*RAM尺寸*/

unsignedlongreset_status;/*在启动时,复位状态寄存器*/

#endif

void**jt;/*跳跃表*/

}gd_t;

U-Boot使用了一个存储在寄存器中的指针gd来记录全局数据区的地址:

#defineDECLARE_GLOBAL_DATA_PTRregistervolatilegd_t*gdasm("r8")

DECLARE_GLOBAL_DATA_PTR定义一个gd_t全局数据结构的指针,这个指针存放在指定的寄存器r8中。

这个声明也避免编译器把r8分配给其它的变量。

任何想要访问全局数据区的代码,只要代码开头加入“DECLARE_GLOBAL_DATA_PTR”一行代码,然后就可以使用gd指针来访问全局数据区了。

【貌似移植Uboot时需要使用全局数据区,在使用前添加了DECLARE_GLOBAL_DATA_PTR】

======================================

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1