news 2026/10/29 3:14:01

从ROM Code到Kernel:嵌入式启动链路四阶段拆解与排查指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从ROM Code到Kernel:嵌入式启动链路四阶段拆解与排查指南

简介:这份文档面向嵌入式开发初学者与底层系统学习者,系统梳理芯片从上电复位到操作系统启动的完整链路,帮助理解 ROM Code、SPL、U-Boot 与 Kernel 四个阶段各自承担的任务及相互依赖关系。内容涵盖 CPU 进入 handler 模式后的初始化流程、SD 卡与 UART/USB 下载模式的判断逻辑、SPL 因片内 SRAM 容量有限而先搬运前 70KB 程序再加载剩余内容至 DDR 的机制,以及 U-Boot 支持的多种 boot 方式与 ptset 测试模式。资源包共 1 个 docx 文件,约 1.41MB,以文字与流程说明为主,适合作为学习笔记或查阅手册。目前已有 923 人学习,读者可借此建立对芯片启动流程的整体认知,为深入理解操作系统引导与芯片工作原理打下基础。

1. 上电到内核:一份把 ROM Code 到 Kernel 讲透的启动链路笔记

板子插上电,串口一行输出都没有,这种场景做过嵌入式的人多少都遇到过。翻遍原理图、换过电源、量过晶振,最后发现问题出在启动链路的前两级——ROM Code 根本没把 SPL 拉起来。芯片启动 boot 这条链路,从复位向量到内核接管,中间隔着 ROM Code、SPL、U-Boot、Kernel 四道关卡,任何一道配置错位,现象都是“上电没反应”,但根因可能完全不同。这份《芯片的boot过程.docx》把四阶段的任务边界、SD/eMMC/UART/USB 多种启动模式的分流逻辑、以及 ptset 测试模式的旁路关系梳理成了一条可对照的链路图。它适合刚接触 SoC 启动流程的固件工程师,也适合需要定位“卡在 SPL 还是卡在 U-Boot”的驱动开发者——不是科普读物,是一份可以对着串口日志逐级核对的排查底稿。

2. 四阶段职责拆解:每一级到底在替谁干活

启动链路最容易混淆的地方,是把“谁加载谁”和“谁初始化什么”搅在一起。ROM Code 负责最底层的 CPU 与系统初始化并把二级程序搬进片内 SRAM;SPL 在 SRAM 这个狭小空间里完成 DDR 训练和剩余镜像的搬运;U-Boot 在 DDR 里跑起来后才有能力读文件系统、加载内核;Kernel 最后接管全部硬件。四级之间是严格的接力关系,前一级没跑完,后一级连代码都不会被执行。理解这条链,关键在于记住每一级的“运行位置”和“可用资源”——SRAM 只有几十到几百 KB,DDR 要等 SPL 训练完才可用,这个资源约束决定了每一级能干什么、不能干什么。

2.1 ROM Code:复位向量之后的第一次呼吸

芯片上电复位,CPU 从固定地址取指,进入 handler 模式(对应 reset 异常向量),ROM Code 的第一条指令开始执行。这一级做的事情分两段:先做 CPU init,包括基本寄存器配置和异常向量建立;然后判断是否进入 ptset 测试模式,如果不进,就转入 system init,把键盘、UART 这类启动阶段就要用的模块配置好。UART 初始化尤其关键,因为后续所有调试输出都依赖它,很多“上电无输出”的问题其实是 ROM Code 阶段 UART 引脚复用或波特率配置没对上。

系统初始化完成后,ROM Code 开始判断启动介质。以 SD 卡启动为例,它会配置 SD 卡控制器,把卡上的内容读到 AON RAM(片内常开 SRAM)中运行,这段被读进来的程序就是 SPL。如果是 UART 或 USB 下载模式,则先走 download 流程把 bootloader 传进来再执行。这里有个容易被忽略的细节:ROM Code 支持的启动介质顺序通常由硬件 strapping 引脚或 eFuse 决定,板子上电时采样到的引脚电平直接决定了它去哪个介质找程序,软件层面改不了。

2.2 SPL:70KB 的 SRAM 里做最重的活

