- Uboot 启动
- 驱动
- 交互
- booti
- Kernel 启动
Uboot 启动
board_init_r 是执行 Uboot 的关键函数,该函数定义在 common/board_r.c 中,主要作用是进行一些必要的初始化工作,然后根据相关的配置情况,读取 Uboot,并启动它。
代码语言:javascript复制void board_init_r(gd_t *new_gd, ulong dest_addr)
{
......
#ifdef CONFIG_NEEDS_MANUAL_RELOC
int i;
#endif
......
gd->flags &= ~GD_FLG_LOG_READY;
#ifdef CONFIG_NEEDS_MANUAL_RELOC
for (i = 0; i < ARRAY_SIZE(init_sequence_r); i )
init_sequence_r[i] = gd->reloc_off;
#endif
if (initcall_run_list(init_sequence_r))
hang();
/* NOTREACHED - run_main_loop() does not return */
hang();
}
nit_sequence_r 中存储着一系列的初始化函数,initcall_run_list 确保了各系统初始化的顺序运行。根据 CONFIG_XX 来使能相应的驱动,最后 run_main_loop 进入循环。如下所示:
代码语言:javascript复制static init_fnc_t init_sequence_r[] = {
......
initr_barrier,
//初始化gd中与malloc相关的成员
initr_malloc,
//log初始化
log_init,
initr_bootstage, /* Needs malloc() but has its own timer */
......
#ifdef CONFIG_DM
//初始化驱动模型相关
initr_dm,
#endif
#ifdef CONFIG_ADDR_MAP
initr_addr_map,
#endif
#if defined(CONFIG_ARM) || defined(CONFIG_NDS32) || defined(CONFIG_RISCV) ||
defined(CONFIG_SANDBOX)
//板子初始化
board_init, /* Setup chipselects */
#endif
......
initr_dm_devices,
stdio_init_tables,
//串口初始化
serial_initialize,
initr_announce,
#if CONFIG_IS_ENABLED(WDT)
//看门狗初始化
initr_watchdog,
#endif
......
//上电
power_init_board,
......
#ifdef CONFIG_MMC
//mmc初始化
initr_mmc,
#endif
......
//串口
console_init_r, /* fully init console as a device */
#ifdef CONFIG_DISPLAY_BOARDINFO_LATE
console_announce_r,
//打印版子信息
show_board_info,
#endif
......
interrupt_init,
#if defined(CONFIG_MICROBLAZE) || defined(CONFIG_M68K)
//定时器
timer_init, /* initialize timer */
#endif
#if defined(CONFIG_LED_STATUS)
//led
initr_status_led,
#endif
/* PPC has a udelay(20) here dating from 2002. Why? */
#ifdef CONFIG_CMD_NET
//网络
initr_ethaddr,
#endif
......
run_main_loop,
};
驱动
从上面的代码可以知道 init_sequence_r 会根据宏定义初始化相应的功能,这里列出主要的几个,如下所示:
这里我们重点关注 mmc 和 net 驱动的初始化。