一. u_boot-2016.11 引导流程分析说明

此文件为新唐 nuc980单板、arm926ejs架构,U_Boot-2016.11版本uboot工作流程分析说明。

(一). 程序业务流程

        arch/arm/cpu/u-boot.lds             /**(1). u-boot 链接文件,指定00存放向量表 *(.vectors) */ |
		|
		|
		V
		arch/arm/lib/vectors.S				/**(2). 00开始存放的向量表 */
		|
		|
		V
		arch/arm/cpu/arm926ejs/start.S     /**(3). start.S文件的 reset向量入口处  */ |
		|
		|
		V
		arch/arm/lib/crt0.S				  /**(4). _main 程序入口点文件,最后执行 ldr	pc, =board_init_r */ |
		|
		|
		V
		common/board_r.c 				 /**(5). board_init_r 程序入口点文件,执行板级初始化函数 */ |
		|
		|
		V
		common/main.c					/** (6). 初始化函数数组run_main_loop调用main_loop函数入口文件;
										 *       此函数获取bootarg参数延时等待后,执行 bootm 命令引导
										 *       内核启动。至此 uboot 引导内核任务就完成。
										*/

(1). arm架构的u-boot链接文件: arch/arm/cpu/u-boot.lds ,简化的文件内容

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { #ifndef CONFIG_CMDLINE /DISCARD/ : { *(.u_boot_list_2_cmd_*) } #endif
	. = 0x00000000;
	. = ALIGN(4);
	.text :
	{
		*(.__image_copy_start)			/** (!). uboot image 开始地址,源码中搬迁uboot时使用的开始地址 */
		*(.vectors)						/** (2). 向量表,00开始存放    */
		CPUDIR/start.o (.text*)         /** (3). reset向量指向的 start.S 文件 */
		*(.text*) }
	. = ALIGN(4);
	.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
	. = ALIGN(4);
	.data : {
		*(.data*) }
	. = ALIGN(4);
	. = .;
	. = ALIGN(4);
	.u_boot_list : { KEEP(*(SORT(.u_boot_list*))); }
	. = ALIGN(4);
	.__efi_runtime_start : {
		*(.__efi_runtime_start) }
	.efi_runtime : {
		*(efi_runtime_text)
		*(efi_runtime_data) }
	.__efi_runtime_stop : {
		*(.__efi_runtime_stop) }
	.efi_runtime_rel_start :
	{
		*(.__efi_runtime_rel_start) }
	.efi_runtime_rel : {
		*(.relefi_runtime_text)
		*(.relefi_runtime_data) }
	.efi_runtime_rel_stop :
	{
		*(.__efi_runtime_rel_stop) }
	. = ALIGN(4);
	.image_copy_end :
	{
		*(.__image_copy_end) }
	/*
	 * 代码重定向数据段
	 * 
	 */ .rel_dyn_start :
	{
		*(.__rel_dyn_start) }
	.rel.dyn : {
		*(.rel*) }
	.rel_dyn_end :
	{
		*(.__rel_dyn_end) }
	.end :
	{
		*(.__end) }
	_image_binary_end = .;
	/* MMU 数据段
	 * Deprecated: this MMU section is used by pxa at present but
	 * should not be used by new boards/CPUs.
	 */ . = ALIGN(4096);
	.mmutable : {
		*(.mmutable) }
/* 编译器保留的数据段
 * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c
 * __bss_base and __bss_limit are for linker only (overlay ordering)
 */
	.bss_start __rel_dyn_start (OVERLAY) : { KEEP(*(.__bss_start));
		__bss_base = .; }
	.bss __bss_base (OVERLAY) : {
		*(.bss*) . = ALIGN(4);
		 __bss_limit = .; }
	.bss_end __bss_limit (OVERLAY) : { KEEP(*(.__bss_end)); }
	.dynsym _image_binary_end : { *(.dynsym) }
	.dynbss : { *(.dynbss) }
	.dynstr : { *(.dynstr*) }
	.dynamic : { *(.dynamic*) }
	.plt : { *(.plt*) }
	.interp : { *(.interp*) }
	.gnu.hash : { *(.gnu.hash) }
	.gnu : { *(.gnu*) }
	.ARM.exidx : { *(.ARM.exidx*) }
	.gnu.linkonce.armexidx : { *(.gnu.linkonce.armexidx.*) } } 

(2). arch/arm/lib/vectors.S /** (2). 向量表,00开始存放 */

#include <config.h>
	.globl _start							/** _start 入口声明,与lds文件中对应 */ .section ".vectors", "ax"
	_start:
#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG 
.word	CONFIG_SYS_DV_NOR_BOOT_CFG 
#endif
		b	reset							/** 地址:0000 是复位向量地址,指向 reset 入口处 */ ldr	pc, _undefined_instruction
		ldr	pc, _software_interrupt
		ldr	pc, _prefetch_abort
		ldr	pc, _data_abort
		ldr	pc, _not_used
		ldr	pc, _irq
		ldr	pc, _fiq