SPL 全称 Secondary Program Loader,它运行在片内 AON SRAM 里,空间极其有限。文档里提到一个具体数字:先搬运 SD 卡前 70KB 的程序过来运行。这个 70KB 不是随便定的,它对应的是 SRAM 可用容量减去栈和少量全局变量后的实际上限。SPL 的核心任务有两个:一是完成 DDR 初始化与训练,让大容量内存变得可用;二是把剩余的 bootloader 和 kernel 镜像从 SD 卡搬到 DDR 中。

为什么不能一次性把 bootloader 全读进 SRAM?因为完整的 U-Boot 加内核动辄几 MB 到几十 MB,SRAM 根本装不下。所以 SPL 是一个“两段式搬运工”:自己先挤进 SRAM 跑起来,把 DDR 点亮,再把大块头搬过去。这里翻车的典型场景是 DDR 训练参数不对——SPL 能跑,但搬运到 DDR 的数据校验失败,表现为 U-Boot 阶段串口输出乱码或直接挂死。DDR 训练参数通常由内存厂商提供的配置文件生成,换一批内存颗粒就得重新校准,这是硬件迭代时必查的一项。

2.3 U-Boot 与 Kernel:DDR 里的接力与交棒

U-Boot 运行在 DDR 中,此时内存空间充裕,它可以做完整的设备驱动初始化、支持多种启动方式(SD、eMMC、UART、USB、网络等)、提供命令行交互。它的核心职责是加载内核镜像到 DDR 指定地址,准备好设备树(device tree)和启动参数(bootargs),然后跳转到内核入口。内核启动后会重新初始化大部分硬件,只保留 U-Boot 传递过来的内存布局、串口控制台等信息。

这条接力链上有个常见误解:以为 U-Boot 初始化过的设备内核可以直接用。实际上内核有自己的驱动模型,U-Boot 阶段配置的时钟、引脚复用状态,内核会按设备树的描述重新配置一遍。所以设备树里外设节点写错,U-Boot 阶段一切正常,内核起来后外设就是不工作——这类问题排查时要把 U-Boot 日志和内核 dmesg 分开看,不能混为一谈。

2.4 四种启动模式的分流逻辑

文档明确列出了 USB/UART 下载模式、SD/eMMC boot 模式以及 ptset 测试模式。这几种模式在 ROM Code 阶段就分流了:正常量产板走 SD 或 eMMC,从存储介质读 SPL;产线首次烧录或救砖场景走 UART/USB 下载,由上位机工具把 bootloader 推下去;ptset 是测试模式,进入后不执行常规启动流程,用于芯片出厂测试。分流依据是 strapping 引脚采样值,所以做板子时这几个引脚的上拉下拉电阻不能省,否则模式判断错乱,板子会“莫名其妙”不进正常启动。

启动模式触发条件典型用途首级加载目标
SD bootstrapping 选中 SD量产、开发调试AON SRAM 中的 SPL
eMMC bootstrapping 选中 eMMC量产设备AON SRAM 中的 SPL
UART 下载strapping 选中 UART首次烧录、救砖上位机推送的 bootloader
USB 下载strapping 选中 USB批量烧录上位机推送的 bootloader
ptset测试模式使能出厂测试不进入常规启动

3. 按链路复现:从串口日志定位卡在哪一级

拿到一份启动流程文档,最有价值的用法不是通读,而是把它变成一张“日志对照表”。每一级启动阶段都会在串口留下特征输出,把这些特征和文档里的阶段划分对齐,就能在几分钟内判断板子卡在哪。下面按实际操作顺序走一遍,从准备调试环境到逐级验证,每一步都给出可执行的命令和判断依据。

3.1 搭好串口观察点:先能看到,再谈分析

启动调试的第一步永远是串口。ROM Code 阶段就会初始化 UART,所以只要硬件没问题,上电瞬间就应该有输出。接线时注意三点:TX/RX 交叉、GND 共地、波特率匹配。多数 SoC 的 ROM Code 默认波特率是 115200,但部分芯片可配置,文档里没写具体值时,先按 115200 试,无输出再换 921600 或 1500000。

# Linux 下用 minicom 连接串口,参数按实际设备节点调整 minicom -D /dev/ttyUSB0 -b 115200 # 或者用 picocom,退出快捷键是 Ctrl+A 再按 Ctrl+X picocom -b 115200 /dev/ttyUSB0

连接后给板子上电,观察是否有任何字符输出。完全无输出,优先查 UART 引脚复用和电平匹配;有输出但全是乱码,查波特率和时钟源。这一步看似基础,但血泪经验是:很多“芯片坏了”的误判,最后都落在串口线接反或波特率不对上。确认能看到 ROM Code 的输出,才有往下分析的基础。

3.2 识别 SPL 阶段:DDR 训练成功的信号

ROM Code 输出结束后,如果 SPL 被成功加载,串口会打印 SPL 的版本信息或直接进入 DDR 初始化日志。不同厂商的 SPL 输出差异很大,有的只打一行版本号,有的会打印 DDR 训练过程和容量检测结果。判断 SPL 是否跑起来,看两个信号:一是 ROM Code 输出之后是否有新的、格式不同的日志出现;二是日志里是否出现内存容量或 DDR 频率相关信息。

如果 ROM Code 输出完整,但之后彻底静默,说明 SPL 没被加载或加载后立即崩溃。排查顺序:先确认 SD 卡上 SPL 的存放偏移是否正确(ROM Code 按固定偏移读卡,偏移错了读到的就是空白数据),再确认 SPL 镜像大小是否超过 SRAM 容量。文档里 70KB 这个数字就是容量红线,SPL 编译出来超过它,链接阶段就该报错,但有些构建系统不检查,烧进去才暴露。

# 查看 SPL 镜像实际大小,确认没超过 SRAM 可用容量 ls -l spl.bin # 输出示例:-rw-r--r-- 1 user user 71680 ... spl.bin # 71680 字节 = 70KB,正好卡在边界,实际要留出栈空间余量

镜像大小接近上限时,编译优化选项就变得关键。-Os优化体积、去掉调试符号、裁剪不必要的驱动,都是常规手段。我一般会在构建脚本里加一条大小检查,超过阈值直接让编译失败,避免烧录后才发现。

3.3 验证 U-Boot 与内核交接:看跳转地址和 bootargs

SPL 成功把 U-Boot 搬进 DDR 后,串口会进入 U-Boot 命令行或自动启动倒计时。此时可以用 U-Boot 命令检查内存、查看环境变量、手动加载内核。关键验证点是内核加载地址和 bootargs 是否正确——地址错了内核解压失败,bootargs 里 console 参数错了内核起来但看不到输出。

# U-Boot 命令行下检查环境变量中的启动参数 printenv bootargs # 典型输出:console=ttyS0,115200 root=/dev/mmcblk0p2 rw # 手动从 SD 卡加载内核到指定地址并启动,用于验证地址是否正确 mmc dev 0 fatload mmc 0:1 0x80080000 zImage bootz 0x80080000

0x80080000是内核加载地址的示例,实际值取决于芯片的内存映射,文档里没给具体地址时,以板级配置文件为准。bootz之后如果内核解压日志出现又中断,多半是设备树地址没传对或内存布局冲突。这一步的排查思路是把 U-Boot 的加载动作和内核的启动日志分开看,哪一段断了就查哪一段的地址配置。

3.4 用启动模式切换做交叉验证

当某一级反复卡住、单一路径排查不出问题时,切换启动模式做交叉验证是有效手段。比如 SD 卡启动卡在 SPL,改用 UART 下载模式把同一份 SPL 推下去,如果 UART 模式能过 SPL,说明问题在 SD 卡控制器配置或卡上数据偏移;如果 UART 模式也卡在同一位置,问题就在 SPL 镜像本身或 DDR 训练参数。这种对照能快速把故障范围从“整条链路”缩小到“某个介质相关模块”。

切换模式靠 strapping 引脚,操作前务必对照原理图确认引脚定义,改完电平后重新上电(不是复位,要断电再上电,因为 strapping 只在复位采样)。交叉验证做完记得把引脚恢复原状,否则下次正常启动又进错模式,这种自己给自己挖坑的事故并不少见。

