赞
踩
main函数代码如下。sp = CONFIG_SYS_INIT_SP_ADDR = 0X0091FF00, 未定义CONFIG_CPU_V7M,sp 8字节对齐,r0 = sp,执行 board_init_f_alloc_reserve函数。
ENTRY(_main) /* * Set up initial C runtime environment and call board_init_f(0). */ #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK) ldr sp, =(CONFIG_SPL_STACK) #else ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) #endif #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */ mov r3, sp bic r3, r3, #7 mov sp, r3 #else bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ #endif mov r0, sp bl board_init_f_alloc_reserve mov sp, r0 /* set up gd here, outside any C code */ mov r9, r0 bl board_init_f_init_reserve mov r0, #0 bl board_init_f #if ! defined(CONFIG_SPL_BUILD) /* * Set up intermediate environment (new sp and gd) and call * relocate_code(addr_moni). Trick here is that we'll return * 'here' but relocated. */ ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */ #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC destination */ mov r3, sp bic r3, r3, #7 mov sp, r3 #else bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ #endif ldr r9, [r9, #GD_BD] /* r9 = gd->bd */ sub r9, r9, #GD_SIZE /* new GD is below bd */ adr lr, here ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */ add lr, lr, r0 #if defined(CONFIG_CPU_V7M) orr lr, #1 /* As required by Thumb-only */ #endif ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ b relocate_code here: /* * now relocate vectors */ bl relocate_vectors /* Set up final (full) environment */ bl c_runtime_cpu_setup /* we still call old routine here */ #endif #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK) # ifdef CONFIG_SPL_BUILD /* Use a DRAM stack for the rest of SPL, if requested */ bl spl_relocate_stack_gd cmp r0, #0 movne sp, r0 movne r9, r0 # endif ldr r0, =__bss_start /* this is auto-relocated! */ #ifdef CONFIG_USE_ARCH_MEMSET ldr r3, =__bss_end /* this is auto-relocated! */ mov r1, #0x00000000 /* prepare zero to clear BSS */ subs r2, r3, r0 /* r2 = memset len */ bl memset #else ldr r1, =__bss_end /* this is auto-relocated! */ mov r2, #0x00000000 /* prepare zero to clear BSS */ clbss_l:cmp r0, r1 /* while not at end of BSS */ #if defined(CONFIG_CPU_V7M) itt lo #endif strlo r2, [r0] /* clear 32-bit BSS word */ addlo r0, r0, #4 /* move to next */ blo clbss_l #endif #if ! defined(CONFIG_SPL_BUILD) bl coloured_LED_init bl red_led_on #endif /* 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. */ #endif ENDPROC(_main)
board_init_f_alloc_reserve函数如下,在main函数部分r0 = sp,board_init_f_alloc_reserve 的top = r0,执行完之后,sp = r0 = (0X0091FB00 -248 ) - (0X0091FB00 -248 )%16 = 0X0091FA00, r9 = r0,将gdata地址设置成0X0091FA00,此时去执行board_init_f_init_reserve函数。base = r0 = 0X0091FA00,执行完base = base +roundup(248,16) =0X0091FA00 + 0X100 = 0X0091FB00
ulong board_init_f_alloc_reserve(ulong top) { /* Reserve early malloc arena */ #if defined(CONFIG_SYS_MALLOC_F) top -= CONFIG_SYS_MALLOC_F_LEN; #endif /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */ top = rounddown(top-sizeof(struct global_data), 16); return top; } #define rounddown(x, y) ( \ { \ typeof(x) __x = (x); \ __x - (__x % (y)); \ } \ )
board_init_f_init_reserve函数代码如下。gd 这个变量通过 DECLARE_GLOBAL_DATA_PTR 定义,这个变量的作用是用来存储 uboot 需要使用到的全局变量,这样可以减少全局变量的数量,方便他人阅读代码。具体的作用可以从结构体成员中得知。 bd 这个成员变量的主要作用是用来保存一些和板级相关的信息,如波特率、ip 地址等。
void board_init_f_init_reserve(ulong base) { struct global_data *gd_ptr; #ifndef _USE_MEMCPY int *ptr; #endif /* * clear GD entirely and set it up. * Use gd_ptr, as gd may not be properly set yet. */ gd_ptr = (struct global_data *)base; /* zero the area */ #ifdef _USE_MEMCPY memset(gd_ptr, '\0', sizeof(*gd)); #else for (ptr = (int *)gd_ptr; ptr < (int *)(gd_ptr + 1); ) *ptr++ = 0; #endif /* set GD unless architecture did it already */ #if !defined(CONFIG_ARM) arch_setup_gd(gd_ptr); #endif /* next alloc will be higher by one GD plus 16-byte alignment */ base += roundup(sizeof(struct global_data), 16); /* * record early malloc arena start. * Use gd as it is now properly set for all architectures. */ #if defined(CONFIG_SYS_MALLOC_F) /* go down one 'early malloc arena' */ gd->malloc_base = base; /* next alloc will be higher by one 'early malloc arena' size */ base += CONFIG_SYS_MALLOC_F_LEN; #endif }
board_init_f_init_reserve函数执行完后,r0 = 0;board_init_f函数代码如下。主要运行initcall_run_list函数初始化序列init_sequence_f里面男的一系列函数
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->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) /* NOTREACHED - jump_to_copy() does not return */ hang(); #endif }
函数代码如下,遍历执行init_sequence里面的函数。
int initcall_run_list(const init_fnc_t init_sequence[]) { const init_fnc_t *init_fnc_ptr; for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { unsigned long reloc_ofs = 0; int ret; if (gd->flags & GD_FLG_RELOC) reloc_ofs = gd->reloc_off; #ifdef CONFIG_EFI_APP reloc_ofs = (unsigned long)image_base; #endif debug("initcall: %p", (char *)*init_fnc_ptr - reloc_ofs); if (gd->flags & GD_FLG_RELOC) debug(" (relocated to %p)\n", (char *)*init_fnc_ptr); else debug("\n"); ret = (*init_fnc_ptr)(); if (ret) { printf("initcall sequence %p failed at call %p (err=%d)\n", init_sequence, (char *)*init_fnc_ptr - reloc_ofs, ret); return -1; } } return 0; }
init_sequence_f序列里面包含了一些列的函数,代码如下。
static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_SANDBOX setup_ram_buf, #endif setup_mon_len, #ifdef CONFIG_OF_CONTROL fdtdec_setup, #endif #ifdef CONFIG_TRACE trace_early_init, #endif initf_malloc, initf_console_record, #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) /* TODO: can this go into arch_cpu_init()? */ probecpu, #endif #if defined(CONFIG_X86) && defined(CONFIG_HAVE_FSP) x86_fsp_init, #endif arch_cpu_init, /* basic arch cpu dependent setup */ initf_dm, arch_cpu_init_dm, mark_bootstage, /* need timer, go after init 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) 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) || defined(CONFIG_NDS32) || \ defined(CONFIG_SPARC) 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 #if defined(CONFIG_SYS_FSL_CLK) || defined(CONFIG_M68K) get_clocks, #endif 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 */ 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 #if defined(CONFIG_PPC) || defined(CONFIG_M68K) checkcpu, #endif print_cpuinfo, /* display cpu info (and speed) */ #if defined(CONFIG_MPC5xxx) prt_mpc5xxx_clks, #endif /* CONFIG_MPC5xxx */ #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_HARD_I2C) || defined(CONFIG_SYS_I2C) init_func_i2c, #endif #if defined(CONFIG_HARD_SPI) init_func_spi, #endif announce_dram_init, /* TODO: unify all these dram functions? */ #if defined(CONFIG_ARM) || defined(CONFIG_X86) || defined(CONFIG_NDS32) || \ defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) dram_init, /* configure available RAM banks */ #endif #if defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_M68K) 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 */ setup_dest_addr, #if defined(CONFIG_BLACKFIN) /* Blackfin u-boot monitor should be on top of the ram */ reserve_uboot, #endif #if defined(CONFIG_SPARC) reserve_prom, #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_DM_VIDEO reserve_video, #else # ifdef CONFIG_LCD reserve_lcd, # endif /* 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) && !defined(CONFIG_M68K) reserve_legacy_video, # endif #endif /* CONFIG_DM_VIDEO */ reserve_trace, #if !defined(CONFIG_BLACKFIN) reserve_uboot, #endif #ifndef CONFIG_SPL_BUILD reserve_malloc, reserve_board, #endif setup_machine, reserve_global_data, reserve_fdt, reserve_arch, reserve_stacks, setup_dram_config, show_dram_config, #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) setup_board_part1, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K) 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, #if defined(CONFIG_X86) || defined(CONFIG_ARC) copy_uboot_to_ram, clear_bss, do_elf_reloc_fixups, #endif #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) jump_to_copy, #endif NULL, };
(1)setup_mon_len :函数设置 gd 的 mon_len 成员变量即代码长度 = __bss_end -_start =0X878A8E74-0x87800000=0XA8E74;
(2)initf_malloc: 函数初始化 gd 中跟 malloc 有关的成员变量,比如 malloc_limit,gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN=0X400 内存池大小为0x400;
(3)timer_init :初始化A7内核定时器,类似于M内核SysTick
(4)env_init: 设置 gd 的成员变量 env_addr,也就是环境变量的保存地址
(5)init_baud_rate :函数用于初始化波特率,根据环境变量 baudrate 来初始化 gd->baudrate。
(6)dram_init :设置 gd->ram_size 的值 512MB
(7)setup_dest_addr函数,设置目的地址,设置gd->ram_size,gd->ram_top,gd->relocaddr 等
(8)reserve_uboot, 留出重定位后的 uboot 所占用的内存区域
(9)reserve_mmu:留出 MMU 的 TLB 表的位置
(10)reserve_malloc:reserve_malloc,留出 malloc 区域,调整 gd->start_addr_sp 位置,malloc 区域由宏TOTAL_MALLOC_LEN 定义:#define TOTAL_MALLOC_LEN (CONFIG_SYS_MALLOC_LEN +
CONFIG_ENV_SIZE),宏 CONFIG_SYS_MALLOC_LEN 为 16MB=0X1000000, 宏CONFIG_ENV_SIZE=8KB=0X2000,因此 TOTAL_MALLOC_LEN=0X1002000。调整以后
gd->start_addr_sp=0X9EF45000 //0X9FF47000-16MB-8KB=0X9EF45000
(11)reserve_board :留出板子 bd 所占的内存区,bd 是结构体 bd_t,bd_t 大小为
80 字节
(12)reserve_global_data:保留出 gd_t 的内存区域
(13)reserve_stacks 留出栈空间,先对 gd->start_addr_sp 减去 16,然后做 16 字节对齐
(14)setup_dram_config 函数设置 dram 信息,就是设置 gd->bd->bi_dram[0].start 和 gd->bd->bi_dram[0].size,后面会传递给 linux 内核,告诉 linux DRAM 的起始地址和大小。
(15)setup_reloc,设置 gd 的其他一些成员变量,供后面重定位的时候使用,并且将以
前的 gd 拷贝到 gd->new_gd 处。
最终的DRAM内存分配图如下图所示:
执行完board_init_f函数之后,ldr sp, [r9, #GD_START_ADDR_SP] 这句话会将sp = gd->start_addr_sp = 0X9EF44E90。下面三条指令,将here函数采用adr相对寻址的方式,将地址给lr,因为下面要调用relocate_code进行重定位。
adr lr, here
ldr r0, [r9, #GD_RELOC_OFF] /* r0 = gd->reloc_off */
add lr, lr, r0
然后设置 r0 =gd->relocaddr = 0X9FF47000,调用 relocate_code函数,代码如下
/* * void relocate_code(addr_moni) * * This function relocates the monitor code. * * NOTE: * To prevent the code below from containing references with an R_ARM_ABS32 * relocation record type, we never refer to linker-defined symbols directly. * Instead, we declare literals which contain their relative location with * respect to relocate_code, and at run time, add relocate_code back to them. */ ENTRY(relocate_code) ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ subs r4, r0, r1 /* r4 <- relocation offset */ beq relocate_done /* skip relocation */ ldr r2, =__image_copy_end /* r2 <- SRC &__image_copy_end */ copy_loop: ldmia r1!, {r10-r11} /* copy from source address [r1] */ stmia r0!, {r10-r11} /* copy to target address [r0] */ cmp r1, r2 /* until source end address [r2] */ blo copy_loop /* * fix .rel.dyn relocations */ ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */ ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */ fixloop: ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ and r1, r1, #0xff cmp r1, #23 /* relative fixup? */ bne fixnext /* relative fix: increase location by offset */ add r0, r0, r4 ldr r1, [r0] add r1, r1, r4 str r1, [r0] fixnext: cmp r2, r3 blo fixloop relocate_done: #ifdef __XSCALE__ /* * On xscale, icache must be invalidated and write buffers drained, * even with cache disabled - 4.2.7 of xscale core developer's manual */ mcr p15, 0, r0, c7, c7, 0 /* invalidate icache */ mcr p15, 0, r0, c7, c10, 4 /* drain write buffer */ #endif /* ARMv4- don't know bx lr but the assembler fails to see that */ #ifdef __ARM_ARCH_4__ mov pc, lr #else bx lr #endif ENDPROC(relocate_code)
uboot拷贝:r1 = __image_copy_start=0X87800000;r0=0X9FF47000,这个地址就是 uboot 拷贝的目标首地址;r0-r1 等于 0,说明 r0 和 r1 相等,也就是源地址和目的地址是一样的,那肯定就不需要拷贝了!执行 relocate_done 函数。
如果r0与r1不相等,读取 uboot 代码保存到 r10 和 r11 中,一次就只拷贝这 2 个 32 位的数据。拷贝完成以后 r1 的值会更新,保存下一个要拷贝的数据地址。然后将 r10 和 r11 的数据写到 r0 开始的地方,也就是目的地址。写完以后 r0 的值会更新,更新为下一个要写入的数据地址。
重定位:
r2=__rel_dyn_start,也就是.rel.dyn 段的起始地址
r3=__rel_dyn_end,也就是.rel.dyn 段的终止地址。
从.rel.dyn 段起始地址开始,每次读取两个 4 字节的数据存放到 r0 和 r1 寄存器中,r0 存放低 4 字节的数据,也就是 Label 地址;
r1 存放高 4 字节的数据,也就是 Label 标志。r1 中给的值与 0xff 进行与运算,其实就是取 r1 的低 8 位,判断 r1 中的值是否等于 23(0X17),如果 r1 不等于 23 的话就说明不是描述 Label 的,执行函数 fixnext。否则的话,r0 保存着 Label 值,r4 保存着重定位后的地址偏移,r0+r4 就得到了重定位后的Label 值。此时 r0 保存着重定位后的 Label 值,相当于0X87804198+0X18747000=0X9FF4B198。ldr r1, [r0]这条指定读取r0数据,这个数据就是记录原来的变量地址,由于重定位了,所以add r1, r1, r4,将原来记录的变量的存储地址也加上偏移,并将新的值写入r0,所以执行str r1, [r0]。
relocate_vectors函数代码如下。 在.config 里面定义了 CONFIG_HAS_VBAR,因此会执行CONFIG_HAS_VBAR这个分支。,r0=gd->relocaddr,也就是重定位后 uboot 的首地址,将 r0 的值写入到 CP15 的 VBAR 寄存器中,也就是将新的向量表首地址写入到寄存器 VBAR 中,设置向量表偏移。
ENTRY(relocate_vectors) #ifdef CONFIG_CPU_V7M /* * On ARMv7-M we only have to write the new vector address * to VTOR register. */ ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ ldr r1, =V7M_SCB_BASE str r0, [r1, V7M_SCB_VTOR] #else #ifdef CONFIG_HAS_VBAR /* * If the ARM processor has the security extensions, * use VBAR to relocate the exception vectors. */ ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ mcr p15, 0, r0, c12, c0, 0 /* Set VBAR */ #else /* * Copy the relocated exception vectors to the * correct address * CP15 c1 V bit gives us the location of the vectors: * 0x00000000 or 0xFFFF0000. */ ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */ mrc p15, 0, r2, c1, c0, 0 /* V bit (bit[13]) in CP15 c1 */ ands r2, r2, #(1 << 13) ldreq r1, =0x00000000 /* If V=0 */ ldrne r1, =0xFFFF0000 /* If V=1 */ ldmia r0!, {r2-r8,r10} stmia r1!, {r2-r8,r10} ldmia r0!, {r2-r8,r10} stmia r1!, {r2-r8,r10} #endif #endif bx lr ENDPROC(relocate_vectors)
c_runtime_cpu_setup 函数代码如下,不使用icache。
ENTRY(c_runtime_cpu_setup)
/*
* If I-cache is enabled invalidate it
*/
#ifndef CONFIG_SYS_ICACHE_OFF
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
#endif
bx lr
ENDPROC(c_runtime_cpu_setup)
在执行board_init_r 函数之前,首先执行mov r0, r9 ;ldr r1, [r9, #GD_RELOCADDR];r0 = gd_t ,r1 = gd->relocadd。board_init_r函数代码如下。也是initcall_run_list函数对序列init_sequence_r里面的函数进行调用初始化。
void board_init_r(gd_t *new_gd, ulong dest_addr) { #ifdef CONFIG_NEEDS_MANUAL_RELOC int i; #endif #ifdef CONFIG_AVR32 mmu_init_r(dest_addr); #endif #if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) gd = new_gd; #endif #ifdef CONFIG_NEEDS_MANUAL_RELOC for (i = 0; i < ARRAY_SIZE(init_sequence_r); i++) init_sequence_r[i] += gd->reloc_off; #endif 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, /* 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 availble * until board_init() is called below to remap IFC to high * region. */ #endif initr_reloc_global_data, #if defined(CONFIG_SYS_INIT_RAM_LOCK) && defined(CONFIG_E500) initr_unlock_ram_in_cache, #endif initr_barrier, initr_malloc, initr_console_record, #ifdef CONFIG_SYS_NONCACHED_MEMORY initr_noncached, #endif bootstage_relocate, #ifdef CONFIG_DM initr_dm, #endif initr_bootstage, #if defined(CONFIG_ARM) || defined(CONFIG_NDS32) 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 set_cpu_clk_info, /* Setup clock information */ #endif stdio_init_tables, initr_serial, initr_announce, INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_NEEDS_MANUAL_RELOC initr_manual_reloc_cmdtable, #endif #if defined(CONFIG_PPC) || defined(CONFIG_M68K) 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_LOGBUFFER initr_logbuffer, #endif #ifdef CONFIG_POST initr_post_backlog, #endif INIT_FUNC_WATCHDOG_RESET #ifdef CONFIG_SYS_DELAYED_ICACHE initr_icache_enable, #endif #if defined(CONFIG_PCI) && defined(CONFIG_SYS_EARLY_PCI_INIT) /* * Do early PCI configuration _before_ the flash gets initialised, * because PCU ressources are crucial for flash access on some boards. */ initr_pci, #endif #ifdef CONFIG_WINBOND_83C553 initr_w83c553f, #endif #ifdef CONFIG_ARCH_EARLY_INIT_R arch_early_init_r, #endif power_init_board, #ifndef CONFIG_SYS_NO_FLASH initr_flash, #endif INIT_FUNC_WATCHDOG_RESET #if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_X86) || \ defined(CONFIG_SPARC) /* initialize higher level parts of CPU like time base and timers */ cpu_init_r, #endif #ifdef CONFIG_PPC initr_spi, #endif #ifdef CONFIG_CMD_NAND initr_nand, #endif #ifdef CONFIG_CMD_ONENAND initr_onenand, #endif #ifdef CONFIG_GENERIC_MMC initr_mmc, #endif #ifdef CONFIG_HAS_DATAFLASH initr_dataflash, #endif initr_env, #ifdef CONFIG_SYS_BOOTPARAMS_LEN initr_malloc_bootparams, #endif INIT_FUNC_WATCHDOG_RESET initr_secondary_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_add_devices, initr_jumptable, #ifdef CONFIG_API initr_api, #endif console_init_r, /* fully init console as a device */ #ifdef CONFIG_DISPLAY_BOARDINFO_LATE 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_ARM) || defined(CONFIG_AVR32) initr_enable_interrupts, #endif #if defined(CONFIG_MICROBLAZE) || defined(CONFIG_AVR32) || defined(CONFIG_M68K) timer_init, /* initialize timer */ #endif #if defined(CONFIG_STATUS_LED) initr_status_led, #endif /* PPC has a udelay(20) here dating from 2002. Why? */ #ifdef CONFIG_CMD_NET initr_ethaddr, #endif #ifdef CONFIG_BOARD_LATE_INIT board_late_init, #endif #ifdef CONFIG_FSL_FASTBOOT initr_fastboot_setup, #endif #if defined(CONFIG_CMD_AMBAPP) ambapp_init_reloc, #if defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP) initr_ambapp_print, #endif #endif #ifdef CONFIG_CMD_SCSI INIT_FUNC_WATCHDOG_RESET initr_scsi, #endif #ifdef CONFIG_CMD_DOC INIT_FUNC_WATCHDOG_RESET initr_doc, #endif #ifdef CONFIG_BITBANGMII initr_bbmii, #endif #ifdef CONFIG_CMD_NET INIT_FUNC_WATCHDOG_RESET initr_net, #endif #ifdef CONFIG_POST initr_post, #endif #if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE) initr_pcmcia, #endif #if defined(CONFIG_CMD_IDE) 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 initr_bedbug, #endif #if defined(CONFIG_PRAM) || defined(CONFIG_LOGBUFFER) initr_mem, #endif #ifdef CONFIG_PS2KBD initr_kbd, #endif #if defined(CONFIG_SPARC) prom_init, #endif #ifdef CONFIG_FSL_FASTBOOT initr_check_fastboot, #endif run_main_loop, };
(1)initr_trace 函数:初始化和调试跟踪有关的内容
(2)initr_caches 函数:初始化 cache,使能 cache
(3)initr_malloc 函数:初始化 malloc
(4)initr_serial 函数:初始化串口
(5)initr_nand函数:初始化NAND
(6)initr_mmc 函数:初始化 EMMC
()run_main_loop:这个函数后面再分析
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。