void board_init_f(ulong boot_flags)
{
#ifdef CONFIG_SYS_GENERIC_GLOBAL_DATA
/*
* For some archtectures, global data is initialized and used before
* calling this function. The data should be preserved. For others,
* CONFIG_SYS_GENERIC_GLOBAL_DATA should be defined and use the stack
* here to host global data until relocation.
*/
gd_t data;
gd = &data;
/*
* Clear global data before it is accessed at debug print
* in initcall_run_list. Otherwise the debug print probably
* get the wrong vaule of gd->have_console.
*/
zero_global_data();
#endif
//初始化变量gd
gd->flags = boot_flags;
gd->have_console = 0;
//按照init_sequence_f顺序进行初始化,包括定时器、串口、ddr等外设,更新gd值,并将uboot拷贝到内存的最后的地址区域
if (initcall_run_list(init_sequence_f))
hang();
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
/* NOTREACHED - jump_to_copy() does not return */
hang();
#endif
}
board_init_f:
1.初始化变量gd
2.按照init_sequence_f顺序进行初始化,包括定时器、串口、ddr等外设,更新gd值,将uboot拷贝到内存的最后的地址区域,跳转到内存中继续运行uboot
static init_fnc_t init_sequence_f[] = {
#ifdef CONFIG_SANDBOX
setup_ram_buf,
#endif
//更新gd->mon_len,及uboot代码长度
setup_mon_len,
setup_fdt,
#ifdef CONFIG_TRACE
trace_early_init,
#endif
//初始化 gd 中跟 malloc 有关的成员变量,比如 malloc_limit,malloc_limit 表示 malloc
内存池大小
initf_malloc,
#if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx)
/* TODO: can this go into arch_cpu_init()? */
probecpu,
#endif
arch_cpu_init, /* basic arch cpu dependent setup */
mark_bootstage,
#ifdef CONFIG_OF_CONTROL
fdtdec_check_fdt,
#endif
initf_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
/* TODO: can any of this go into arch_cpu_init()? */
#if defined(CONFIG_PPC) && !defined(CONFIG_8xx_CPUCLK_DEFAULT)
//获取时钟相关信息,并更新到gd
get_clocks, /* get CPU and bus clocks (etc.) */
#if defined(CONFIG_TQM8xxL) && !defined(CONFIG_TQM866M) \
&& !defined(CONFIG_TQM885D)
adjust_sdram_tbs_8xx,
#endif
/* TODO: can we rename this to timer_init()? */
init_timebase,
#endif
#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_BLACKFIN)
//初始化定时器
timer_init, /* initialize timer */
#endif
#ifdef CONFIG_SYS_ALLOC_DPRAM
#if !defined(CONFIG_CPM2)
dpram_init,
#endif
#endif
#if defined(CONFIG_BOARD_POSTCLK_INIT)
board_postclk_init,
#endif
#ifdef CONFIG_FSL_ESDHC
get_clocks,
#endif
//获取环境变量的地址,并更新到gd
env_init, /* initialize environment */
#if defined(CONFIG_8xx_CPUCLK_DEFAULT)
/* get CPU and bus clocks according to the environment variable */
get_clocks_866,
/* adjust sdram refresh rate according to the new clock */
sdram_adjust_866,
init_timebase,
#endif
//从环境变量中读取波特率
init_baud_rate, /* initialze baudrate settings */
//初始化串口
serial_init, /* serial communications setup */
//设置 gd->have_console 为 1,表示有个控制台,此函数也将前面
暂存在缓冲区中的数据通过控制台打印出来
console_init_f, /* stage 1 init of console */
#ifdef CONFIG_SANDBOX
sandbox_early_getopt_check,
#endif
#ifdef CONFIG_OF_CONTROL
fdtdec_prepare_fdt,
#endif
display_options, /* say that we are here */
display_text_info, /* show debugging info if required */
#if defined(CONFIG_MPC8260)
prt_8260_rsr,
prt_8260_clks,
#endif /* CONFIG_MPC8260 */
#if defined(CONFIG_MPC83xx)
prt_83xx_rsr,
#endif
#ifdef CONFIG_PPC
checkcpu,
#endif
print_cpuinfo, /* display cpu info (and speed) */
#if defined(CONFIG_MPC5xxx)
prt_mpc5xxx_clks,
#endif /* CONFIG_MPC5xxx */
#if defined(CONFIG_DISPLAY_BOARDINFO)
checkboard, /* display board info */
#endif
INIT_FUNC_WATCHDOG_INIT
#if defined(CONFIG_MISC_INIT_F)
misc_init_f,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
//初始化i2c接口
init_func_i2c,
#endif
#if defined(CONFIG_HARD_SPI)
//初始化spi接口
init_func_spi,
#endif
announce_dram_init,
/* TODO: unify all these dram functions? */
#if defined(CONFIG_ARM) || defined(CONFIG_X86)
dram_init, /* configure available RAM banks */
#endif
#if defined(CONFIG_MIPS) || defined(CONFIG_PPC)
//初始化ddr,并获取ddr大小,更新到gd
init_func_ram,
#endif
#ifdef CONFIG_POST
post_init_f,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_SYS_DRAM_TEST)
testdram,
#endif /* CONFIG_SYS_DRAM_TEST */
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_POST
init_post,
#endif
INIT_FUNC_WATCHDOG_RESET
/*
* Now that we have DRAM mapped and working, we can
* relocate the code and continue running from DRAM.
*
* Reserve memory at end of RAM for (top down in that order):
* - area that won't get touched by U-Boot and Linux (optional)
* - kernel log buffer
* - protected RAM
* - LCD framebuffer
* - monitor code
* - board info struct
*/
//开始为uboot代码搬运做准备
//更新gd->ram_size,gd->ram_top ,gd->relocaddr
setup_dest_addr,
#if defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2)
/* Blackfin u-boot monitor should be on top of the ram */
//根据uboot代码段的大小,计算gd->relocaddr
reserve_uboot,
#endif
#if defined(CONFIG_LOGBUFFER) && !defined(CONFIG_ALT_LB_ADDR)
reserve_logbuffer,
#endif
#ifdef CONFIG_PRAM
reserve_pram,
#endif
reserve_round_4k,
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF)) && \
defined(CONFIG_ARM)
reserve_mmu,
#endif
#ifdef CONFIG_LCD
reserve_lcd,
#endif
reserve_trace,
/* TODO: Why the dependency on CONFIG_8xx? */
#if defined(CONFIG_VIDEO) && (!defined(CONFIG_PPC) || defined(CONFIG_8xx)) && \
!defined(CONFIG_ARM) && !defined(CONFIG_X86) && \
!defined(CONFIG_BLACKFIN)
reserve_video,
#endif
#if !defined(CONFIG_BLACKFIN) && !defined(CONFIG_NIOS2)
reserve_uboot,
#endif
#ifndef CONFIG_SPL_BUILD
reserve_malloc,
reserve_board,
#endif
setup_machine,
reserve_global_data,
reserve_fdt,
reserve_arch,
//留出栈空间,先对 gd->start_addr_sp 减去 16,然后做 16 字节对齐
reserve_stacks,
setup_dram_config,
show_dram_config,
#ifdef CONFIG_PPC
setup_board_part1,
INIT_FUNC_WATCHDOG_RESET
setup_board_part2,
#endif
display_new_sp,
#ifdef CONFIG_SYS_EXTBDINFO
setup_board_extra,
#endif
INIT_FUNC_WATCHDOG_RESET
reloc_fdt,
setup_reloc,
#ifdef CONFIG_X86
copy_uboot_to_ram,
clear_bss,
do_elf_reloc_fixups,
#endif
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX)
//开始执行uboot代码拷贝,拷贝之后调用board_init_r,不返回,开始另一阶段的初始化
jump_to_copy,
#endif
NULL,
};
init_sequence_f:
1.setup_mon_len:更新gd->mon_len,即uboot代码长度
2.initf_malloc:初始化 gd 中跟 malloc 有关的成员变量,比如 malloc_limit,malloc_limit 表示 malloc内存池大小
3.get_clocks:获取时钟相关信息,并更新到gd
4.timer_init:初始化定时器
5.env_init:获取环境变量的地址,并更新到gd,因为flash还未初始化,一般是将地址指向default_environment
6.init_baud_rate:从环境变量中读取波特率
7.serial_init:初始化串口
8.console_init_f:设置 gd->have_console 为 1,表示有个控制台,此函数也将前面
暂存在缓冲区中的数据通过控制台打印出来
9.init_func_i2c:初始化i2c接口
10.初始化spi接口:init_func_spi
11.init_func_ram:初始化ddr,并获取ddr大小,更新到gd。初始化DDR控制器,涉及片选(地址区间)以及相关时序等。
12.setup_dest_addr:开始为uboot代码搬运做准备,更新gd->ram_size,gd->ram_top ,gd->relocaddr
13.reserve_uboot:根据uboot代码段的大小,计算gd->relocaddr
14.reserve_stacks:留出栈空间,先对 gd->start_addr_sp 减去 16,然后做 16 字节对齐
15.jump_to_copy:开始执行uboot代码拷贝,拷贝之后调用board_init_r,不返回,开始另一阶段的初始化