4. 避坑与排查:启动链路上的五类高频翻车

启动流程的坑有个共同特点:现象高度相似,根因分布在不同阶段。下面五条是从实际调试记录里整理出来的高频问题,每条按现象、原因、解决三段走,对照串口日志能快速定位。

4.1 上电完全无串口输出

现象:给板子上电,串口终端一片空白,换线换电脑都一样。

原因:三种可能——UART 引脚复用没配对(ROM Code 阶段引脚还处于默认功能)、波特率不匹配、或者 strapping 引脚把芯片带进了 ptset 测试模式,该模式不走常规启动也不初始化调试串口。

解决:先量 strapping 引脚电平,确认不在测试模式;再查原理图确认 UART TX/RX 对应的引脚在复位后的默认功能;最后用示波器看 TX 线上有没有波形,有波形但终端无字符就是波特率问题。这一步顺序不能乱,先排除模式错误再查硬件。

4.2 SPL 加载后静默,DDR 训练失败

现象:ROM Code 日志正常打印完,之后没有任何输出,板子像死了一样。

原因:SPL 被加载进 SRAM 并开始执行,但 DDR 初始化或训练失败,SPL 在访问 DDR 时挂死。常见诱因是内存颗粒型号与训练参数不匹配,或者 DDR 供电时序不满足。

解决:换用厂商提供的 DDR 训练参数重新编译 SPL;用示波器检查 DDR 供电和参考电压在上电时序中的建立时间;部分芯片支持在 SPL 里打开 DDR 训练详细日志,打开后能看到训练在哪一步失败。换内存颗粒必须重新跑训练,这是硬件迭代的固定动作,没有后悔药。

4.3 U-Boot 能进命令行但内核起不来

现象:U-Boot 倒计时结束或手动bootz后,内核解压日志打印到一半停住,或直接复位重启。

原因:内核加载地址与设备树地址重叠、bootargs 中 root 设备路径错误、或者内核镜像本身损坏。地址重叠会导致解压过程覆盖自身代码,表现为随机崩溃。

解决:用printenv核对kernel_addr_r、fdt_addr_r等变量,确保各镜像地址区间不重叠;用md命令读回加载地址处的数据,和主机上的镜像做校验和比对;bootargs 里的 root 分区号要和实际分区表一致。地址类问题没有玄学,就是逐段核对内存映射表。

4.4 SD 卡启动时好时坏

现象:同一张卡、同一块板,有时能启动有时卡在 ROM Code 之后。

原因:SD 卡控制器时钟配置处于临界状态,或者卡上 SPL 数据所在扇区有坏块。劣质卡在高速模式下的时序裕量不足,温度或电压波动就会导致读取出错。

解决:降低 SD 控制器时钟频率重新测试,如果低频稳定高频不稳,就是时序裕量问题;换一张品牌卡交叉验证,排除卡本身质量因素;量产时在 SPL 里加读取校验,读回数据做 CRC 比对,失败重试。启动介质的一致性在量产阶段比实验室阶段重要得多。

4.5 改了 strapping 后忘记恢复

现象:调试时切到 UART 下载模式,调完后板子再也进不了正常启动。

原因:strapping 引脚的电平改动没恢复,芯片每次上电都采样到下载模式,等待上位机推送程序,自然不进 SD 卡启动流程。

解决:对照原理图逐一核对 strapping 引脚当前电平与设计值;养成习惯,任何涉及 strapping 的改动都在板子上贴标签或记在调试日志里。这个坑不涉及技术难度,纯粹是流程管理,但踩一次能浪费半天。

5. 进阶验证:把启动链路变成可回归的检查清单

启动流程调通一次不算完,换板、换内存、换存储介质之后,同样的链路要能快速回归验证。我的做法是把四阶段拆成一张检查清单,每次硬件变更后按清单走一遍,而不是等出了问题再从头查。清单的核心是把“每一级是否成功”转化成可观测的信号:ROM Code 看串口首行输出,SPL 看 DDR 容量日志,U-Boot 看命令行提示符,内核看dmesg里的设备初始化完成标志。

