bootloader是系统上电后最初加载运行的代码。它提供了处理器上电复位后最开始需要执行的初始化代码。在PC机上引导程序一般由BIOS开始执行,然后读取硬盘中位于MBR(Main Boot Record,主引导记录)中的Bootloader(例如LILO或GRUB),并进一步引导操作系统的启动。然而在嵌入式系统中通常没有像BIOS那样的固件程序,因此整个系统的加载启动就完全由bootloader来完成。它主要的功能是加载与引导内核映像 。
初始化CPU,初始化内存、串口、时钟等硬件资源,加载内核、引导内核,为操作系统的运行提供环境准备
1、第一阶段依赖于cpu体系结构的代码,从存储介质中读取小部分程序到cpu中,这部分程序要完成引导linux所用的硬件的初始化以及加载uboot其余程序到RAM中
2、继续初始化必备硬件,加载linux镜像到RAM中,把执行权限交给linux
目录结构:
启动流程代码分析:
.globl _start //初始化中断向量表
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
reset:
/*
* set the cpu to SVC32 mode //切换CPU模式为SVC模式,关闭中断,以便访问更多硬件资源
*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
/*
* disable MMU stuff and caches //关闭MMU与caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB
mcr p15, 0, r0, c1, c0, 0
after_ziju:
/* init PLL/DDRC/pin mux/... */ //初始化时钟、内存、IO
ldr r0, _blank_zone_start
ldr r1, _TEXT_BASE
sub r0, r0, r1
cmp r3, r2
beq pcie_slave_addr
ldr r1, =RAM_START_ADRS
ldr sp, =STACK_TRAINING
b ziju_ddr_init
pcie_slave_addr:
ldr r1, =0x0
ldr sp, =PCIE_SLV_STACK
ldr r4, =SYS_CTRL_REG_BASE
str r2, [r4, #HI3531D_SYSBOOT10]
ziju_ddr_init:
add r0, r0, r1
mov r1, #0x0 /* flags: 0->normal 1->pm */
bl init_registers /* init PLL/DDRC/... */
copy_loop: @ copy 32 bytes at a time //循环拷贝u-boot到内存
ldmia r0!, {
r3 - r10} @ copy from source address [r0]
stmia r1!, {
r3 - r10} @ copy to target address [r1]
cmp r0, r2 @ until source end addreee [r2]
ble copy_loop
/* Set up the stack */ //设置堆栈
stack_setup:
ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot
sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area
sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 @ leave 3 words for abort-stack
and sp, sp, #~7 @ 8 byte alinged for (ldr/str)d
ldr pc, _start_armboot @ jump to C code //跳转到start_armboot函数执行
_start_armboot: .word start_armboot
void start_armboot (void)
/* Pointer is writable since we allocated a register for it */
gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t))