本文讲述uboot引导内核启动的全部过程,uboot版本为2010.06
1、arch/arm/cpu/hi3536/u-boot.lds
连接文件,不同平台不一样。
OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm", "elf32-littlearm") //elf格式 32位,小端
OUTPUT_ARCH(arm)//arm架构
ENTRY(_start)//代码进入点arch/arm/cpu/hi3536/start.S中定义,一切从这里开始
SECTIONS
{
.= 0x00000000; //可执行文件入口地址
.= ALIGN(4);
.text ://代码段
{
__text_start = .;
arch/arm/cpu/hi3536/start.o (.text)
drivers/ddr/ddr_training_impl.o (.text)
drivers/ddr/ddr_training_ctl.o (.text)
drivers/ddr/ddr_training_boot.o (.text)
drivers/ddr/ddr_training_custom.o (.text)
__init_end = .;
ASSERT(((__init_end - __text_start) < 0x16000), "init sectionstoo big!");
*(.text)
}
.= ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } //只读数据段
.= ALIGN(4);
.data : { *(.data) } //数据段
.= ALIGN(4);
.got : { *(.got) }
__u_boot_cmd_start = .; //存放uboot命令
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
.= ALIGN(4);
__bss_start = .; //bss段
.bss : { *(.bss) }
_end = .;
}
2、arch/arm/cpu/hi3536/start.S
Arm在uboot下的入口文件,纯汇编,由于代码太多,这里描述基本过程:
(1)定义入口
.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
(2)进入reset第一步
A. set the cpu to SVC32 mode
B. Invalidate L1 I/D
C. Invalidate L1 D-cache
D. disable MMU stuff and caches
(3)第二步
判断boot方式,从bootrom / spi /nand中的一种启动,撤销地址空间映射。
假设启动方式为spi nor flash启动,这时起始地址空间映射到spi nor flash地址空间,但是spi nor flash不能直接执行代码,这里猜测是:映射后硬件自己从spi nor flash中将部分代码搬运到内部开始执行。
(4)第三步
进行pll /flash/ddr等的初始化
(5)第4步
拷贝flash数据到DDR空间。在这步之前只是搬运了初始化用的最基本的部分到内部,但是整个uboot并未搬运到DDR,这里则进行完整的搬运:r1-DDR地址0x40c00000(src/board/hi3536/config.mk中定义),r0-flash地址为spi地址,r2大小为_bss_start- _armboot_start(_start),memcpy(r1, r0, r2)。内存布局见第8节
根据uboot.map可以看到连接收地址发生了变化从0x40c00000开始,修改这个的地方由底层的config.mk完成:
LDFLAGS += -Bstatic -T $(obj)u-boot.lds$(PLATFORM_LDFLAGS)
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)
endif
连接地址替换成TEXT_BASE(src/board/hi3536/config.mk定义)
(6)第5步
跳转到DDR,进入第一个C语言入口
clbss_l:
str r2, [r0] @ clear BSSlocation
cmp r0, r1 @ are we atthe end yet
add r0, r0, #4 @ incrementclear index pointer
bne cl