1. U-Boot概述与Rockchip平台介绍
大家好,我是你们的讲师。做嵌入式底层开发这么多年,我接触过不少Bootloader,但U-Boot始终是我最常用的一个。今天咱们就从U-Boot的历史讲起,再聊聊Rockchip这个平台的特点,最后把整个启动流程串一遍。
1.1 U-Boot的历史与作用
U-Boot,全称是"Universal Boot Loader"。说白了,它就是一块芯片上电后,在操作系统内核跑起来之前,负责初始化硬件、加载内核的那段程序。
我记得最早接触U-Boot是在2008年左右,那时候它还叫PPCBoot,主要支持PowerPC架构。后来逐渐演变成了支持ARM、MIPS、x86等多种架构的通用Bootloader。为什么它能活到现在?我觉得核心原因有两个:一是开源,二是社区活跃。
U-Boot的核心作用:
- 硬件初始化:设置时钟、配置DDR、初始化串口等外设
- 引导操作系统:从Flash、SD卡、网络等介质加载内核
- 提供调试接口:通过命令行交互,方便开发调试
- 支持多种启动介质:eMMC、NAND Flash、SPI NOR、SD卡、USB、网络
你想想看,没有U-Boot,芯片上电后CPU直接跑内核?那是不可能的。因为DDR还没初始化,内核代码都没地方放。所以U-Boot就是那个"铺路"的角色。
1.2 Rockchip SoC家族概览
Rockchip这家公司,做嵌入式的人应该都不陌生。从早期的RK28xx系列,到现在的RK35xx系列,我几乎每一代都碰过。说实话,Rockchip的文档质量早期确实一般,但近几年改善了很多。
下面这张表是我整理的Rockchip主流SoC对比,方便大家快速了解:
| 系列 | 典型型号 | CPU架构 | 典型应用 | 我遇到的坑 |
|---|---|---|---|---|
| RK33xx | RK3328、RK3399 | Cortex-A53/A72 | 电视盒子、NAS | DDR训练参数容易配错 |
| RK35xx | RK3568、RK3588 | Cortex-A55/A76 | 边缘计算、AI盒子 | PMIC时序要求严格 |
| RV11xx | RV1126、RV1109 | Cortex-A7 | IPC摄像头 | NPU驱动加载顺序 |
个人建议:新手入门Rockchip,建议从RK3568开始。资料相对齐全,社区支持好,而且这颗芯片的DDR训练流程比较典型,适合学习。
1.3 启动流程概览
Rockchip的启动流程,我当年第一次看的时候也觉得挺绕。但说白了,就是"多阶段引导"。为什么要分这么多阶段?因为芯片内部SRAM太小,放不下完整的U-Boot。
完整的启动链路是这样的:
- BootROM:芯片内部固化的只读代码,上电后CPU第一条指令就在这里
- TPL:初始化DDR,为后续代码提供运行空间
- SPL:加载U-Boot proper到DDR中
- U-Boot proper:完整的U-Boot,负责加载内核
下面这张图是我手绘的启动流程,大家感受一下:
1.4 各阶段详解
1.4.1 BootROM
BootROM是芯片内部的一块只读存储器,出厂时就写好了。它的任务很简单:检测启动介质,加载下一级代码。Rockchip的BootROM支持从eMMC、SD卡、SPI NOR、USB等多种介质启动。
注意:BootROM的代码你是改不了的。我曾经遇到一个项目,客户非要改BootROM的启动顺序,结果折腾了两周才发现这条路走不通。最后只能通过修改硬件复位逻辑来解决。
1.4.2 TPL(Tiny Program Loader)
TPL是U-Boot的第一个"可编程"阶段。它的核心任务只有一个:初始化DDR。为什么要把DDR初始化单独拎出来?因为DDR的初始化需要复杂的训练过程,而BootROM里放不下这么多代码。
我记得在RK3399上调试DDR时,遇到过一个问题:同样的代码,换了一批DDR颗粒就起不来了。后来发现是DDR训练参数需要根据颗粒型号微调。嗯,这里要提醒大家,DDR参数不是随便抄的。
1.4.3 SPL(Secondary Program Loader)
SPL是U-Boot的"第二阶段加载器"。此时DDR已经可用,SPL可以加载更大的代码了。它的任务是从存储介质中读取U-Boot proper,放到DDR中,然后跳转过去。
SPL的大小通常被限制在几十KB以内,因为很多芯片的SRAM就这么大。所以SPL里只保留最核心的功能:存储驱动、文件系统支持、以及基本的命令行交互。
1.4.4 U-Boot proper
U-Boot proper就是咱们常说的"完整版U-Boot"。它运行在DDR中,拥有完整的驱动支持、网络协议栈、文件系统支持、以及丰富的命令行工具。到了这个阶段,你可以做很多事情:
- 通过TFTP从网络加载内核
- 从eMMC或SD卡读取内核和设备树
- 修改环境变量,配置启动参数
- 执行内存测试、Flash擦写等调试操作
我的经验:在调试阶段,我习惯在U-Boot proper里加一些自定义命令,比如打印寄存器值、测试特定外设。这样能快速定位问题,不用每次都重新编译内核。
1.5 启动介质的选择
Rockchip支持多种启动介质,优先级由芯片的"启动源选择"引脚决定。下面这个表格列出了常见的启动介质及其特点:
| 启动介质 | 速度 | 可靠性 | 适用场景 |
|---|---|---|---|
| eMMC | 快 | 高 | 量产产品 |
| SD卡 | 中等 | 中等 | 开发调试 |
| SPI NOR | 慢 | 高 | 小容量启动 |
| USB | 中等 | 低 | 烧录/恢复 |
| 网络 | 依赖网络 | 低 | 无盘启动 |
我个人习惯在开发阶段用SD卡启动,方便反复烧写。量产时再切到eMMC,稳定可靠。
1.6 小结
这一章咱们把U-Boot和Rockchip平台的基本概念捋了一遍。从U-Boot的历史作用,到Rockchip的SoC家族,再到那套"BootROM -> TPL -> SPL -> U-Boot proper"的启动流程。说白了,就是理解芯片上电后,代码是怎么一步步从只读存储器跑到DDR里的。