#ifdef CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK
#include <asm/arch/boot0.h> 
ARM_SOC_BOOT0_HOOK 
#endif
	/*
	 *************************************************************************
	 *
	 * Indirect vectors table
	 *
	 * Symbols referenced here must be defined somewhere else
	 *
	 *************************************************************************
	 */
		.globl	_undefined_instruction
		.globl	_software_interrupt
		.globl	_prefetch_abort
		.globl	_data_abort
		.globl	_not_used
		.globl	_irq
		.globl	_fiq
	_undefined_instruction:	.word undefined_instruction
	_software_interrupt:	.word software_interrupt
	_prefetch_abort:	.word prefetch_abort
	_data_abort:		.word data_abort
	_not_used:		.word not_used
	_irq:			.word irq
	_fiq:			.word fiq
	.balignl 16,0xdeadbeef
	/*** SPL interrupt handling: just hang */ 
	#ifdef CONFIG_SPL_BUILD
	.align	5
	undefined_instruction:
	software_interrupt:
	prefetch_abort:
	data_abort:
	not_used:
	irq:
	fiq:
	1: bl	1b			/* hang and never return */
#else	/* !CONFIG_SPL_BUILD */ /*** 通用 uboot 模式的终端向量 */ /* IRQ stack memory (calculated at run-time) + 8 bytes */
	.globl IRQ_STACK_START_IN
	IRQ_STACK_START_IN: .word	0x0badc0de
#ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */
	.globl IRQ_STACK_START
	IRQ_STACK_START: .word	0x0badc0de
	/* IRQ stack memory (calculated at run-time) */
	.globl FIQ_STACK_START
	FIQ_STACK_START: .word 0x0badc0de
#endif /* CONFIG_USE_IRQ */
	@
	@ IRQ stack frame.
	@ 
