/* SPL階段函數(shù)調用過程 */ u-boot-spl.lds(arch/arm/cpu/arm/u-boot-spl.lds) |--> vectors.S(arch/arm/lib/vectors.S) |--> start.S(arch/arm/cpu/arm926ejs/start.S) |--> /*set SVC mode .. disable FIQ and IRQ*/ |--> cpu_init_crit(arch/arm/cpu/armv7/start.S) |--> /* flush D cache before disabling it*/ |--> /* disable MMU and D cache it, enable I cache if SYS_ICACHE_OFF is not defined*/ |--> lowlevel_init(arch/arm/cpu/arm926ejs/nuc970/lowlevel_init.S) /* 板級初始化,設置棧空間 */ |--> _main(arch/arm/lib/crt0.S ) |--> /* Set up initial C runtime environment and call board_init_f(0).*/ |--> board_init_f_alloc_reserve(common/init/board_init.c) |--> board_init_f_init_reserve(common/init/board_init.c) |--> board_init_f(common/spl/spl.c) |--> spl_early_init(common/spl/spl.c) |--> spl_common_init(true) (common/spl/spl.c) |--> gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN); |--> gd->malloc_ptr = 0; |--> bootstage_init(u_boot_first_phase())(include/bootstage.c) |--> bootstage_unstash(#ifdef CONFIG_BOOTSTAGE_STASH) (include/bootstage.c) |--> bootstage_mark_name(include/bootstage.c) |--> log_init(common/log.c) |--> fdtdec_setup()(lib/fdtdec.c) |--> gd->fdt_blob = board_fdt_blob_setup()(lib/fdtdec.c) |--> fdtdec_prepare_fdt() (lib/fdtdec.c) |--> bootstage_start(include/bootstage.c) |--> dm_init_and_scan(drivers/core/root.c) |--> dm_init (drivers/core/root.c) //#define DM_UCLASS_ROOT_NON_CONST (((gd_t *)gd)->uclass_root) 創(chuàng)建頭結點gd->uclass_root |--> INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST) (drivers/core/root.c) |--> device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST) (drivers/core/device.c) //lists_driver_lookup_name("root_driver") |--> drv = lists_driver_lookup_name(info->name) (drivers/core/device.c) //通過上篇分析,此處得到的是uboot_list_2_driver_1的地址 |--> struct driver *drv =ll_entry_start(struct driver, driver); //uboot_list_2_driver_3-uboot_list_2_driver_1即得到長度 |--> const int n_ents = ll_entry_count(struct driver, driver) //遍歷,通過name字段匹配,匹配成功得到driver結構體地址 |--> for (entry = drv; entry != drv + n_ents; entry++) |--> device_bind_common(drv, "root_driver", gd->dm_root) (drivers/core/device.c) //通過上面得到的drv中的id字段(UCLASS_ROOT)進行匹配,匹配成功得到對應的uclass_driver結構體地址 |--> uclass_get(drv->id, &uc) |-->uc = uclass_find(id); |-->return uclass_add(id, ucp); |--> uc->uc_drv = uc_drv; //uclass root的uclass_driver指向uclass_driver root |--> INIT_LIST_HEAD(&uc->sibling_node); |--> INIT_LIST_HEAD(&uc->dev_head); |--> list_add(&uc->sibling_node, &DM_UCLASS_ROOT_NON_CONST); |--> dev = calloc(1, sizeof(struct udevice)) /* put dev into parent's successor list */ |--> list_add_tail(&dev->sibling_node, &parent->child_head); |--> ret = uclass_bind_device(dev); /* if we fail to bind we remove device from successors and free it */ |--> DM_ROOT_NON_CONST->node = |--> np_to_ofnode, offset_to_ofnode() |--> device_probe (drivers/core/device.c) |--> if (dev->flags & DM_FLAG_ACTIVATED) |--> device_ofdata_to_platdata (drivers/core/device.c) |--> /* Ensure all parents are probed */ |--> seq = uclass_resolve_seq(dev) (drivers/core/uclass.c) |--> uclass_find_device_by_seq |--> dev->flags |= DM_FLAG_ACTIVATED |--> pinctrl_select_state |--> dev_power_domain_on |--> uclass_pre_probe_device |--> uclass_pre_probe_device |--> /* Only handle devices that have a valid ofnode */ |--> clk_set_defaults |--> drv->probe |--> uclass_post_probe_device |--> pinctrl_select_state |--> ret = dm_scan_platdata(pre_reloc_only); (drivers/core/root.c) //搜索使用宏U_BOOT_DEVICE定義的設備進行驅動匹配,也就是bind子節(jié)點 |--> ret = dm_extended_scan_fdt(gd->fdt_blob, pre_reloc_only); (drivers/core/root.c) //在其他地方(設備樹)搜索設備并進行驅動匹配,然后bind |--> dm_scan_fdt//在設備樹種搜索設備并進行驅動匹配,然后bind |--> ret = dm_scan_other(pre_reloc_only); (drivers/core/root.c) |--> bootstage_accum(include/bootstage.c) |--> gd->flags |= GD_FLG_SPL_EARLY_INIT (common/spl/spl.c) |--> preloader_console_init (common/spl/spl.c) |--> gd->baudrate = CONFIG_BAUDRATE(common/spl/spl.c) |--> serial_init (drivers/serail/serial-uclass.c) |--> serial_find_console_or_panic(drivers/serail/serial-uclass.c) |--> /* Live tree has support for stdout */ |--> ogd->cur_serial_dev <- uclass_get_device_by_ofnode |--> ogd->cur_serial_dev <- serial_check_stdout |--> gd->flags |= GD_FLG_SERIAL_READY |--> gd->have_console = 1
|--> board_init_r(common/spl/spl.c) |--> spl_set_bd();gd->bd = &bdata /* gd是保存在r9寄存器的,即r9保存的是指向gdata的指針 */ |--> timer_init(arch/arm/cpu/armv7/sunxi/timer.c) /* 初始化時鐘 */ ret = bloblist_init(); ret = setup_spl_handoff(); |--> spl_board_init() |--> initr_watchdog(); |--> dram_init_banksize(); |--> bootcount_inc(); |--> memset(&spl_image, '\0', sizeof(spl_image)); |--> board_boot_order(spl_boot_list); |--> boot_from_devices(common/spl/spl.c) |--> spl_ll_find_loader(common/spl/spl.c) |--> ll_entry_start(include/linker_lists.h) |--> SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image); (common/spl/spl_nand.c) |--> loader->load_image(spl_image, &bootdev); spl_nand_load_image (common/spl/spl_nand.c) |--> nand_init(); (common/spl/spl_mmc.c) |--> spl_get_load_buffer(0, sizeof(*header)); (common/spl/spl_mmc.c) |--> spl_nand_load_element |--> /* Load u-boot */spl_nand_load_element(spl_image, spl_nand_get_uboot_raw_page(), header); |--> nand_deselect(); (common/spl/spl.c) /* 解析 header */ |--> spl_perform_fixups(&spl_image); |--> ret = write_spl_handoff(); |--> ret = bloblist_finish(); /* 結束SPL過程,跳轉到u-boot */ |--> bootstage_mark_name |--> bootstage_stash |--> spl_board_prepare_for_boot(); |--> jump_to_image_no_args(&spl_image); |
|