[uboot] (第三章)uboot流程——uboot-spl代码流程

本文详细解析了uboot-spl的入口、配置、任务和核心代码流程,包括_start、reset、cpu_init_cp15、cpu_init_crit、_main等步骤。重点介绍了在armv7架构下关闭中断、禁用MMU、初始化CPU和板级设置的过程,以及如何加载BL2并跳转到uboot。

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

以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为例。

[uboot] uboot流程系列
[project X] tiny210(s5pv210)上电启动流程(BL0-BL2)
[uboot] (第一章)uboot流程——概述
[uboot] (第二章)uboot流程——uboot-spl编译流程

建议参考文章
[kernel 启动流程] (第二章)第一阶段之——设置SVC、关闭中断
[kernel 启动流程] (第六章)第一阶段之——打开MMU
ARM的CP15协处理器的寄存器

建议先看《[project X] tiny210(s5pv210)上电启动流程(BL0-BL2)》,根据例子了解一下上电之后的BL0\BL1\BL2阶段,以及各个阶段的运行位置,功能。

========================================================================================================

一、说明

1、uboot-spl入口说明

通过uboot-spl编译脚本project-X/u-boot/arch/arm/cpu/u-boot-spl.lds

ENTRY(_start)

所以uboot-spl的代码入口函数是_start
对应于路径project-X/u-boot/arch/arm/lib/vector.S的_start,后续就是从这个函数开始分析。

2、CONFIG_SPL_BUILD说明

前面说过,在编译SPL的时候,编译参数会有如下语句:
project-X/u-boot/scripts/Makefile.spl

KBUILD_CPPFLAGS += -DCONFIG_SPL_BUILD

所以说在编译SPL的代码的过程中,CONFIG_SPL_BUILD这个宏是打开的。
uboot-spl和uboot的代码是通用的,其区别就是通过CONFIG_SPL_BUILD宏来进行区分的。

二、uboot-spl需要做的事情

CPU初始刚上电的状态。需要小心的设置好很多状态,包括cpu状态、中断状态、MMU状态等等。
在armv7架构的uboot-spl,主要需要做如下事情

  • 关闭中断,svc模式
  • 禁用MMU、TLB
  • 芯片级、板级的一些初始化操作
    • IO初始化
    • 时钟
    • 内存
    • 选项,串口初始化
    • 选项,nand flash初始化
    • 其他额外的操作
  • 加载BL2,跳转到BL2

上述工作,也就是uboot-spl代码流程的核心。

三、代码流程

1、代码整体流程

代码整体流程如下,以下列出来的就是spl核心函数。
_start———–>reset————–>关闭中断
………………………………|
………………………………———->cpu_init_cp15———–>关闭MMU,TLB
………………………………|
………………………………———->cpu_init_crit————->lowlevel_init————->平台级和板级的初始化
………………………………|
………………………………———->_main————–>board_init_f_alloc_reserve & board_init_f_init_reserve & board_init_f———->加载BL2,跳转到BL2
board_init_f执行时已经是C语言环境了。在这里需要结束掉SPL的工作,跳转到BL2中。

2、_start

上述已经说明了_start是整个spl的入口,其代码如下:
arch/arm/lib/vector.S

_start:
#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
    .word   CONFIG_SYS_DV_NOR_BOOT_CFG
#endif
    b   reset

会跳转到reset中。
注意,spl的流程在reset中就应该被结束,也就是说在reset中,就应该转到到BL2,也就是uboot中了。
后面看reset的实现。

3、reset

建议先参考[kernel 启动流程] (第二章)第一阶段之——设置SVC、关闭中断,了解一下为什么要设置SVC、关闭中断以及如何操作。

代码如下:
arch/arm/cpu/armv7/start.S


                
### U-Boot SPL 启动过程详解 #### 定义与作用 U-Boot SPL (Secondary Program Loader) 是一种小型引导加载程序,在嵌入式系统的启动过程中起着至关重要的角色。由于 SRAM 存储器容量有限,通常仅有 48 KiB 可供使用[^3]。因此,SPL 被设计成能够快速初始化基本硬件资源,并将主要的 U-Boot 映像从外部存储介质(如 MMC/SD 卡)复制到 RAM 中。 #### 启动流程概述 SPL 的启动流程遵循 U-Boot 整体架构的设计原则,但在功能上有所简化和针对性优化: 1. **初始环境准备** - 上电复位后,CPU 开始执行位于 ROM 或者内部 SRAM 中最基础的指令集。 - 这些指令负责设置堆栈指针、清除 BSS 段等内容,为后续操作提供稳定的运行平台[^1]。 2. **低级硬件初始化** - 对 CPU 寄存器进行必要的配置调整,确保其工作状态适合进一步的操作需求。 - 初始化时钟源与时序控制器,使系统频率达到预期水平;同时激活电源管理单元以支持更多外设供电。 3. **内存子系统建立** - 如果目标设备具备 SDRAM 控制器,则需在此阶段完成相应的参数设定以及训练序列,从而让 DRAM 成功进入可读写模式。 - 配置好之后即可利用大容量随机访问存储作为临时缓冲区来装载完整的 U-Boot 影像文件。 4. **加载主引导镜像** - 使用 SPI Flash, eMMC 等接口读取预先烧录好的 U-Boot 主体部分数据流。 - 将获取的数据按照指定地址映射至之前预备完毕的工作区内存位置处。 5. **跳转执行全量版 U-Boot** - 设置 PC(program counter)寄存器指向新加载的 U-Boot 入口点偏移地址。 - 正式移交控制权给更高级别的固件组件继续处理剩余的任务直至最终启动 Linux 内核或其他操作系统实例[^4]。 ```c // 示例代码片段展示如何切换到新的 U-Boot 实例 void __attribute__((noreturn)) jump_to_uboot(unsigned long addr) { typedef void (*image_entry_point)(void); ((image_entry_point)addr)(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值