U-Boot初始化及工作流程分析

本文解析了U-Boot启动过程中的lowlevel_init(), board_init_f(), 和 board_init_r()三个关键函数,涉及CPU初始化、SDRAM配置和串口设置。详细介绍了各阶段在不同架构处理器上的执行细节和相关代码路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0. 概述

U-Boot通常是从架构相关的汇编文件(尾缀为大写S的汇编文件意为可链接)中获取第一条执行的指令,例如:

- arch/arm/cpu/armv7/start.S
- arch/powerpc/cpu/mpc83xx/start.S
- arch/mips/cpu/start.S

在以上所列出的汇编文件中,主要执行如下三个函数:

lowlevel_init()
board_init_f()
board_init_r()

完整的执行流程如下图所示:

U-Boot代码执行流程

1. lowlevel_init()

不同架构类型的处理器会单独定义lowlevel_init.S文件,例如:

./arch/arm/cpu/armv7/lowlevel_init.S
./arch/arm/cpu/armv8/lowlevel_init.S
./arch/mips/mach-ath79/ar933x/lowlevel_init.S

该函数的基本功能是使得CPU可以获取、执行到board_init_f()函数。在此函数中没有栈信息,不能设置SDRAM和控制台。

.pushsection .text.lowlevel_init, "ax"
WEAK(lowlevel_init)
#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
	ldr	sp, =CONFIG_SPL_STACK
#else
	ldr	sp, =CONFIG_SYS_INIT_SP_ADDR
#endif
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
#ifdef CONFIG_SPL_DM
	mov	r9, #0
#else
#ifdef CONFIG_SPL_BUILD
	ldr	r9, =gdata
#else
	sub	sp, sp, #GD_SIZE
	bic	sp, sp, #7
	mov	r9, sp
#endif
#endif
	push	{ip, lr}
	bl	s_init
	pop	{ip, pc}
ENDPROC(lowlevel_init)
.popsection

2. board_init_f()

为执行board_init_r做准备,需要初始化两个关键功能:SDRAM和串口。
在此阶段,global_data已经可以使用,栈信息位于SRAM中。由于BSS段仍然无法使用,因此,不可以使用全局/静态变量。

若U-Boot中开启了SPL功能,则在common/spl.c代码中可以实现该函数,否则,通常以common/board_f.c中实现为准。

board_init_f()中调用的函数在数组init_sequence_f[]中定义:

static const init_fnc_t init_sequence_f[] = {
	setup_mon_len,
......
	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 */
	checkcpu,
#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
......
#if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
		!CONFIG_IS_ENABLED(X86_64)
	jump_to_copy,
#endif
	NULL,
};

3. board_init_r()

U-Boot执行到此处,已经进入到正常的功能代码调用流程,例如设备驱动、命令行、镜像搬移加载等功能。

若U-Boot中开启了SPL功能,则在common/spl.c代码中可以实现该函数,否则,通常以common/board_r.c中实现为准。

board_init_r()中调用的函数在数组init_sequence_r[]中定义:

static init_fnc_t init_sequence_r[] = {
	initr_trace,
	initr_reloc,
......
#ifdef CONFIG_MMC
	initr_mmc,
#endif
......
	run_main_loop,
};

以上所有的功能相关的初始化中,CPU相关的初始化代码通常位于如下路径:

linux@u-boot$ ls arch/arm/
config.mk      lib           mach-davinci     mach-keystone  mach-orion5x   mach-snapdragon  mach-tegra      mach-zynqmp-r5
cpu            mach-aspeed   mach-exynos      mach-kirkwood  mach-owl       mach-socfpga     mach-uniphier   Makefile
dts            mach-at91     mach-highbank    mach-mediatek  ......
linux@u-boot$

板级相关的初始化代码通常位于如下路径:

linux@u-boot$ ls board/
abilis          bluewater     corscience     ge           lg           qca             sifive             toradex
advantech       bosch         creative       geekbuying   l+g          qemu-mips       silica             tplink
alliedtelesis   boundary      cssi           google       liebherr     qualcomm        sks-kinkel         tqc
altera          broadcom      CZ.NIC         grinn        logicpd      quipos          socrates           ucRobotics
......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux与SoC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值