U-boot 21.10 启动流程梳理

news2025/1/16 20:16:34

目录

    • 背景
    • 平台启动
      • 入口确认
      • 启动源码
        • DuoS_SG2000_RISCV
        • Lubancat2_RK3568_ARM
    • 初始化流程
      • board_init_f
      • board_init_r
    • 参考

背景

  • 设备:MilkV Duo S

  • 版本:U-boot 2021.10

  • 编译命令

    # Milkv-DuoS SD卡版本,对应[board]与[config]分别为:
    # milkv-duo	 cv1800b_milkv_duo_sd
    # milkv-duos cv1813h_milkv_duos_sd
    # 拆解如下
    CHIP=cv1813h
    VENDOR=milkv
    BOARD=duos
    BOOT=sd
    
    # 得到板级目录与配置文件
    BOARD_FULL=${CHIP}-${VENDOR}-${BOARD}-${BOOT}
    CONFIG_FULL=${CHIP}_${VENDOR}_${BOARD}_${BOOT}
    
    # 加载板级配置与基础环境变量
    source device/${BOARD_FULL}/boardconfig.sh
    source build/milkvsetup.sh
    
    # 加载板级配置
    defconfig ${CONFIG_FULL}
    
    # 编译U-boot
    build_uboot
    

平台启动

入口确认

查看Kbuild生成的链接脚本u-boot-2021.10/build/cv1813h_milkv_duos_sd/u-boot.lds,内容如下:

OUTPUT_ARCH("riscv")
ENTRY(_start)
SECTIONS
{
 . = ALIGN(4);
 .text : {
  arch/riscv/cpu/start.o (.text)
 }
...

其中,关键信息攫取:

  • OUTPUT_ARCH("riscv"),目标平台为riscv;
  • ENTRY(_start),入口为_start;
  • arch/riscv/cpu/start.o (.text),入口可能存在于汇编文件arch/riscv/cpu/start.S中;

而生成该u-boot.lds脚本的命令可以参考文件u-boot-2021.10/build/cv1813h_milkv_duos_sd/.u-boot.lds.cmd,内容如下:

cmd_u-boot.lds := riscv64-unknown-linux-musl-gcc -E -Wp,-MD,./.u-boot.lds.d -D__KERNEL__ -D__UBOOT__ -DCONFIG_SKIP_RAMDISK=y -DCONFIG_USE_DEFAULT_ENV=y -DCVICHIP=cv1813h -DCVIBOARD=milkv_duos_sd -DCV1813H_MILKV_DUOS_SD -DMIPI_PANEL_HX8394 -ffixed-gp -fpic -fno-common -gdwarf-2 -ffunction-sections -fdata-sections -pipe -march=rv64imac -mabi=lp64 -mcmodel=medlow -Iinclude  -I/home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/include  -I/home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/include/cvitek  -I/home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/arch/riscv/include -include /home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/include/linux/kconfig.h -nostdinc -isystem /home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/host-tools/gcc/riscv64-linux-musl-x86_64/bin/../lib/gcc/riscv64-unknown-linux-musl/10.2.0/include -ansi -include /home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/include/u-boot/u-boot.lds.h -DCPUDIR=arch/riscv/cpu/generic  -D__ASSEMBLY__ -x assembler-with-cpp -std=c99 -P -o u-boot.lds /home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/arch/riscv/cpu/u-boot.lds

source_u-boot.lds := /home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/arch/riscv/cpu/u-boot.lds

deps_u-boot.lds := \
  /home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/include/linux/kconfig.h \
    $(wildcard include/config/booger.h) \
    $(wildcard include/config/foo.h) \
    $(wildcard include/config/spl/.h) \
    $(wildcard include/config/tpl/build.h) \
    $(wildcard include/config/spl/build.h) \
    $(wildcard include/config/spl/foo.h) \
    $(wildcard include/config/tpl/foo.h) \
    $(wildcard include/config/option.h) \
    $(wildcard include/config/acme.h) \
    $(wildcard include/config/spl/acme.h) \
    $(wildcard include/config/tpl/acme.h) \
  /home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/u-boot-2021.10/include/u-boot/u-boot.lds.h \

u-boot.lds: $(deps_u-boot.lds)

其中,关键信息:

  • cmd_u-boot.lds,u-boot.lds文件生成命令,其中有参数:
    • riscv64-unknown-linux-musl-gcc,使用GCC工具;
    • .../u-boot-2021.10/arch/riscv/cpu/u-boot.lds,源文件为arch/riscv/cpu/u-boot.lds
    • -o u-boot.lds,编译输出为u-boot.lds

查看相似文件,可以获知程序入口。

查看u-boot编译命令文件u-boot-2021.10/build/cv1813h_milkv_duos_sd/.u-boot.cmd,有如下内容:

cmd_u-boot := riscv64-unknown-linux-musl-ld.bfd -m elf64lriscv --gc-sections -static -pie -Bstatic  --no-dynamic-linker --build-id=none -Ttext 0x80200000 -o u-boot -T u-boot.lds arch/riscv/cpu/start.o --whole-archive  arch/riscv/cpu/built-in.o  arch/riscv/cpu/generic/built-in.o  arch/riscv/lib/built-in.o  board/cvitek/cv181x/built-in.o  cmd/built-in.o  common/built-in.o  disk/built-in.o  drivers/built-in.o  drivers/cvi_usb/built-in.o  drivers/dma/built-in.o  drivers/gpio/built-in.o  drivers/net/built-in.o  drivers/net/phy/built-in.o  drivers/power/built-in.o  drivers/power/battery/built-in.o  drivers/power/domain/built-in.o  drivers/power/fuel_gauge/built-in.o  drivers/power/mfd/built-in.o  drivers/power/pmic/built-in.o  drivers/power/regulator/built-in.o  drivers/serial/built-in.o  drivers/spi/built-in.o  drivers/usb/cdns3/built-in.o  drivers/usb/common/built-in.o  drivers/usb/dwc3/built-in.o  drivers/usb/emul/built-in.o  drivers/usb/eth/built-in.o  drivers/usb/host/built-in.o  drivers/usb/mtu3/built-in.o  drivers/usb/musb-new/built-in.o  drivers/usb/musb/built-in.o  drivers/usb/phy/built-in.o  drivers/usb/ulpi/built-in.o  env/built-in.o  fs/built-in.o  lib/built-in.o  net/built-in.o --no-whole-archive -L /home/gaoyang3513/Source/10-CV1800/01-MilkDuo/02-Project/CV180x_Milkv_Baseline/host-tools/gcc/riscv64-linux-musl-x86_64/bin/../lib/gcc/riscv64-unknown-linux-musl/10.2.0/lib64/lp64 -lgcc -Map u-boot.map;  true

其中,有关键信息:

  • -Ttext 0x80200000,入口地址为0x8020000,在DDR内存起始偏移128KB的位置;
  • -o u-boot -T u-boot.lds,依据链接脚本u-boot.lds编译输出u-boot文件;

启动源码

DuoS_SG2000_RISCV

查找入口_start,有如下:

$ grep -wrn "_start" u-boot-2021.10/
...
u-boot-2021.10/arch/x86/cpu/start.S:65:_start:
...
u-boot-2021.10/arch/arm/cpu/armv8/start.S:20:_start:
...
u-boot-2021.10/arch/riscv/cpu/start.S:41:_start:
...
u-boot-2021.10/arch/mips/mach-jz47xx/start.S:20:_start:
...

有多个平台的汇编入口,由上一章节链接脚本的生成过程中可知,汇编实现源文件为u-boot-2021.10/arch/riscv/cpu/start.S,内容如下:

.globl _start
_start:
	...
/*
 * Set stackpointer in internal/ex RAM to call board_init_f
 */
call_board_init_f:
	li	t0, -16
	...
	li	t1, CONFIG_SYS_INIT_SP_ADDR								// 栈指针
	and	sp, t1, t0		/* force 16 byte alignment */			// 栈寄存器初始化,16字节对齐
	...
	/* Enable cache */
	jal	icache_enable											// I-Cache 使能
	jal	dcache_enable											// D-Cache 使能
	...
	mv	a0, zero		/* a0 <-- boot_flags = 0 */
	la	t5, board_init_f
	jalr	t5			/* jump to board_init_f() */			// 调用 board_init_f
	...
/*
 * void relocate_code(addr_sp, gd, addr_moni)
 *
 * This "function" does not return, instead it continues in RAM
 * after relocating the monitor code.
 *
 */
.globl relocate_code											// 定义函数 relocate_code
relocate_code:
	mv	s2, a0			/* save addr_sp */
	mv	s3, a1			/* save addr of gd */
	mv	s4, a2			/* save addr of destination */			// 重定向的目标地址

/*
 *Set up the stack
 */
stack_setup:													// 栈初始化
#if CONFIG_IS_ENABLED(SMP)
	/* tp: hart id */
	slli	t0, tp, CONFIG_STACK_SIZE_SHIFT
	sub	sp, s2, t0
#else
	mv	sp, s2
#endif

	la	t0, _start												// 计算重定向需要的偏移量,_start是入口地址,即:0x8020000;s4是重定向的目标地址
	sub	t6, s4, t0			/* t6 <- relocation offset */		// 重定向偏移量(t6) = 目标地址(s4, addr_moni) - 入口地址(t0,_start)
	beq	t0, s4, clear_bss	/* skip relocation */				// 如果目标地址即是入口地址,即不需要搬移,跳转到BSS清零阶段运行

	mv	t1, s4			/* t1 <- scratch for copy_loop */
	la	t3, __bss_start
	sub	t3, t3, t0		/* t3 <- __bss_start_ofs */				// BSS段偏移量(t3) = 入口地址(t0,_start) - BSS地址(s3, __bss_start)
	add	t2, t0, t3		/* t2 <- source end address */			// 代码段末尾(t2) = 入口地址(t0,_start) + BSS段偏移量(t3)

copy_loop:
	LREG	t5, 0(t0)
	addi	t0, t0, REGBYTES
	SREG	t5, 0(t1)
	addi	t1, t1, REGBYTES
	blt	t0, t2, copy_loop

...

clear_bss:
	la	t0, __bss_start		/* t0 <- rel __bss_start in FLASH */
	add	t0, t0, t6		/* t0 <- rel __bss_start in RAM */
	la	t1, __bss_end		/* t1 <- rel __bss_end in FLASH */
	add	t1, t1, t6		/* t1 <- rel __bss_end in RAM */
	beq	t0, t1, relocate_secondary_harts

...

relocate_secondary_harts:
#if CONFIG_IS_ENABLED(SMP)
	...					// Duo S 单核,SMP内容忽略
#endif

/*
 * We are done. Do not return, instead branch to second part of board
 * initialization, now running from RAM.
 */
call_board_init_r:
	jal	invalidate_icache_all
	jal	flush_dcache_all
	la	t0, board_init_r    /* offset of board_init_r() */
	add	t4, t0, t6			/* real address of board_init_r() */		// board_init_r重定向后的地址 = 原地址 + 重定向偏移量(t6)
/*
 * setup parameters for board_init_r
 */
	mv	a0, s3			/* gd_t */										// 参数{gd_t, dest_addr}
	mv	a1, s4			/* dest_addr */

/*
 * jump to it ...
 */
	jr	t4			/* jump to board_init_r() */						// 调用board_init_r(重定向后)

其中,关键信息:

在这里插入图片描述

Lubancat2_RK3568_ARM
#--------------- u-boot/arch/arm/cpu/armv8/start.S
.globl	_start
_start:		
	...
master_cpu:
	bl	_main

#--------------- u-boot/arch/arm/lib/crt0.S
ENTRY(_main)

/*
 * Set up initial C runtime environment and call board_init_f(0).
 */
	...
	ldr	r0, =(CONFIG_SYS_INIT_SP_ADDR)
	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
	mov	sp, r0
	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
	bl	board_init_f_boot_flags

	bl	board_init_f										// 调用board_init_f
/*
 * 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	r0, [r9, #GD_START_ADDR_SP]	/* sp = gd->start_addr_sp */
	bic	r0, r0, #7	/* 8-byte alignment for ABI compliance */
	mov	sp, r0
	ldr	r9, [r9, #GD_BD]		/* r9 = gd->bd */
	sub	r9, r9, #GD_SIZE		/* new GD is below bd */

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
	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											// 执行重定向
#endif
here:

...
/*
 * now relocate vectors
 */
	bl	relocate_vectors

c_runtime:
/* Set up final (full) environment */

	bl	c_runtime_cpu_setup	/* we still call old routine here */	
...															// C环境初始化
	/* 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 */

	ldr	pc, =board_init_r	/* this is auto-relocated! */			// 调用board_init_r

	/* we should not return here. */
  • 执行前置的(front)初始化操作,调用board_init_f接口

    • 清除BBS段
    • 执行relocation操作
  • 执行后置的(rear)初始化操作,调用board_init_r接口

初始化流程

board_init_f

u-boot/common/board_f.c:992:void board_init_f(ulong boot_flags)
u-boot/common/spl/spl.c:708: * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
u-boot/common/spl/Kconfig:135:    stack available. Since SPL sets up DRAM while in its board_init_f()
u-boot/common/spl/Kconfig:139:    board_init_f() completes, and before board_init_r() starts.
Binary file u-boot/common/built-in.o matches
# common/board_f.c

void board_init_f(ulong boot_flags)
{
	if (initcall_run_list(init_sequence_f))
		hang();
  
static const init_fnc_t init_sequence_f[] = {
	setup_mon_len,
#ifdef CONFIG_OF_CONTROL
	fdtdec_setup,
#endif
#ifdef CONFIG_TRACE
	trace_early_init,
#endif
	initf_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
	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,
};   

board_init_r

# common/board_r.c

static 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 available
	 *	 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,
	log_init,
	initr_bootstage,	/* Needs malloc() but has its own timer */
	initr_console_record,
#ifdef CONFIG_SYS_NONCACHED_MEMORY
	initr_noncached,
#endif
	bootstage_relocate,
#ifdef CONFIG_OF_LIVE
	initr_of_live,
#endif
#ifdef CONFIG_DM
	initr_dm,
#endif
#ifdef CONFIG_BSP_SPEC
	initr_func_bsp,
#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
	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) || 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.
	 */
	initr_pci,
#endif
#ifdef CONFIG_ARCH_EARLY_INIT_R
	arch_early_init_r,
#endif
	power_init_board,
#ifdef CONFIG_MTD_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
	initr_nand,
#endif
#ifdef CONFIG_CMD_ONENAND
	initr_onenand,
#endif
#ifdef CONFIG_MMC
	initr_mmc,
#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,				// standalone 相关跳转表
#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,
#ifdef CONFIG_ARM
	initr_enable_interrupts,
#endif
#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
#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_CMD_NET
	INIT_FUNC_WATCHDOG_RESET
	initr_net,
#endif
#ifdef CONFIG_POST
	initr_post,
#endif
#if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_IDE)
	initr_pcmcia,
#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
	initr_bedbug,
#endif
#if defined(CONFIG_PRAM)
	initr_mem,
#endif
	run_main_loop,
};

参考

  1. u-boot启动流程分析(2)_板级(board)部分;
  2. 内存分布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1628379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode_相交链表

✨✨所属专栏&#xff1a;LeetCode刷题专栏✨✨ ✨✨作者主页&#xff1a;嶔某✨✨ 题目&#xff1a; 题解&#xff1a; 看到这个题目首先我们要排除链表逆置的想法&#xff0c;如图、因为c1节点只有一个next指针&#xff0c;逆置后不可能同时指向a2和b3节点。 其次有的的同学…

24深圳杯AC题完整思路+可执行代码+参考论文!!!!

比赛题目的完整版思路可执行代码数据参考论文都会在第一时间更新上传的&#xff0c;大家可以参考我往期的资料&#xff0c;所有的资料数据以及到最后更新的参考论文都是一次付费后续免费的。注意&#xff1a;&#xff08;建议先下单占坑&#xff0c;因为随着后续我们更新资料数…

【AIGC调研系列】大型语言模型如何减少幻觉生成

在解读大型语言模型&#xff08;LLMs&#xff09;中的长格式事实性问题时&#xff0c;我们首先需要认识到这些模型在生成内容时可能会产生与既定事实不一致的情况&#xff0c;这种情况通常被称为“幻觉”[2][3]。这种现象不仅可能导致信息的误传&#xff0c;还可能对社会造成误…

新时代凌迟:考研

我不喜欢上班&#xff0c;但我很欣赏老板的品味&#xff0c;因为咱们公司竟然还在订阅报纸&#xff0c;而且只有一份&#xff0c;《中国青年报》。 这份报纸我最喜欢看的是“冰点周刊”专栏&#xff0c;因为这个栏目能让读者相信&#xff1a;报纸远远可以超越一天的生命。 昨天…

跨境代买淘宝系统,跨境代采系统,淘宝代购系统,淘宝代购集运系统,1688代采系统

淘宝代购系统是一种集成的电商平台服务&#xff0c;主要针对海外用户提供购买中国大陆商品的便利通道。以下是其核心功能与特点&#xff1a; 多语言支持&#xff1a;为了满足全球用户的需求&#xff0c;代购系统提供多语言界面&#xff0c;让不同国家和地区的用户都能方便地浏…

c++初阶——类和对象(下)

大家好&#xff0c;我是小锋&#xff0c;今天我们来学习我们类和对象的最后一个章节&#xff0c;我们本期的内容主要是类和对象的一些细节进行讲解 再谈构造函数 我们在初始化时有两种方式一种是函数体内初始化&#xff0c;一种是初始化列表 我们先来看看日期类的初始化 构造…

Web3技术解析:区块链在去中心化应用中的角色

引言 在过去几年中&#xff0c;Web3技术已经成为了互联网领域的一个热门话题。作为区块链技术的延伸&#xff0c;Web3不仅仅是数字货币的代名词&#xff0c;更是一个能够为各种应用提供去中心化解决方案的强大工具。本文将深入探讨区块链在Web3去中心化应用中的关键角色&#…

【考研数学】武忠祥考研课优缺点大盘点

虽然每年大家推荐的最多的是张宇和汤家凤&#xff0c;但是我强烈推荐武忠祥老师&#xff01; 武忠祥老师真宝藏老师&#xff0c;他讲课不像张宇老师那样段子频出&#xff0c;也不想汤家凤老师那样&#xff0c;武忠祥老师有自己的方法论&#xff0c;真的有点东西&#xff0c;武…

一周学会Django5 Python Web开发-Django5 ORM执行SQL语句

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计49条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

AI工具集:解锁智能新境界,一站式解决你的所有需求!

在这个信息爆炸的时代&#xff0c;我们每天都在与大量的数据和信息打交道。如何高效地处理这些信息&#xff0c;提高工作效率和生活品质&#xff0c;成为了我们亟待解决的问题。而AI工具集(AI-321.com)的出现&#xff0c;无疑为我们提供了一把解锁智能新境界的钥匙。 AI-321 | …

基于streamlit快速部署机器学习项目(Public URL)

基于streamlit的AIGC项目前端展示 1.Streamlit 简介与入门1.1 安装 Streamlit1.2 开发Streamlit应用程序1.3 启动并运行1.3.1 本地运行1.3.2 部署 现在LLM技术发展迅速&#xff0c;很多人在学习的时候&#xff0c;都想展示效果&#xff0c;并且想部署在服务器上&#xff0c;但是…

Zephyr sensor子系统学习

一、背景 2023年7月份nRF Connect SDK 2.4.0最新版本&#xff0c;使用的Zephyr V3.3版本。从Zephyr 3.5版本在子系统中加入了sensing子系统。 现在最新的nRF Connect SDK 2.6.0 release支持v3.5.99-ncs1&#xff0c;已经支持sensing子系统 nRF52840现在官方支持两个传感器de…

Rust中的函数指针

什么是函数指针 通过函数指针允许我们使用函数作为另一个函数的参数。函数的类型是 fn &#xff08;使用小写的 ”f” &#xff09;以免与 Fn 闭包 trait 相混淆。fn 被称为 函数指针&#xff08;function pointer&#xff09;。指定参数为函数指针的语法类似于闭包。 函数指…

阿里前端常考vue面试题汇总_阿里高级vue面试题

改变 ![](https://img-blog.csdnimg.cn/img_convert/b736620bcd29f08f3685022ab5583d8b.webp?x-oss-processimage/format,png)你会发现&#xff0c; **只有改变的栏目才闪烁&#xff0c;也就是进行重绘** &#xff0c;数据没有改变的栏目还是保持原样&#xff0c;这样就大大节…

(3)C程序可执行文件的生成过程

原文链接&#xff1a;https://www.jianshu.com/p/b7e44f749211 一、可执行文件的生成 我们先通过一个简单C程序&#xff0c;回顾一下可执行文件的生成过程。 ​​​​​​​ ​​​​​​​ 可执行文件的生成过程如下图&#xff1a; 如图&#xff0c;可执行文…

Java学习路线及自我规划

荒废了一段时间&#xff0c;这段时间的总结开始了JavaWeb的学习但是困难重重&#xff0c;例如Maven&#xff0c;Vue的路由等&#xff0c;所以我反省了一段时间&#xff0c;因为基础薄弱&#xff0c;加之学习的资源是速成视频&#xff0c;导致大厦将倾的局面&#xff08;也算不上…

为什么如果重写了某个类的equals方法,还必须重写对应的hashcode方法?

为什么如果重写了某个类的equals方法&#xff0c;还必须重写对应的hashcode方法&#xff1f; 答&#xff1a; 保证equals相同的两个对象hashcode必须相同的原则。不重写hashcode方法的的话&#xff0c;若用hashmap/hashset等散列表存储这个类&#xff0c;可能会出现两个相同对…

IDEA上配置Maven环境

1.选择IDEA中的Setting 2.搜索maven 3.设置IDEA使用本地安装的Maven&#xff0c;并修改配置文件路径 配置文件&#xff0c;本地仓库&#xff0c;阿里云仓库配置及路径教程 在IDEA上配置完成。

java中http调用组件深入详解

目录 一、前言 二、http调用概述 2.1 什么是http调用 2.1.1 http调用步骤 2.2 HTTP调用特点 2.3 HTTP调用应用场景 三、微服务场景下http调用概述 3.1 微服务开发中http调用场景 3.2 微服务组件中http的应用 四、常用的http调用组件 4.1 java中常用的http组件介绍 4…

输入输出重定向,追加重定向(Linux)

文章目录 一、输出重定向二、追加重定向三.输入重定向总结 一、输出重定向 我们在使用echo内容时&#xff0c;会把内容显示在显示器上。 echo自动换行。 我们如果输入 echo “hello linux” >file.txt 我们运行一下就会发现系统中多了一个file.txt的文件&#xff0c;如果这…