#define S_FRAME_SIZE	72
#define S_OLD_R0	68 
#define S_PSR		64 
#define S_PC		60 
#define S_LR		56 
#define S_SP		52
/* ... */
#define MODE_SVC 0x13 
#define I_BIT	 0x80
	/*
	 * use bad_save_user_regs for abort/prefetch/undef/swi ...
	 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
	 */
		.macro	bad_save_user_regs
		@ carve out a frame on current user stack
		sub	sp, sp, #S_FRAME_SIZE
		stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12 ldr	r2, IRQ_STACK_START_IN
		@ get values for "aborted" pc and cpsr (into parm regs)
		ldmia	r2, {r2 - r3}
		add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
		add	r5, sp, #S_SP
		mov	r1, lr
		stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
		mov	r0, sp		@ save current stack into r0 (param register)
		.endm
		.macro	irq_save_user_regs
		sub	sp, sp, #S_FRAME_SIZE
		stmia	sp, {r0 - r12}			@ Calling r0-r12
		@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. add	r8, sp, #S_PC
		stmdb	r8, {sp, lr}^		@ Calling SP, LR
		str	lr, [r8, #0]		@ Save calling PC
		mrs	r6, spsr
		str	r6, [r8, #4]		@ Save CPSR
		str	r0, [r8, #8]		@ Save OLD_R0
		mov	r0, sp
		.endm
		.macro	irq_restore_user_regs
		ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
		mov	r0, r0
		ldr	lr, [sp, #S_PC]			@ Get PC
		add	sp, sp, #S_FRAME_SIZE
		subs	pc, lr, #4		@ return & move spsr_svc into cpsr
		.endm
		.macro get_bad_stack
		ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
		str	lr, [r13]	@ save caller lr in position 0 of saved stack
		mrs	lr, spsr	@ get the spsr
		str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
		mov	r13, #MODE_SVC	@ prepare SVC-Mode
		@ msr	spsr_c, r13
		msr	spsr, r13	@ switch modes, make sure moves will execute
		mov	lr, pc		@ capture return pc
		movs	pc, lr		@ jump to next instruction & switch modes.
		.endm
		.macro get_irq_stack			@ setup IRQ stack
		ldr	sp, IRQ_STACK_START
		.endm
		.macro get_fiq_stack			@ setup FIQ stack
		ldr	sp, FIQ_STACK_START
		.endm
	/*
	 * exception handlers
	 */
		.align  5 undefined_instruction: get_bad_stack
		bad_save_user_regs
		bl	do_undefined_instruction
		.align	5 software_interrupt: get_bad_stack
		bad_save_user_regs
		bl	do_software_interrupt
		.align	5 prefetch_abort: get_bad_stack
		bad_save_user_regs
		bl	do_prefetch_abort
		.align	5 data_abort: get_bad_stack
		bad_save_user_regs
		bl	do_data_abort
		.align	5 not_used: get_bad_stack
		bad_save_user_regs
		bl	do_not_used
#ifdef CONFIG_USE_IRQ
		.align	5 irq: get_irq_stack
		irq_save_user_regs
		bl	do_irq
		irq_restore_user_regs
		.align	5 fiq: get_fiq_stack
		/* someone ought to write a more effiction fiq_save_user_regs */ irq_save_user_regs
		bl	do_fiq
		irq_restore_user_regs
#else
		.align	5 irq: get_bad_stack
		bad_save_user_regs
		bl	do_irq
		.align	5 fiq: get_bad_stack
		bad_save_user_regs
		bl	do_fiq
#endif /* CONFIG_USE_IRQ */
#endif	/* CONFIG_SPL_BUILD */ 

(3). reset向量指向的 start.S 文件

#include <asm-offsets.h> 
#include <config.h> 
#include <common.h>
/*************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don't start from memory!
 * setup Memory and board specific bits prior to relocation.
 * relocate armboot to ram
 * setup stack
 ********************************************************/
 
	.globl	reset  /** vectors.S文件中 b reset跳转过来的,reset入口点*/ 
	reset: 
	/*
	 * set the cpu to SVC32 mode
	 */ 
	mrs	r0,cpsr
	bic	r0,r0,#0x1f
	orr	r0,r0,#0xd3
	msr	cpsr,r0
	/*
	 * we do sys-critical inits only at reboot,
	 * not when booting from ram!
	 */ 
	 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 
	 bl	cpu_init_crit 
	 #endif
	 bl	_main  /** 跳转到 arch/arm/lib/crt0.S 文件中_main入口处 */ 

(4). _main 程序入口点文件 //arch/arm/lib/crt0.S 文件

#include <config.h> 
#include <asm-offsets.h> 
#include <linux/linkage.h> 
#ifdef CONFIG_CPU_V7M 
#include <asm/armv7m.h> 
#endif
/*
 * entry point of crt0 sequence
 */
ENTRY(_main)	/** 程序入口点 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! 
						   * 执行跳转到 board_init_r 函数 
						   */ 
	#endif /* we should not return here. */ 
	#endif
ENDPROC(_main)    /** ( _main ) 程序段结束 ENDPROC  */

(5). board_init_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(); 
}
/****     函数指针数组 初始化 */
/*
 * Over time we hope to remove these functions with code fragments and
 * stub funtcions, and instead call the relevant function directly.
 *
 * We also 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?
 */ 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 
	 #ifdef CONFIG_EFI_LOADER 
	 efi_memory_init, 
	 #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 
	 #if defined(CONFIG_CMD_AMBAPP) ambapp_init_reloc, 
	 #if defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP) initr_ambapp_print, 
	 #endif 
	 #endif 
	 #ifdef CONFIG_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 	 
	/** 
	*   statge 2: entry dot, uboot 第二阶段的入口函数 run_main_loop 函数 
	*/ 
	run_main_loop,     
	};

static int run_main_loop(void) { 
#ifdef CONFIG_SANDBOX 
	sandbox_main_loop_init(); 
#endif /* main_loop() can return to retry autoboot, if so just run it again */ 
	for (;;) 
		main_loop(); /**调用函数main_loop()此函数在common/main.c文件中*/ 
		return 0; 
}

(6). 初始化函数数组run_main_loop调用main_loop函数入口文件

/* We come here after U-Boot is initialised and ready to process commands */ void main_loop(void) { const char *s;
	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
	#ifdef CONFIG_VERSION_VARIABLE 
	setenv("ver", version_string);  /* set version variable */ 
	#endif /* CONFIG_VERSION_VARIABLE */
	cli_init();
	run_preboot_environment_command();
	#if defined(CONFIG_UPDATE_TFTP) 
	update_tftp(0UL, NULL, NULL); 
	#endif /* CONFIG_UPDATE_TFTP */ 
    
    s = bootdelay_process();	
	/**
	* s 内容:烧录到spi flash中环境变量内容,参考下面6.2的env.txt文件
	*       setspi=sf probe 0 30000000
	*       loadkernel=sf read 0x7fc0 0x200000 0x800000
	* 
	* s 命令内容如下:
	*   (1)	 =run sf probe 0 30000000;   
	*   设置 spi 频率3000000Hz;    
	*   (2)  run sf read 0x7fc0 0x200000 0x800000;
	*   sf read flash 0x200000 to DDR 0x7fc0,length 0x800000;
	*   (3)  bootm 0x7fc0
	*   引导uimage内核从 0x7fc0 地址启动, 
	*   64byte(0x40) + 0x7fc0 = 0x8000 内核地址。
	*/ 
	
	if (cli_process_fdt(&s)) 
		cli_secure_boot_cmd(s);
	autoboot_command(s); /**此函数执行bootm 0x7fc0 启动引导kernel程序 */
	cli_loop();
	panic("No CLI available"); }

(6.2) 烧录到spi flash中环境变量内容,参考 env.txt 文件

baudrate=115200
bootdelay=1
stderr=serial
stdin=serial
stdout=serial
setspi=sf probe 0 30000000
loadkernel=sf read 0x7fc0 0x200000 0x800000
bootcmd=run setspi;run loadkernel;bootm 0x7fc0
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值