嵌入式uboot学习报告.docx
《嵌入式uboot学习报告.docx》由会员分享,可在线阅读,更多相关《嵌入式uboot学习报告.docx(34页珍藏版)》请在冰豆网上搜索。
![嵌入式uboot学习报告.docx](https://file1.bdocx.com/fileroot1/2022-12/13/85d4f468-ebe9-405b-bcf2-b39c793b7c99/85d4f468-ebe9-405b-bcf2-b39c793b7c991.gif)
嵌入式uboot学习报告
1.u-boot简介
1.1.概述
U-Boot,全称UniversalBootLoader,是遵循GPL条款的开放源码项目,从FADSROM、8xxROM、PPCBOOT逐步发展演化而来,其源码目录、编译形式与Linux内核很相似。
事实上,不少U-Boot源码就是相应Linux内核源程序的简化,尤其是一些设备的驱动程序,从UBoot源码的注释中能体现这一点。
但是U-Boot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS嵌入式操作系统。
其目前要支持的目标操作系统包括OpenBSD、NetBSD、FreeBSD、4.4BSD、Linux、SVR4、Esix、Solaris、Irix、SCO、Dell、NCR、VxWorks、LynxOS、pSOS、QNX、RTEMS和ARTOS。
这是U-Boot中Universal的一层含义。
另外一层含义则是U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、x86、ARM、Nios、xScale等诸多常用系列的处理器。
这两个特点正是U-Boot项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入式操作系统。
就目前来看,U-Boot对PowerPC系列处理器支持最为丰富,对Linux的支持最完善。
其它系列的处理器和操作系统基本是在2002年11月PPCBOOT改名为U-Boot后逐步扩充的。
从PPCBOOT向U-Boot的顺利过渡,很大程度上归功于U-Boot的维护人,德国DENX软件工程中心的WolfgangDenk(以下简称W.D)本人精湛的专业水平和持着不懈的努力。
当前,U-Boot项目在他的领军下,众多有志于开放源码Bootloader移植工作的嵌入式开发人员,正如火如荼地将各个不同系列嵌入式处理器的移植工作不断展开和深入,以支持更多嵌入式操作系统的装载与引导。
1.2.U-Boot主要目录结构
board——目标板相关文件,主要包含SDRAM、Flash驱动;
common——独立于处理器体系结构的通用代码,如内存大小探测与故障检测;
cpu——与处理器相关的文件,如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件;
driver——通用设备驱动,如CFIFlash驱动(目前对IntelFlash支持较好)
doc——U-Boot的说明文档;
examples——可在U-Boot下运行的示例程序;如 helloworld.c,timer.c;
include——U-Boot头文件,configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件;
lib_xxx——处理器体系相关的文件,如lib—ppc,lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件;
net——与网络功能相关的文件目录,如bootp、nfs、tftp;
post——上电自检文件目录,尚有待于进一步完善;
rtc——RTC驱动程序;
tools——用于创建U-BootS-RECORD和BIN镜像文件的工具。
1.3.U-Boot支持的主要功能
U-Boot可支持的主要功能如表1所列。
表格1
系统引导
支持NFS挂载、RAMDISK(压缩或非压缩)形式的根文件系统
支持NTS挂载,从Flash中引导压缩或非压缩系统内核
基本辅助功能
强大的操作系统接口功能,可灵活设置、传递多个关键参数给操作系统,适合系统在不同开发阶段的调试要求与产品发布,尤其对Linux支持最为强劲
支持目标板环境参数的多种存储方式,如Flash、NVRAIvl、EEPROM
CRC32校验,可校验Flash中内核、RAMDISK镜像文件是否完好
设备驱动
串口、SDRAM、Flash、以太网、LCD、NVRA/vl、EEPROM、键盘、JSB、PCMCIA、PCI、RTC等驱动支持
上电自检功能
SDRAM、Flash大小自动检测;SDRAM故障检测:
CPLy型号
特殊功能
xⅢ内核引导
2.u-boot启动过程
2.1.启动模式
Bootloader启动模式通常有两种:
启动加载模式和下载模式。
u-boot作为bootloader的一种也不例外。
启动加载模式:
整个系统启动过程是自主的,完全没有人的干预。
下载模式:
linux内核在加载时有开发人员控制,通过串口或者网络进行加载的方式。
对于普通用户来说,一般都用在启动加载模式,但是对于开发人员来数,则需要运行在下载模式下,因为开发过程中需要经常更新镜像。
为了达到两者兼顾的目的,通常,采用两种模式相结合的方式。
复位后,bootloader首先进行初始化工作,结束后不是立刻加载linux镜像,而是等待一段时间,如果用户有键盘输入,就进入下载模式,否则进入启动加载模式。
2.2.启动的阶段
u-boot启动分为两个阶段。
第一阶段主要针对与CPU体系结构和存储设备密切相关部分作一些必要的初始化工作,是一些依赖于CPU结构的代码,为了增加效率以及涉及到处理器的设置,只能采用汇编语言编写。
第二阶段主要针对目标板一级的一些初始化工作并且提供一些驱动的支持,用c语言实现。
2.3.启动代码分析
首先我们整体上浏览下u-boot启动代码的流程图。
下面详细分析各个阶段中代码的具体工作。
1.Start.S
源码位置:
cpu/arm920t/start.S
运行位置:
Flash
描述:
一个可执行的映像有且只有一个全局入口。
这个入口点为处理器复位取第一条指令的位置。
U-boot映像的入口就是start.S。
这个可以通过board/smdk2410/u-boot.lds连接脚本文件决定。
.globl_start
_start:
breset//复位向量
ldrpc,_undefined_instruction
ldrpc,_software_interrupt
ldrpc,_prefetch_abort
ldrpc,_data_abort
ldrpc,_not_used
ldrpc,_irq
ldrpc,_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//快速中断向量
_TEXT_BASE:
.wordTEXT_BASE
.globl_armboot_start
_armboot_start:
.word_start
/*
*Thesearedefinedintheboard-specificlinkerscript.
*/
.globl_bss_start
_bss_start:
.word__bss_start
.globl_bss_end
_bss_end:
.word_end
#ifdefCONFIG_USE_IRQ
/*IRQstackmemory(calculatedatrun-time)*/
.globlIRQ_STACK_START
IRQ_STACK_START:
.word0x0badc0de
/*IRQstackmemory(calculatedatrun-time)*/
.globlFIQ_STACK_START
FIQ_STACK_START:
.word0x0badc0de
#endif
/*
*theactualresetcode
*/
reset:
//复位启动子程序
/*设置CPU为SVC32模式*/
mrsr0,cpsr
bicr0,r0,#0x1f
orrr0,r0,#0xd3
msrcpsr,r0
/*关闭看门狗*/
#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]
/*
*maskallIRQsbysettingallbitsintheINTMR-default
*/
movr1,#0xffffffff
ldrr0,=INTMSK
strr1,[r0]
#ifdefined(CONFIG_S3C2410)
ldrr1,=0x3ff
ldrr0,=INTSUBMSK
strr1,[r0]
#endif
/*FCLK:
HCLK:
PCLK=1:
2:
4*/
/*defaultFCLKis120MHz!
*/
ldrr0,=CLKDIVN
movr1,#3
strr1,[r0]
#endif/*CONFIG_S3C2400||CONFIG_S3C2410*/
/*
关键的初始化代码在系统重启是执行,而在热复位也就是直接从RAM中启动不执行
*/
#ifndefCONFIG_SKIP_LOWLEVEL_INIT
blcpu_init_crit
#endif
#ifndefCONFIG_SKIP_RELOCATE_UBOOT
relocate:
/*把u-boot重新定位到RAM*/
adrr0,_start/*把代码的当前位置也就是需要复制代码的起始地址放到r0*/
ldrr1,_TEXT_BASE/*测试启动从Flash还是RAM*/
cmpr0,r1/*比较r0和r1,调试的时候也就是都是从RAM启动*/
beqstack_setup/*的情况下,不需要重定位,跳过重定位代码*/
ldrr2,_armboot_start/*准备重新定位代码,得到_armboot_start的位置*/
ldrr3,_bss_start/*得到_bss_start的位置*/
subr2,r3,r2/*r2为arm_boot的大小*/
addr2,r0,r2/*r2得到需要复制代码的末尾地址*/
copy_loop:
/*重新定位代码,也就是执行从代码从flash到RAM的拷贝工作*/
ldmiar0!
{r3-r10}/*copyfromsourceaddress[r0]*/
stmiar1!
{r3-r10}/*copytotargetaddress[r1]*/
cmpr0,r2/*untilsourceendaddreee[r2]*/
blecopy_loop
#endif/*CONFIG_SKIP_RELOCATE_UBOOT*/
/*初始化堆栈*/
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
subsp,r0,#12/*为abort-stack预留3个字*/
clear_bss:
ldrr0,_bss_start/*找到bss段起始地址*/
ldrr1,_bss_end/*bss段的末尾地址*/
movr2,#0x00000000/*清零*/
clbss_l:
strr2,[r0]/*bss段地址空间循环清零*/
addr0,r0,#4
cmpr0,r1
bleclbss_l
/*跳转到start_armboot函数入口,_start_armboot字保存函数的入口地址*/
ldrpc,_start_armboot
_start_armboot:
.wordstart_armboot
#ifndefCONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*关键的初始化程序*/
/*
初始化CACHE
*/
movr0,#0
mcrp15,0,r0,c7,c7,0/*flushv3/v4cache*/
mcrp15,0,r0,c8,c7,0/*flushv4TLB*/
/*
*关闭MMU和CACHE
*/
mrcp15,0,r0,c1,c0,0
bicr0,r0,#0x00002300@clearbits13,9:
8(--V---RS)
bicr0,r0,#0x00000087@clearbits7,2:
0(B----CAM)
orrr0,r0,#0x00000002@setbit2(A)Align
orrr0,r0,#0x00001000@setbit12(I)I-Cache
mcrp15,0,r0,c1,c0,0
/*
*beforerelocating,wehavetosetupRAMtiming
*becausememorytimingisboard-dependend,youwill
*findalowlevel_init.Sinyourboarddirectory.
*/
movip,lr
bllowlevel_init
movlr,ip
movpc,lr
#endif/*CONFIG_SKIP_LOWLEVEL_INIT*/
/*
*************************************************************************
*
*中断向量
*
*************************************************************************
*/
@
@IRQstackframe.
@
#defineS_FRAME_SIZE72
#defineS_OLD_R068
#defineS_PSR64
#defineS_PC60
#defineS_LR56
#defineS_SP52
#defineS_IP48
#defineS_FP44
#defineS_R1040
#defineS_R936
#defineS_R832
#defineS_R728
#defineS_R624
#defineS_R520
#defineS_R416
#defineS_R312
#defineS_R28
#defineS_R14
#defineS_R00
#defineMODE_SVC0x13
#defineI_BIT0x80
/*
*usebad_save_user_regsforabort/prefetch/undef/swi...
*useirq_save_user_regs/irq_restore_user_regsforIRQ/FIQhandling
*/
.macrobad_save_user_regs
subsp,sp,#S_FRAME_SIZE
stmiasp,{r0-r12}@Callingr0-r12
ldrr2,_armboot_start
subr2,r2,#(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
subr2,r2,#(CFG_GBL_DATA_SIZE+8)@setbase2wordsintoabortstack
ldmiar2,{r2-r3}@getpc,cpsr
addr0,sp,#S_FRAME_SIZE@restoresp_SVC
addr5,sp,#S_SP
movr1,lr
stmiar5,{r0-r3}@savesp_SVC,lr_SVC,pc,cpsr
movr0,sp
.endm
.macroirq_save_user_regs
subsp,sp,#S_FRAME_SIZE
stmiasp,{r0-r12}@Callingr0-r12
addr8,sp,#S_PC
stmdbr8,{sp,lr}^@CallingSP,LR
strlr,[r8,#0]@SavecallingPC
mrsr6,spsr
strr6,[r8,#4]@SaveCPSR
strr0,[r8,#8]@SaveOLD_R0
movr0,sp
.endm
.macroirq_restore_user_regs
ldmiasp,{r0-lr}^@Callingr0-lr
movr0,r0
ldrlr,[sp,#S_PC]@GetPC
addsp,sp,#S_FRAME_SIZE
subspc,lr,#4@return&movespsr_svcintocpsr
.endm
.macroget_bad_stack
ldrr13,_armboot_start@setupourmodestack
subr13,r13,#(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
subr13,r13,#(CFG_GBL_DATA_SIZE+8)@reservedacouplespotsinabortstack
strlr,[r13]@savecallerlr/spsr
mrslr,spsr
strlr,[r13,#4]
movr13,#MODE_SVC@prepareSVC-Mode
@msrspsr_c,r13
msrspsr,r13
movlr,pc
movspc,lr
.endm
.macroget_irq_stack@setupIRQstack
ldrsp,IRQ_STACK_START
.endm
.macroget_fiq_stack@setupFIQstack
ldrsp,FIQ_STACK_START
.endm
/*
*异常向量
*/
.align5
undefined_instruction:
get_bad_stack
bad_save_user_regs
bldo_undefined_instruction
.align5
software_interrupt:
get_bad_stack
bad_save_user_regs
bldo_software_interrupt
.align5
prefetch_abort:
get_bad_stack
bad_save_user_regs
bldo_prefetch_abort
.align5
data_abort:
get_bad_stack
bad_save_user_regs
bldo_data_abort
.align5
not_used:
get_bad_stack
bad_save_user_regs
bldo_not_used
#ifdefCONFIG_USE_IRQ
.align5
irq:
get_irq_stack
irq_save_user_regs
bldo_irq
irq_restore_user_regs
.align5
fiq:
get_fiq_stack
/*someoneoughttowriteamoreeffictionfiq_save_user_regs*/
irq_save_user_regs
bldo_fiq
irq_restore_user_regs
#else
.align5
irq:
get_bad_stack
bad_save_user_regs
bldo_irq
.align5
fiq:
get_bad_stack
bad_save_user_regs
bldo_fiq
#endif
2.Board.c
源码位置:
lib_arm/board.c
运行位置:
SDRAM
描述:
start_armboard()是u-boot运行的第一个c语言函数,完成系统的初始化工作,进入主循环,处理用户的命令。
voidstart_armboot(void)
{
init_fnc_t**init_fnc_ptr;
char*s;
#if