[Linux]uboot启动过程解析:board_init_r函数

文章目录

board_init_r

调用 board_init_r 函数,入参 r0 = gd, r1 = gd->relocaddr
实际上这俩参数未用到!

//路径:arch/arm/lib/crt0.S L166
	/* call board_init_r(gd_t *id, ulong dest_addr) */
	mov     r0, r9                  /* gd_t */
	ldr	r1, [r9, #GD_RELOCADDR]	/* dest_addr */
	/* call board_init_r */
#if defined(CONFIG_SYS_THUMB_BUILD)
	ldr	lr, =board_init_r	/* this is auto-relocated! */
	bx	lr
#else
	ldr	pc, =board_init_r	/* this is auto-relocated! */
#endif
	/* we should not return here. */
void board_init_r(gd_t *new_gd, ulong dest_addr)
{
	if (initcall_run_list(init_sequence_r))
		hang();

	/* NOTREACHED - run_main_loop() does not return */
	hang();
}

删减后的 init_sequence_r 数组(只列举相对重要的项)

init_fnc_t init_sequence_r[] = {
    initr_trace,
    initr_reloc,
    initr_caches,
    initr_reloc_global_data,
    initr_barrier,
    initr_malloc,
    initr_console_record,
    bootstage_relocate,
    initr_bootstage,
    board_init,                 /* Setup chipselects */
    stdio_init_tables,
    initr_serial,
    initr_announce,
    power_init_board,
    initr_flash,
    initr_nand,
    initr_mmc,
    initr_env,
    initr_secondary_cpu,
    stdio_add_devices,
    initr_jumptable,
    console_init_r,             /* fully init console as a device */
    interrupt_init,
    initr_enable_interrupts,
    initr_ethaddr,
    board_late_init,
    initr_net,
    run_main_loop,
};

1. initr_trace

如果初始化宏 CONFIG_TRACE 则会调用 trace_init(gd->trace_buff, CONFIG_TRACE_BUFFER_SIZE);
初始化和调试跟踪有关的内容

2. initr_reloc

执行 gd->flags |= GD_FLG_RELOC | GD_FLG_FULL_MALLOC_INIT;
标记重定位操作已经完成

3. initr_caches

使能 catch

4. initr_reloc_global_data

初始化重定位后 gd 的一些成员变量
对于 IMX6ULL 只是设置了 monitor_flash_len

monitor_flash_len 是程序镜像的长度(包括 .code/.data/.rel.dyn)
不包括 .bss

static int initr_reloc_global_data(void)
{
	monitor_flash_len = _end - __image_copy_start;

	return 0;
}

5. initr_barrier/initr_console_record

IMX6ULL 未使用

6. initr_malloc

初始化 malloc

7. board_init

板卡外设初始化,分为两个阶段

  1. board_init
  2. board_late_init
//路径:board/freescale/mx6ull_myboard_nand/mx6ull_myboard_nand.c L693
int board_init(void)
{
	/* Address of boot parameters */
	gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;

#ifdef CONFIG_SYS_I2C_MXC
	setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1);
#endif

#ifdef	CONFIG_FEC_MXC
	setup_fec(CONFIG_FEC_ENET_DEV);
#endif

#ifdef CONFIG_USB_EHCI_MX6
	setup_usb();
#endif

#ifdef CONFIG_FSL_QSPI
	board_qspi_init();
#endif

#ifdef CONFIG_NAND_MXS
	setup_gpmi_nand();
#endif

	return 0;
}

8. stdio_init_tables

进行 stdio 相关初始化

9. serial_initialize

初始化串口

10. initr_announce

与调试有关,通知已经在 RAM 中运行

static int initr_announce(void)
{
	debug("Now running in RAM - U-Boot at: %08lx\n", gd->relocaddr);
	return 0;
}

11. power_init_board

初始化电源芯片

12. initr_flash

IMX6ULL 未使用

13. initr_nand/initr_mmc

初始化 nand/emmc 二选一
同时输出调试信息

14. initr_env

初始化环境变量

15. stdio_add_devices

初始化各种输入/输出设备,如 LCD
路径:common/stdio.c L249

16. initr_jumptable

初始化跳转表

static int initr_jumptable(void)
{
	jumptable_init(); //路径:common/exports.c L26
	return 0;
}

17. console_init_r

控制台初始化
调用 stdio_print_current_devices 打印当前的控制台设备(In Out Err)

18. interrupt_init/initr_enable_interrupts

初始化/使能中断

19. initr_ethaddr

从环境变量中获取 MAC 地址,保存到 bd->bi_enetaddr/bi_enet1addr/...
并不是初始化 ENET

static int initr_ethaddr(void)
{
	bd_t *bd = gd->bd;

	/* kept around for legacy kernels only ... ignore the next section */
	eth_getenv_enetaddr("ethaddr", bd->bi_enetaddr);
#ifdef CONFIG_HAS_ETH1
	eth_getenv_enetaddr("eth1addr", bd->bi_enet1addr);
#endif
#ifdef CONFIG_HAS_ETH2
	eth_getenv_enetaddr("eth2addr", bd->bi_enet2addr);
#endif
#ifdef CONFIG_HAS_ETH3
	eth_getenv_enetaddr("eth3addr", bd->bi_enet3addr);
#endif
#ifdef CONFIG_HAS_ETH4
	eth_getenv_enetaddr("eth4addr", bd->bi_enet4addr);
#endif
#ifdef CONFIG_HAS_ETH5
	eth_getenv_enetaddr("eth5addr", bd->bi_enet5addr);
#endif
	return 0;
}

20. board_late_init

板卡外设初始化,分为两个阶段

  1. board_init
  2. board_late_init
//路径:board/freescale/mx6ull_myboard_nand/mx6ull_myboard_nand.c L731
int board_late_init(void)
{
#ifdef CONFIG_CMD_BMODE
	add_board_boot_modes(board_boot_modes);
#endif

#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
	if (is_mx6ull_9x9_evk() || is_mx6ull_14x14_evk())
		setenv("board_name", "EVK");
	else
		setenv("board_name", "MYBOARD");

	if (is_mx6ull_9x9_evk())
		setenv("board_rev", "9X9");
	else if (is_mx6ull_14x14_evk())
		setenv("board_rev", "14X14");
	else 
		setenv("board_rev", "NAND");
#endif

#ifdef CONFIG_ENV_IS_IN_MMC
	board_late_mmc_env_init();
#endif

	set_wdog_reset((struct wdog_regs *)WDOG1_BASE_ADDR);

	return 0;
}

board_late_init 中完成一些环境变量来那个的设置,因此需要在 emmc/nand 等存储设备初始化完成后才能进行
如果使用的是 emmc/sd 则会调用 board_late_mmc_env_init 来切换当前使用的设备
因此不能合并到 board_init

特别说明: board_init 完成的是芯片内部外设的初始化,不是外部设备的初始化!

21. initr_net

初始化网络
注意,这里的网络指的整个 enet 重点是外部的 phy 芯片的初始化
enet 的 MAC 部分初始化在 board_init 中就完成了,此部分属于芯片的内部外设

initr_net
    eth_initialize
        board_eth_init

22. run_main_loop

主循环,处理交互命令
run_main_loop 不会返回!

总结:

board_init_r 完成的是外设、设备的初始化操作

  1. 初始化芯片外设(I2C、SPI)
  2. 初始化外部设备(存储器、网络等)
  3. 初始化输入/输出设备(控制台、显示、键盘等)
  4. 初始化环境变量
  5. 更新环境变量
上一篇:关于网页前端的html使用技巧1


下一篇:条件编译#ifdef的妙用详解_透彻