u-boot 启动流程 广州创龙电子科技有限公司 Guangzhou Tronlong Electronic Technology Co., Ltd
01 u-boot 启动流程概述 02 u-boot 启动第一阶段 03 u-boot 启动第二阶段
01 u-boot 启动流程概述 第 1 部分
u-boot 启动流程概述 u-boot启动分为stage1和stage2两个阶段: stage1通常是开发板的配置等设备初始化代码,需要依赖于SoC体系结构,通常用汇编语言来实现。 stage2阶段主要是对外部设备如网卡、Flash等的初始化以及u-boot命令集等的自身实现,通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。 04 广州创龙电子科技有限公司
u-boot 启动流程概述 stage1 (start.S代码结构) (1) 定义入口。系统复位转入u-boot的stage1入口点,通常这个入口放在rom(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。 (2)设置异常向量。 (3)设置CPU的速度、时钟频率及中断控制寄存器。 (4)初始化内存控制器 ,为stage2准备RAM空间。 (5)将u-boot的stage2拷贝到到RAM中。 (6)初始化堆栈 、数据段。 (7)转到stage2的入口点。 加入图片-uboot-vivi-redboot等 05 广州创龙电子科技有限公司
u-boot 启动流程概述 stage2 (c语言代码部分) (1)初始化本阶段使用的硬件设备。 (2)初始化系统内存。 (3)将kernel和文件系统映射从Flash读取到RAM中。 (4)为内核设置启动参数。 (5)调用内核。 加入图片-uboot-vivi-redboot等 06 广州创龙电子科技有限公司
02 u-boot 启动第一阶段 第 2 部分
u-boot 启动第一阶段 1. _start _start是u-boot启动后的第一个执行地址。对于任何程序,入口函数是在链接时决定的,u-boot的入口是由链接脚本决定的。uboot下链接脚本默认目录为arch/arm/cpu/u-boot.lds。 _start: arch/arm/lib/vectors .S 08 广州创龙电子科技有限公司
u-boot 启动第一阶段 _start: #ifdef CONFIG_SYS_DV_NOR_BOOT_CFG .word CONFIG_SYS_DV_NOR_BOOT_CFG #endif b reset @跳到reset入口 ldr pc, _undefined_instruction @7种异常的入口函数 ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq 09 广州创龙电子科技有限公司
u-boot 启动第一阶段 2. reset 在上电或者重启后,处理器取得第一条指令就是b reset,所以会直接跳转到reset函数处。reset首先是跳转到save_boot_params中。 执行完cpu_init_cp15、cpu_init_crit后跳转到_main。 reset: arch/arm/cpu/armv7/start.S 10 广州创龙电子科技有限公司
u-boot 启动第一阶段 2.1 save_boot_params reset: /* Allow the board to save important registers */ b save_boot_params save_boot_params_ret: /* * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode, * except if in HYP mode already */ mrs r0, cpsr and r1, r0, #0x1f @ mask mode bits teq r1, #0x1a @ test for HYP mode bicne r0, r0, #0x1f @ clear all mode bits orrne r0, r0, #0x13 @ set SVC mode orr r0, r0, #0xc0 @ disable FIQ and IRQ msr cpsr,r0 11 广州创龙电子科技有限公司
u-boot 启动第一阶段 2.2 cpu_init_cp15 cp15是协处理器,该函数是配置cp15协处理器相关寄存器来设置处理器的MMU,cache以及TLBs 。 cpu_init_cp15: arch/arm/cpu/armv7/start.S 12 广州创龙电子科技有限公司
u-boot 启动第一阶段 2.3 cpu_init_crit ENTRY(cpu_init_crit) /* * Jump to board specific initialization... * The Mask ROM will have already initialized * basic memory. Go here to bump up clock rate and handle * wake up conditions. */ b lowlevel_init @ go setup pll,mux,memory ENDPROC(cpu_init_crit) lowlevel_init函数是与特定开发板相关的初始化函数,会做一些pll、pinmux、memory初始化,方便后续拷贝到memory中运行。 cpu_init_cp15: arch/arm/cpu/armv7/start.S 13 广州创龙电子科技有限公司
u-boot 启动第一阶段 3. _main 这个段汇编主要作用是: (1)初始化一个C语言能够运行的环境 (2)bl board_init_f (3)设置堆栈地址 (4)设置全局变量gd结构体 (5)中断向量表的重映射 (6)未初始化段(bss)的清除 (7)最后调用ldr pc, =board_init_r, 跳转到u-boot的第二阶段。 crt0是C-runtime Startup Code的简称,意思就是运行C代码之前的准备工作。 _main: arch/arm/lib/crt0.S 14 广州创龙电子科技有限公司
u-boot 启动第一阶段 3.1 board_init_f 调用init_sequence_f[]数组中的函数,完成一些前期的初始化工作,例如: (a)点亮一个Debug用的LED灯,表示u-boot已经启动。 (b)初始化DRAM、DDR。 (c)初始化调试串口。 (d)打印CPU信息等。 board_init_f: common/board_f.c 15 广州创龙电子科技有限公司
u-boot 启动第一阶段 3.1.1 board_early_init_f board_early_init_f: arch/arm/cpu/armv7/am33xx/board.c 16 广州创龙电子科技有限公司
u-boot 启动第一阶段 3.2 relocate_code 代码重定位,不管从哪里启动,u-boot运行后会将自身代码拷贝到sdram的另一个位置继续运行。旧版的u-boot会通过判断_start和TEXT_BASE(链接地址)是否相等来确定是否需要relocate。 relocate relocate_code: arch/arm/lib/relocate.S 17 广州创龙电子科技有限公司
u-boot 启动第一阶段 跳转运行第二第阶段代码 u-boot代码重定位后,接下来调用board_init_r,这个就是u-boot启动的第二阶段。 relocate 18 广州创龙电子科技有限公司
03 u-boot 启动第二阶段 第 3 部分
u-boot 启动第二阶段 1. board_init_r 调用init_sequence_r[]数组中的函数,完成第二阶段的初始化工作。包括nand flash的初始化,spi flash 等等设备初始化。其中board_init函数是与特定开发板相关的初始化函数。 board_init, initr_nand, initr_mmc, board_init_r: common/board_r.c board_init: board/ti/am437x/board.c 20 广州创龙电子科技有限公司
u-boot 启动第二阶段 2. run_main_loop static int run_main_loop(void) { #ifdef CONFIG_SANDBOX sandbox_main_loop_init(); #endif /* main_loop() can return to retry autoboot, if so just run it again */ for (;;) main_loop(); return 0; } run_main_loop: common/board_r.c 21 广州创龙电子科技有限公司
u-boot 启动第二阶段 3. main_loop bootstage_mark_name() 来标记u-boot的运行状态。 bootdelay_process() 把环境变量bootcmd获取出来,最后将bootcmd的内容返回上层。 cli_process_ftd() 由于该函数永远返回false,因此if判断永远不成立。 autoboot_command() -> abortboot() -> abortboot_normal() -> run_command_list() -> parse_stream_outer() 自启模式。 cli_loop() -> parse_file_outer() -> parse_stream_outer(); u-boot的命令行模式。 main_loop: common/main.c 22 广州创龙电子科技有限公司
u-boot 启动第二阶段 3.1 parse_stream_outer() common/cli_hush.c -> parse_stream_outer() common/cli_hush.c -> run_list() common/cli_hush.c -> run_list_real() common/cli_hush.c -> run_pipe_real() common/command.c -> cmd_process() common/command.c -> cmd_call() 23 广州创龙电子科技有限公司
u-boot 启动第二阶段 3.2 cmd_call() cmd_call()通过一个cmd_tbl_t结构,并调用其一个函数指针进行对实际命令的调用。u-boot的命令位于根目录下的cmd/中。 旧版的uboot命令源码在common/中,每一个命令都以“cmd_”开头的c文件形式存在。 接下来就是解析uboot命令,或者解析uboot启动参数来启动内核。 24 广州创龙电子科技有限公司
广州创龙电子科技有限公司 谢谢 官网:www.tronlong.com 论坛:51ele.net 微信公众号:广州创龙