前沿
可能快要离开这个工作了3年半的岗位了,和E9000-MM910相伴这么久,连它的启动流程都不清楚,肯定是有遗憾的;顺带着学习下uboot
- uboot为实现跨平台、跨设备,使用了 board->machine->arch->cpu 框架
本片主要内容
uboot大致初始化流程
-
uboot启动后,会先执行CPU的初始化代码,在各个不同的cpu架构目录中
-
cpu相关的代码,会调用ARCH的公共代码(arch/arm)
-
ARCH的公共代码,在适当的时候,调用board有关的接口,其中实现了uboot的功能逻辑,大多在common代码;部分和平台有关的代码,择优board代码实现
-
board代码在需要的时候,会调用machine(arch/arm/mach-xxx)提供的接口,实现特定的功能
e500芯片手册中前置信息
-
CPU复位后执行的第一条指令的地址是 0xFFFF FFFC
-
MMU在复位时仅TLB1的entry0有效,将0xFFFF F000开始的4K有效地址空间映射到0xFFFF F000开始的4K物理地址空间中
CPU复位后启动流程
-
CPU首先到0xFFFF FFFC处执行跳转指令(b _start_e500),跳转到_start_e500(0xFFFF F000)处,也是entry0能够映射的4K最大空间
-
首先执行这4K代码,期间将会把MMU初始化,映射更大的空间,用于加载到所有的uboot代码
_start_e500
-
清除硬件未消除的寄存器
-
setup interrupt vectors
-
配置TLB1 Entry15,使整个U-boot都可见
-
配置TLB1 Entry14,准备16k Cash-SRAM空间
-
在D-Cache中锁定一段空间,用于在RAW初始化之前的C函数栈空间
代码
board_init_f
common/board_f.c
void board_init_f(ulong boot_flags)
{
gd->flags = boot_flags;
gd->have_console = 0;
if (initcall_run_list(init_sequence_f))
hang();
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64) && \
!defined(CONFIG_ARC)
/* NOTREACHED - jump_to_copy() does not return */
hang();
#endif
}
static const init_fnc_t init_sequence_f[] = {
setup_mon_len, //设置gd->mon_len=u-boot.bin+bss段的长度
#ifdef CONFIG_OF_CONTROL
fdtdec_setup,
#endif
#ifdef CONFIG_TRACE_EARLY
trace_early_init,
#endif
initf_malloc, //初始化malloc相关参数,使得可以使用malloc函数
log_init,
initf_bootstage, /* uses its own timer, so does not need DM */
#ifdef CONFIG_BLOBLIST
bloblist_init,
#endif
setup_spl_handoff,
initf_console_record,
#if defined(CONFIG_HAVE_FSP)
arch_fsp_init,
#endif
/* 下面一组4个函数,留给移植的人员使用,使用weak修饰,且是空函数 */
arch_cpu_init, /* basic arch cpu dependent setup */
mach_cpu_init, /* SoC/machine dependent CPU setup */
initf_dm,
arch_cpu_init_dm,
#if defined(CONFIG_BOARD_EARLY_INIT_F)
board_early_init_f,
#endif
#if defined(CONFIG_PPC) || defined(CONFIG_SYS_FSL_CLK) || defined(CONFIG_M68K)
/* get CPU and bus clocks according to the environment variable */
get_clocks, /* get CPU and bus clocks (etc.) */
#endif
#if !defined(CONFIG_M68K)
timer_init, /* initialize timer */
#endif
#if defined(CONFIG_BOARD_POSTCLK_INIT)
board_postclk_init,
#endif
env_init, /* initialize environment */
init_baud_rate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_options, /* say that we are here */
display_text_info, /* show debugging info if required */
#if defined(CONFIG_PPC) || defined(CONFIG_SH) || defined(CONFIG_X86)
checkcpu,
#endif
#if defined(CONFIG_SYSRESET)
print_resetinfo,
#endif
#if defined(CONFIG_DISPLAY_CPUINFO)
print_cpuinfo, /* display cpu info (and speed) */
#endif
#if defined(CONFIG_DTB_RESELECT)
embedded_dtb_select,
#endif
#if defined(CONFIG_DISPLAY_BOARDINFO)
show_board_info,
#endif
INIT_FUNC_WATCHDOG_INIT
#if defined(CONFIG_MISC_INIT_F)
misc_init_f,
#endif
INIT_FUNC_WATCHDOG_RESET
#if defined(CONFIG_SYS_I2C)
init_func_i2c,
#endif
#if defined(CONFIG_VID) && !defined(CONFIG_SPL)
init_func_vid,
#endif
announce_dram_init,
dram_init, /* configure available RAM banks */
#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
*/
setup_dest_addr,
#ifdef CONFIG_PRAM
reserve_pram,
#endif
reserve_round_4k,
#ifdef CONFIG_ARM
reserve_mmu,
#endif
reserve_video,
reserve_trace,
reserve_uboot,
reserve_malloc,
reserve_board,
setup_machine,
reserve_global_data,
reserve_fdt,
reserve_bootstage,
reserve_bloblist,
reserve_arch,
reserve_stacks,
dram_init_banksize,
show_dram_config,
#if defined(CONFIG_M68K) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || \
defined(CONFIG_SH)
setup_board_part1,
#endif
#if defined(CONFIG_PPC) || defined(CONFIG_M68K)
INIT_FUNC_WATCHDOG_RESET
setup_board_part2,
#endif
display_new_sp,
#ifdef CONFIG_OF_BOARD_FIXUP
fix_fdt,
#endif
INIT_FUNC_WATCHDOG_RESET
reloc_fdt,
reloc_bootstage,
reloc_bloblist,
setup_reloc,
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
copy_uboot_to_ram,
do_elf_reloc_fixups,
clear_bss,
#endif
#if defined(CONFIG_XTENSA)
clear_bss,
#endif
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
!CONFIG_IS_ENABLED(X86_64)
jump_to_copy,
#endif
NULL,
}