下面详细介绍board_init_r函数的调用流程
board_init_r主要做一些板级硬件的初始化,会对板子上的各个外设进行初始化配置,最后调用run_main_loop进入下一级boot或者进入boot console。
1、board_init_r函数类似前面的board_init_f,关键就是遍历执行数组init_sequence_r里面的函数来初始化硬件,下面是具体的代码讲解:
/*
* We hope to remove most of the driver-related init and do it if/when
* the driver is later used.
*
* TODO: perhaps reset the watchdog in the initcall function after each call?
*/
static init_fnc_t init_sequence_r[] = {
//根据CONFIG_TRACE来初始化trace system
initr_trace,
//设置gd flags,标记重定向完成,malloc 已经ready
initr_reloc,
/* TODO: could x86/PPC have this also perhaps? */
#ifdef CONFIG_ARM
initr_caches,
/* Note: For Freescale LS2 SoCs, new MMU table is created in DDR.
* A temporary mapping of IFC high region is since removed,
* so environmental variables in NOR flash is not available
* until board_init() is called below to remap IFC to high
* region.
*/
#endif
initr_reloc_global_data, //获取uboot的大小,赋值到monitor_flash_len里面
#if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500)
initr_unlock_ram_in_cache,
#endif
// PPC专用
initr_barrier,
//初始化malloc使用的内存区域和大小
initr_malloc,
// 初始化log system, flag设置为GD_FLG_LOG_READY
log_init,
//设置启动stage为board_init_r
initr_bootstage, /* Needs malloc() but has its own timer */
//初始化控制台,申请console_out 和console_in buffer
initr_console_record,
#ifdef CONFIG_SYS_NONCACHED_MEMORY
//初始化不经过cache的内存,这个需要cpu支持
initr_noncached,
#endif
//设置boot stage为of_live,解析传进来设备树,把dtb里面的信息记录下来
initr_of_live,
#ifdef CONFIG_DM
//初始化驱动模型的结构并扫描所有的设备
initr_dm,
#endif
#if defined(CONFIG_ARM) || defined(CONFIG_NDS32) || defined(CONFIG_RISCV) || \
defined(CONFIG_SANDBOX)
board_init, /* Setup chipselects,进行板级的初始化 */
#endif
/*
* TODO: printing of the clock inforamtion of the board is now
* implemented as part of bdinfo command. Currently only support for
* davinci SOC's is added. Remove this check once all the board
* implement this.
*/
#ifdef CONFIG_CLOCKS
//获取cpu的clock信息,保存在gd里面
set_cpu_clk_info, /* Setup clock information */
#endif
#ifdef CONFIG_EFI_LOADER
efi_memory_init,
#endif
//分配struct binman_info结构内存,并设置binman相关信息参数
initr_binman,
#ifdef CONFIG_FSP_VERSION2
arch_fsp_init_r,
#endif
//在系统启动早期初始化定时器,和将多路复用控制初始化为默认状态
initr_dm_devices,
//用于初始化标准输出设备链表(struct stdio_dev)
stdio_init_tables,
//注册串行端口设备
serial_initialize,
//打印出运行调试信息
initr_announce,
#if CONFIG_IS_ENABLED(WDT)
//初始化看门狗
initr_watchdog,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_NEEDS_MANUAL_RELOC) && defined(CONFIG_BLOCK_CACHE)
blkcache_init,
#endif
#ifdef CONFIG_NEEDS_MANUAL_RELOC
initr_manual_reloc_cmdtable,
#endif
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS)
initr_trap,
#endif
#ifdef CONFIG_ADDR_MAP
initr_addr_map,
#endif
#if defined(CONFIG_BOARD_EARLY_INIT_R)
board_early_init_r,
#endif
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_POST
initr_post_backlog,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT)
/*
* Do early PCI configuration _before_ the flash gets initialised,
* because PCU resources are crucial for flash access on some boards.
*/
//初始化pci
initr_pci,
#endif
#ifdef CONFIG_ARCH_EARLY_INIT_R
//cpu相关的初始化,自己实现
arch_early_init_r,
#endif
//初始化电源管理,和具体的cpu和板子有关,自己实现
power_init_board,
#ifdef CONFIG_MTD_NOR_FLASH
//NOR flash的初始化
initr_flash,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_X86)
/* initialize higher level parts of CPU like time base and timers */
cpu_init_r,
#endif
#ifdef CONFIG_CMD_NAND
//NAND flash的初始化
initr_nand,
#endif
#ifdef CONFIG_CMD_ONENAND
//onenand flash的初始化
initr_onenand,
#endif
#ifdef CONFIG_MMC
//mmc的初始化
initr_mmc,
#endif
#ifdef CONFIG_XEN
initr_xen,
#endif
#ifdef CONFIG_PVBLOCK
initr_pvblock,
#endif
//初始化环境变量,找到load address
initr_env,
#ifdef CONFIG_SYS_BOOTPARAMS_LEN
//为boot参数分配地址
initr_malloc_bootparams,
#endif
INIT_FUNC_WATCHDOG_RESET
initr_secondary_cpu, //weak函数,cpu的初始化
#if defined(CONFIG_ID_EEPROM) || defined(CONFIG_SYS_I2C_MAC_OFFSET)
mac_read_from_eeprom,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_PCI) && !defined(CONFIG_SYS_EARLY_PCI_INIT)
/*
* Do pci configuration
*/
initr_pci,
#endif
//添加stdio设备到设备表中,iic 串口,lcd,video等等都属于stdio设备
stdio_add_devices,
//为gd的jt申请memory
initr_jumptable,
//下面都是为各种外设进行初始化,太多了,不去一一看了,用到哪个具体分析
#ifdef CONFIG_API
initr_api,
#endif
console_init_r, /* fully init console as a device */
#ifdef CONFIG_DISPLAY_BOARDINFO_LATE
console_announce_r,
show_board_info,
#endif
#ifdef CONFIG_ARCH_MISC_INIT
arch_misc_init, /* miscellaneous arch-dependent init */
#endif
#ifdef CONFIG_MISC_INIT_R
misc_init_r, /* miscellaneous platform-dependent init */
#endif
INIT_FUNC_WATCHDOG_RESET
#ifdef CONFIG_CMD_KGDB
initr_kgdb,
#endif
interrupt_init,
#if defined(CONFIG_MICROBLAZE) || defined(CONFIG_M68K)
timer_init, /* initialize timer */
#endif
#if defined(CONFIG_LED_STATUS)
initr_status_led,
#endif
/* PPC has a udelay(20) here dating from 2002. Why? */
#ifdef CONFIG_CMD_NET
initr_ethaddr,
#endif
#if defined(CONFIG_GPIO_HOG)
gpio_hog_probe_all,
#endif
#ifdef CONFIG_BOARD_LATE_INIT
board_late_init,
#endif
#if defined(CONFIG_SCSI) && !defined(CONFIG_DM_SCSI)
INIT_FUNC_WATCHDOG_RESET
initr_scsi,
#endif
#ifdef CONFIG_BITBANGMII
initr_bbmii,
#endif
#ifdef CONFIG_PCI_ENDPOINT
initr_pci_ep,
#endif
#ifdef CONFIG_CMD_NET
INIT_FUNC_WATCHDOG_RESET
initr_net,
#endif
#ifdef CONFIG_POST
initr_post,
#endif
#if defined(CONFIG_IDE) && !defined(CONFIG_BLK)
initr_ide,
#endif
#ifdef CONFIG_LAST_STAGE_INIT
INIT_FUNC_WATCHDOG_RESET
/*
* Some parts can be only initialized if all others (like
* Interrupts) are up and running (i.e. the PC-style ISA
* keyboard).
*/
last_stage_init,
#endif
#ifdef CONFIG_CMD_BEDBUG
INIT_FUNC_WATCHDOG_RESET
bedbug_init,
#endif
#if defined(CONFIG_PRAM)
initr_mem,
#endif
#ifdef CONFIG_EFI_SETUP_EARLY
(init_fnc_t)efi_init_obj_list,
#endif
//这个是关键的关键,board_int_r最后调用的函数,死循环在main_loop里面,后门分析main_loop
run_main_loop,
};