1. U-Boot 概述:从历史到源码结构
做嵌入式开发这些年,我接触过不少 bootloader。从早期的 RedBoot 到 Barebox,各有各的脾气。但要说哪个最普及、社区最活跃、文档最全——那还得是 U-Boot。说白了,它就是嵌入式世界的「标准件」。今天咱们就从它的历史、定位和源码结构聊起。
1.1 U-Boot 的历史与作用
U-Boot 的全称是 Das U-Boot,德语里是「潜艇」的意思。这个名字挺有意思,暗示它像潜艇一样潜伏在系统底层。
它最早源于 1999 年的 PPCBoot 项目,专门给 PowerPC 平台用。后来 ARM 火了,社区把它扩展成了 U-Boot。我记得 2010 年左右我刚入行时,U-Boot 还只支持几十款板子。现在呢?上千种 SoC 和开发板都能跑。
U-Boot 的核心作用就三件事:
- 初始化硬件——时钟、DDR、串口、存储控制器,让板子「活过来」
- 加载操作系统——从 Flash、SD 卡、网络把内核和设备树搬到内存
- 提供交互环境——通过串口命令行调试、烧写、测试硬件
一句话总结:U-Boot 是硬件和操作系统之间的「翻译官」。没有它,CPU 上电后只能跑死循环。
1.2 U-Boot 在嵌入式系统中的位置
你想想看,一块嵌入式板子上电后,执行顺序是这样的:
- ROM Code(芯片内部固件)——初始化最基础的时钟和存储,加载 U-Boot SPL
- SPL(Secondary Program Loader)——初始化 DDR,加载完整的 U-Boot
- U-Boot 主程序——初始化外设,加载内核
- Linux 内核——接管系统
U-Boot 就站在第 2 和第 3 步。它不像 BIOS 那样固化在主板上,而是存在 Flash 里,可以随时更新。这一点在项目开发阶段特别方便——我经常一天刷十几次 U-Boot,调试新板子的 DDR 参数。
我的经验:很多新手以为 U-Boot 只负责「引导内核」。其实它还是个强大的硬件测试工具。我曾经用 U-Boot 的 md/mw 命令直接读写寄存器,定位过好几起 DDR 布线问题。
1.3 U-Boot 源码结构概览
U-Boot 的源码目录乍一看挺吓人,但摸清规律后其实很清晰。我习惯把它分成几个大块:
| 目录/文件 | 作用 | 我关注的点 |
|---|---|---|
arch/ |
CPU 架构相关代码(arm、riscv、x86 等) | 启动汇编、异常向量表、cache 操作 |
board/ |
具体板级代码(DDR 参数、GPIO 配置) | 移植时改得最多的目录 |
drivers/ |
外设驱动(串口、网卡、MMC、SPI 等) | 调试新硬件时重点看 |
common/ |
通用命令和框架代码 | cli、bootm、环境变量处理 |
include/ |
头文件和配置文件 | configs/ 下的板级配置 |
net/ |
网络协议栈 | tftp、nfs 引导相关 |
fs/ |
文件系统支持(ext4、fat、ubifs) | 从存储设备读内核时用到 |
tools/ |
主机端工具(mkimage、fdt 处理) | 制作 U-Boot 镜像时必用 |
嗯,这里要注意:arch/arm/ 下面还有 cpu/ 子目录,里面按厂商分(armv7、armv8、tegra、omap 等)。我第一次移植时就在这迷过路——找了半天没找到 start.S,后来才发现它在 arch/arm/cpu/armv7/ 里。
避坑指南:我曾经犯过一个低级错误——直接在 board/ 目录下改别人的板级文件,结果编译出来跑不起来。后来才明白,U-Boot 的板级代码和配置是强耦合的。改板子一定要新建目录,别偷懒。
1.4 U-Boot 启动流程全景图
为了让你对 U-Boot 的整体脉络有个直观印象,我画了张流程图。这张图涵盖了从 CPU 上电到加载内核的完整路径:
这张图里,阶段 2 和阶段 3 是我们移植工作的重点。SPL 负责把 DDR 初始化好,主程序负责把外设驱动起来。我见过不少项目在 SPL 阶段卡住——DDR 参数配错了,串口死活没输出。这时候连调试都难,只能靠逻辑分析仪。
1.5 为什么选择 U-Boot?
你可能要问:市面上 bootloader 那么多,为什么偏偏选 U-Boot?
- 社区活跃——邮件列表每天几百封,遇到问题基本能找到答案
- 架构支持广——ARM、RISC-V、x86、MIPS、PowerPC,全都有
- 驱动模型统一——从 2016 年开始引入 DM(Driver Model),写驱动比以前规范多了
- 调试工具丰富——md/mw 读写内存、i2c 探测、mmc 读写、网络 ping,基本够用
我的建议:如果你刚开始学 U-Boot 移植,别急着看源码。先拿一块成熟的开发板(比如 BeagleBone Black 或 Raspberry Pi),把 U-Boot 编译烧进去,跑起来。亲眼看到串口打印出 U-Boot 的 logo,比读十遍代码都有用。
1.6 本章小结
这一章我们聊了 U-Boot 的来龙去脉、它在系统里的位置,以及源码目录怎么组织。说白了,U-Boot 就是个「硬件初始化 + 内核加载器」,但它的灵活性和社区支持让它成了嵌入式开发的事实标准。