本篇文章梳理了一下对正点原子的驱动开发教程中u-boot启动流程的梳理,制作了一份流程图,并简单的记录了一下各函数的作用,方便回头翻阅。
一、U-boot启动过程流程图
二、U-boot启动过程函数简单注释
u-boot启动过程中_main函数中调用的各函数作用:
save_boot_params_ret:设置CPU处于SVC32 模式,并且关闭FIQ和IRQ这两个中断,设置允许向量表重定位
lowlevel_init:设置sp指针指向的地址
board_init_f_alloc_reserve:主要是留出早期的malloc内存区域和gd内存区域
board_init_f_init_reserve:此函数用于初始化gd
board_init_f:此函数主要用来初始化DDR、定时器、完成代码拷贝(把u-boot的代码拷贝到内存最后面,但是不做拷贝工作,只计算应该拷贝的位置)等等
relocate_code:代码重定位函数,此函数负责将uboot拷贝到新的地址去
relocate_vector:重定位向量表,将新的向量表首地址(就是uboot的新地址的首地址)写入到寄存器VBAR中,设置向量表偏移
c_runtime_cpu_setup:此函数主要进行两个工作:设置函数board_init_r的两个参数和调用board_init_r函数
board_init_r:完成board_init_f剩余的一些外设初始化工作
main_loop: 就是u-boot开头倒计时用的,如果倒计时结束前按下按键就会进入cli_loop函数
如果按下按键:
-->cli_loop:主要是调用parse_stream_outer函数
-->parse_stream_outer:是hush shell的命令解释器,负责接收命令行输入,解析并执行相应的命令。
-->cmd_process:最终真正执行命令解析和执行相应操作的函数。
如果没有按下按键:
-->do_bootz:启动内核,主要调用bootz_start和do_bootm_states函数
-->bootz_start:主要用于初始化结构体变量images的相关成员变量
-->do_bootm_state:会调用一次do_bootm_states执行BOOTM_STATE_START阶段
-->bootz_setup:判断当前系统镜像文件是否为Linux镜像
-->bootm_find_images:查找ramdisk和设备树,不用ramdisk的时候这个函数只用来查找设备树,初始化images下设备树相关的成员变量
-->do_bootm_states:处理BOOTM_STATE_START、BOOTM_STATE_OS_PREP、BOOTM_STATE_OS_GO三种状态
-->bootm_start:处理BOOTM_STATE_START状态,清零images
-->bootm_os_get_boot_func :查找对应系统的启动函数,Linux的启动函数为do_bootm_linux
并将该函数赋给函数指针boot_fn
-->boot_fn:已经变成了do_bootm_linux,处理BOOTM_STATE_OS_PREP、BOOTM_STATE_OS_GO
这俩状态
-->boot_prep_linux:处理BOOTM_STATE_OS_PREP状态,主要用于处理环境变量bootargs,bootargs
保存着传递给Linux kernel的参数,如果使用设备树会添加bootargs节点。
设备树地址(若启用设备树)或bootargs地址会放在r2寄存器中传给kernel的启动函数
-->boot_jump_linux:处理BOOTM_STATE_OS_GO状态,最终执行Linux的kernel_entry函数-->内核启动!!
Tips:
1. gd是一个指针,指向一个gd_t类型(定义在include/asm-generic/global_data.h中)的结构体
2. images是文件cmd/bootm.c下定义的一个bootm_headers类型的全局变量,里面存放着一些系统镜像、设备树相关的信息。
附几张图:
lowlevel_init后:
board_init_f_alloc_reserve后:
board_init_f后: