本章系统的介绍RK3228主板uboot的启动流程
bl board_init_f -> crt0.S
initcall_run_list(init_sequence_f) -> board_f.c
arch_cpu_init ->
rk_get_chiptype //获取chip type (rk31xx, rk32xx等)
timer_init
env_init
init_baud_rate
serial_init
print_cpuinfo //dump cpu/pll info
dram_init //获取size以及end address
setup_dram_config ->
dram_init_banksize
show_dram_config
ldr pc, =board_init_r -> crt0.S
board_init_r -> board_r.c
init_sequence_r //调用init_sequence_r中的各个函数。
board_init rk32xx.c //设置machine type以及boot param起始地址,kernel要用到。
initr_serial -> board_r.c //初始化串口。
serial_initialize
initr_rk_storage -> //初始化storage
board_storage_init -> rk32xx.c
StorageInit -> storage.c //初始化eMMC.
memFunTab[memdev]->Init //调用emmcFunOp的SdmmcInit()
SdmmcInit sdmmcBoot.c 这里还会根据sd里存的信息来区分是要boot还是update.
StorageReadFlashInfo ->
gpMemFun->ReadInfo ->
SdmmcReadFlashInfo sdmmcBoot.c
initr_env //初始化u-boot中的环境变量
stdio_add_devices -> //不做什么。
console_init_r //作为device来管理。
board_late_init -> rk32xx.c
board_init_adjust_env //初始化bootdelay, bootcmd这些env.
load_disk_partitions ->
GetParam
ParseParam -> //解析parameter文件
ParseLine -> //获取各个参数选项,如machine model, cmdline等。
parse_cmdline ->
mtdpart_parse //获取分区表信息
rkimage_prepare_fdt rkimage.c //从boot或者resource image读取fdt地址,resource会覆盖boot.img的fdt.
key_init //各种key init
pmic_init -> power_rockchip.c //多个型号pmic的init,如rk808, rk818,一旦匹配到成功的就不再尝试其他的了。
pmic_act8846_init //sdk board用的是此IC。
pmic_rk808_init -> pmic_rk808.c //后续项目要替换成这颗。
rk808_parse_dt ->
fdt_device_is_available //status为disabled就没必要解析了。
fdt_get_i2c_info //获取i2c address, number,
rk808_i2c_probe //detect pmic.
fdt_get_regulator_node //获取pmic regulator信息
fdt_regulator_match //获取regulator初始化数据
rk808_set_regulator_init //设置各regulator初始化电压
fdtdec_decode_gpios //获取gpio内容, pwr_hold
charger_init
i2c_init
pmic_rk818_init
pwm_regulator_init -> //pwm init.
pwm_regulator_parse_dt
fg_init //gauge init.
SecureBootCheck
board_fbt_preboot ->
fbt_fastboot_init
board_fbt_get_reboot_type //读取reboot flag
board_fbt_key_pressed //再次检查key有没有按下来决定进入哪种模式。
board_fbt_low_power_check //电量检查,过低就充电,如果失败就直接关机.
fdtdec_get_int //读取u-boot是否显示logo值
drv_lcd_init -> lcd.c
lcd_init ->
lcd_ctrl_init -> rockchip_fb.c
rk_fb_parse_dt -> //从dts中解析出lcd的参数。
rk_fb_pwr_enable //上电
rkclk_lcdc_clk_set //设置clock
rk_lcdc_init //lcdc控制器初始化
rk_lcdc_load_screen //根据不同的接口设置不同的配置到控制器
lcd_clear ->
lcd_logo -> //show logo
bitmap_plot ->
rk_bitmap_from_resource ->
show_resource_image -> //name是logo.bmp
get_content ->
get_base_offset //先从resoure分区获取,失败的话从boot分区获取.
lcd_display_bitmap_center
board_fbt_low_power_off //如果是低电量而且没在充电,那就显示fail的logo,1s后关机.
lcd_standby
rk_backlight_ctrl
board_fbt_run_recovery //进recovery的情况
board_fbt_run_recovery_wipe_data //wipe data的情况,也是进recovery
board_fbt_request_start_fastboot //进fastboot mode
rkloader_run_misc_cmd //其他情况
run_main_loop ->
main_loop //启动kernel
do_bootrk -> cmd_bootrk.c
rk_load_image_from_storage ->
rkimage_load_image //先尝试从boot.img读取内核以及ramdisk
StorageReadLba //如果boot.img没有内核则从kernel中读取
rkimage_load_fdt //从resource分区中读取fdt.
rk_load_kernel_logo -> //加载kernel logo
get_content //图片存在resource 分区
rk_commandline_setenv
do_bootm_linux //加载kernel,这里就是标准u-boot的做法了.
在board_r的启动序列中有
board_late_init
{
.......
load_disk_partitions(这里解析了parameter参数)
.......
board_fbt_preboot()这里检测了按键并且执行了启动流程
........
}
board_fbt_preboot中对按键进行了检查。随后根据不同按键执行不同的函数。
如果没有进行其他按键。最后正常的启动流程会走入
rkloader_run_misc_cmd函数(在rkloader.c中)
先找到misc的分区信息,这个分区信息是从前面load_disk_partitions里面解析的结构中得到的。
从MISC分区中读取bootload message
const disk_partition_t *ptn = get_disk_partition(MISC_NAME);
bmsg = (struct bootloader_message *)buf;
if (StorageReadLba(ptn->start + MISC_COMMAND_OFFSET, buf, DIV_ROUND_UP(
sizeof(struct bootloader_message), RK_BLK_SIZE)) != 0)
根据bmsg里面的命令执行。由于bmsg->command 既不是boot-recovery 也不是bootloader所以返回false
最终导致从board_late_init返回了。继续执行
最终到了main_loop
在main_loop里面进入cli_loop前执行了
autoboot_command(s);
只有一条指令。那就是bootrk
do_bootrk(NULL, 0, ARRAY_SIZE(boot_cmd), boot_cmd)
{
得到内核所在的分区信息默认先从boot分区开始
ptn = get_disk_partition(boot_source);
从分区中读取image到内存。并且取得image信息
hdr = rk_load_image_from_storage(ptn, &images);
设置命令行参数等等。也就是commandline这些 root=xxxxx这样的
rk_commandline_setenv(boot_source, hdr, charge);
接下来执行
do_bootm_linux(0, 0, NULL, &images); 正式启动内核。
}
rk_load_image_from_storage 首先从 boot分区中读取头部。查看头部是不是ANDROID!!
如果是的话。那么加载内核到内存中
如果不是,尝试使用rkimage_load_image从kernel分区和boot分区中读取内核和ramdisk
如果这次还是失败。
表示整个 rk_load_image_from_storage失败,执行 board_fbt_boot_failed 。再尝试从recovery分区执行do_bootrk
如果从recovery分区执行do_boottk还是失败。尝试从backup分区执行do_bootrk
如果还是失败。执行do_rockusb模式 等待usb刷机。
1、init_sequence_r :common/board_r.c //调用init_sequence_r中的各个函数。
2、board_late_init() board/rockchip/rk33xx/rk33xx.c
3、main_loop(): common/main.c
uboot启动进入命令行 与准备自动启动
4、autoboot_command() : common/autoboot.c 自动启动
5、board/rockchip/common/rkloader/parameter.h 分区表的定义
6、board/rockchip/common/rkloader/parameter.c 分区表的读取
7、board/rockchip/common/rkloader/rkloader.c 没有按键进入