具体操作上,可以在 U-Boot 里加一段自检脚本,启动时自动校验各镜像的 CRC 并打印结果,把隐性的数据损坏提前暴露。下面这段脚本放在 U-Boot 环境变量里,上电自动执行:

# U-Boot 环境变量:启动前校验内核镜像完整性 setenv verify_kernel 'if crc32 ${loadaddr} ${filesize}; then echo KERNEL_CRC_OK; else echo KERNEL_CRC_FAIL; fi' setenv bootcmd 'run verify_kernel; bootz ${loadaddr}' saveenv

crc32命令对加载地址处的镜像算校验和,filesize是上一条加载命令自动设置的长度变量。校验通过打印 OK 再启动,失败则停在命令行便于排查。这个脚本的价值在于把“镜像是否完整”从启动失败后的猜测变成启动前的确定判断,省掉大量二分排查时间。

另一个值得固化的习惯是记录每次启动的完整串口日志,按日期和硬件版本归档。启动问题的很多规律只有在多份日志对比时才显现——比如某批次板子总是在 DDR 训练的同一阶段慢几十毫秒,单看一份日志发现不了,横向对比就是线索。从那以后我每次改完启动相关配置,都会强制走一遍“断电上电、抓完整日志、对照四阶段检查点”的流程,不跳步。希望这份链路笔记能帮你在下次面对一块沉默的板子时,少走几段弯路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/29 3:13:42

HackRF One 从入门到开发:Windows/Linux 环境搭建与收发链路实战

简介:这份PDF文档面向软件无线电初学者与嵌入式开发者,系统讲解HackRF One软件无线电平台的入门与开发实践,帮助读者解决从硬件认知到环境搭建、再到实际收发实验的完整链路问题。资源包共1个PDF文件,约2.49MB,内容涵盖…

作者头像 李华
网站建设 2026/10/29 3:13:41

Anaconda安装避坑指南:版本选择、路径配置与验证全流程

简介:这份文档面向刚接触Python数据科学的初学者与需要配置开发环境的学生,系统梳理了Anaconda从官网下载到环境配置的完整流程,帮助读者解决安装过程中版本选择、环境变量设置、安装路径规划等常见困惑。资源为1个docx文档,压缩包…

作者头像 李华
网站建设 2026/10/29 3:13:25

CINRAD雷达基数据格式解析:SA/SB与CA/CB字节结构详解

简介:面向气象数据处理、雷达产品开发与教学科研人员的CINRAD雷达基数据格式参考文档,聚焦SA/SB与CA/CB两类雷达的二进制存储规范,帮助读者解决基数据解析、字段定位与解码换算中的实际问题。资源包共1个doc文件,约92KB&#xff0…

作者头像 李华
网站建设 2026/10/29 3:13:08

动易SiteWeaver6.8后台编辑器IE9/10/11兼容修复指南

简介:这份文档面向仍在使用动易 SiteWeaver6.8 建站系统的站长与后台维护人员,针对后台编辑器在 IE9、IE10、IE11 下无法正常加载、无法编辑文章的问题给出修复方案。资源包共 1 个 doc 文件,约 21KB,以图文步骤形式整理了两种处理…

作者头像 李华
网站建设 2026/10/29 3:12:34

医疗票据OCR识别技术解析与应用实践

1. 医疗票据识别的行业痛点与现状医疗票据处理一直是医疗机构和财务人员最头疼的日常事务之一。我曾在三甲医院财务科工作过五年,每天经手的各类票据少则几百张,多则上千张。门诊收费票据、住院结算单、医保报销凭证、检验检查报告...这些纸质单据不仅数…

作者头像 李华
网站建设 2026/10/29 3:10:06

论文AI检测降重实战:3个案例与技巧

1. 论文AI检测降重实战指南最近帮几位研究生处理论文时,发现他们普遍遇到了AI检测率过高的问题。有位学生的初稿检测结果显示82%的内容被标记为AI生成,这直接影响了论文的学术可信度。经过我们三周的反复调整,最终将AI率降到了12%的可接受范围…

作者头像 李华