SoC 启动时 BootROM/SRAM/Flash/DDR 怎么映射加载?
更新时间:2026-09-21。问题驱动短答页。SoC 概念见 什么是 SoC,时钟/PLL 见 时钟控制器 CGU,DDR 训练见 DDR 双边沿训练,DMA 见 中断与 DMA 入门。
一句话回答
复位后 CPU 从一个由架构固定的复位地址开始取指,SoC 把这个地址映射到片上 BootROM(掩膜 ROM 或一小块专用 SRAM),里面固化了“一级启动代码”:做最少的时钟/PLL、引脚复用和一个调试串口初始化,读取启动选择引脚/熔丝决定从哪种介质启动(SPI/NOR/NAND Flash、SD/eMMC、UART、USB),然后把下一阶段镜像(SPL/bootloader)搬到当前就能用的存储里执行。注意 DDR 此时还不能用——DDR 必须先由代码完成控制器和 PHY 初始化及训练(见 DDR 训练),所以早期代码通常先在内部 SRAM 里跑(SRAM 上电立即可用但小),把 DDR 训练好后,再把更大的 bootloader/操作系统镜像从外部 Flash 拷到 DDR,最后校验(安全启动做签名验证)并跳转执行。这个过程本质是“逐级接力”:BootROM → SRAM 里的 SPL → DDR 里的 bootloader → OS。
存储在启动中的角色
| 存储 | 启动时状态 | 角色 |
|---|---|---|
| BootROM | 立即可执行 | 固化一级代码、选启动介质、做最小初始化 |
| 内部 SRAM | 立即可用、容量小 | 跑 SPL/DDR 初始化代码(DDR 未就绪前) |
| SPI/Flash/eMMC | 需驱动初始化 | 存放持久镜像;可 XIP 或读入 |
| DDR | 必须先训练 | 容量大,加载 bootloader/OS 后才能用 |
典型时序
- 复位取指:CPU 跳到固定向量(如 0x0/0xFFFF0000),地址译码指向 BootROM,见 复位设计。
- 最小初始化:时钟源(先用低频直连,再配 PLL,见 PLL/DLL)、必要 IO、调试 UART。
- 选介质:读 boot pins/efuse,初始化对应控制器(SPI/SD/UART)。
- 加载 SPL 到 SRAM:第一级引导程序小到能放进 SRAM;也可直接在 NOR 上 XIP(就地执行,省拷贝但慢)。
- 初始化 DDR:SPL 跑 DDR PHY 训练和控制器配置,见 DDR 训练。
- 加载大镜像到 DDR:用 DMA/CPU 搬运 bootloader 甚至 OS,见 DMA。
- 校验与跳转:安全启动验签/哈希,设置向量表和栈,跳到新镜像链接地址。
两个易混概念
- 链接地址(runtime/link address) vs 加载地址(load address):代码最终在哪个地址运行(链接),最初被放在哪(加载);早期搬运用位置无关代码(PIC)或先重定位,否则跳转到未映射地址会取指失败。
- XIP(eXecute In Place):NOR Flash 等可直接按内存读的介质上就地执行,省去拷贝,但速度和时序受接口限制;NAND/SD 必须先读到 RAM。
常见坑
- BootROM 代码假设 DDR 已可用,实际复位后 DDR 未训练,取指/写数据失败。
- 链接地址和实际加载/重定位地址不一致,跳转后跑飞。
- 时钟/PLL 未稳定就切时钟源,见 PLL locked。
- 启动介质驱动或引脚复用初始化顺序错误,导致读不到镜像。
- 忽略安全启动校验,运行了被篡改的下一级镜像。
总结
SoC 启动是固定复位向量进入片上 BootROM 的逐级接力:BootROM 做最小初始化、按启动引脚选介质,把小的一级引导装入立即可用但容量小的内部 SRAM;DDR 必须由这段代码完成 PHY 训练后才可用,随后把大的 bootloader/OS 从外部 Flash 搬到 DDR,校验后跳转执行。关键约束是“DDR 训练前只能用 SRAM/BootROM”、链接地址要与重定位地址一致、NOR 可 XIP 而 NAND/SD 必须先读入,安全启动还要在每一级跳转前验证镜像。