1. 课程导入
嵌入式系统从上电到操作系统内核开始运行,看似只是“几秒钟”的过程,实际上经历了一条非常长且高度耦合的启动链路:芯片内部固化的 BootROM 首先执行,随后加载一级引导程序、二级引导程序,完成时钟、内存、存储与外设初始化,再加载操作系统内核、设备树与根文件系统,最终把控制权交给内核。这条链路上任何一环出错,现象往往都表现为“串口无输出”“卡在某一阶段”“反复重启”或“内核 panic”。本课程的目标,就是把这整条链路拆开、看清、可观测、可定位,形成一套系统化的启动调试工程方法。
一、学习目标:从“能启动”到“能定位为什么不能启动”
本课程不是简单地罗列启动流程,而是围绕“调试工程”构建能力。学完本课程后,应当具备以下四类能力:
- 链路认知能力:能够准确说出从 BootROM 到内核启动的每一个阶段、每一级加载者与被加载者、每一阶段的运行位置(片内 SRAM、DDR、Cache)和交接条件。
- 现象定位能力:面对“无输出”“卡死”“重启”“panic”等典型现象,能够根据启动阶段特征快速缩小故障范围,而不是盲目换板、换线、换镜像。
- 工具使用能力:熟练使用串口日志、JTAG/调试器、示波器/逻辑分析仪、启动模式引脚、镜像校验工具、内核 earlycon 等手段获取证据。
- 工程化能力:能够建立可复现的启动调试环境,记录启动日志、版本信息、寄存器快照,形成可回溯的排障记录。
二、核心概念:启动链路上的关键角色
理解启动调试,必须先建立几个稳定的概念锚点。BootROM 是芯片出厂时固化在片内只读存储中的一段代码,它在上电复位后最先运行,负责最基本的启动介质探测和第一级镜像加载。由于它不可修改,调试时只能通过启动模式引脚、外部介质内容和串口输出间接观察它。一级引导程序(如 SPL、BL1、BootROM 加载的头部镜像)通常运行在片内 SRAM 中,负责初始化 DDR 等关键资源。二级引导程序(如 U-Boot、BL2/BL31)运行在 DDR 中,负责加载内核、设备树和根文件系统。内核启动阶段则包括解压、早期初始化、驱动探测、挂载根文件系统并启动 init 进程。
另一个关键概念是“交接点”。每一级引导程序把控制权交给下一级时,都会约定入口地址、参数结构(如 ATAGS、设备树地址)、CPU 状态和内存布局。交接点出错,往往表现为下一级完全没有输出,或者输出乱码。调试时,交接点是最值得设置断点和打印日志的位置。
三、整体框架:一张图看清启动链路与调试观测点
下面的 SVG 展示了从复位到内核启动的完整链路,并标注了每一阶段可用的调试观测手段。它既是本课程的整体框架,也是后续章节反复引用的“地图”。
四、调试工具链概览:不同阶段用不同工具
启动调试最忌讳“一把锤子敲所有钉子”。不同阶段的可观测性差异很大,工具选择也应随之变化。下表给出阶段与工具的对应关系,可作为实际排障时的速查清单。
| 启动阶段 | 运行位置 | 主要调试工具 | 典型可观测信息 |
|---|---|---|---|
| BootROM | 片内 ROM | 启动模式引脚、示波器、JTAG | 复位电平、时钟、启动介质片选 |
| 一级引导 SPL | 片内 SRAM | 串口、JTAG、镜像校验工具 | DDR 初始化结果、镜像头部校验 |
| 二级引导 U-Boot | DDR | 串口控制台、环境变量、网络加载 | 内核加载地址、设备树地址、启动参数 |
| 内核早期初始化 | DDR | earlycon、earlyprintk、JTAG | 解压地址、设备树解析、时钟与中断控制器 |
| 根文件系统与 init | DDR | 串口登录、内核日志、initramfs 调试 | 挂载失败原因、init 脚本执行顺序 |
五、典型场景与误区复盘
一个常见场景是:板子上电后串口没有任何输出。初学者往往直接怀疑内核镜像损坏,但更合理的顺序是先确认复位是否释放、晶振是否起振、启动模式引脚是否选择了正确的介质。因为 BootROM 阶段没有任何软件日志,只能靠硬件信号判断。若示波器看到时钟正常、复位正常,但启动介质片选没有动作,则问题很可能在启动模式配置或介质本身。
另一个典型场景是:U-Boot 有输出,但加载内核后卡住。此时应重点检查内核加载地址、设备树地址与 U-Boot 传递参数是否一致,以及内核是否配置了正确的 earlycon。很多“内核无输出”其实是串口驱动尚未初始化,而 earlycon 没有打开,导致早期日志被丢弃。
本课程后续将沿着这条链路逐段展开:先讲 BootROM 与启动模式,再讲 SPL 与 DDR 初始化,然后进入 U-Boot 加载流程、内核早期启动、设备树与根文件系统,最后落到系统化排障方法与工程记录规范。掌握本节的整体框架和工具对应关系,是后续每一章能够“对号入座”的前提。