它们是启动流程中先后衔接的两个阶段,可以概括为:BootROM 加载并启动 Bootloader。
一、BootROM(只读存储器中的启动代码)
本质
芯片出厂时固化的掩膜 ROM,用户无法修改。位于芯片内部,上电后 CPU 第一个执行的代码。
主要职责
基本硬件初始化:设置堆栈指针、关看门狗、初始化时钟(部分芯片)、配置启动引脚采样
选择启动介质:根据 BOOT 引脚电平,决定从 NAND、SD、UART、USB 等哪个设备读取
加载第一级启动代码:将启动介质前 4KB~64KB 内容复制到内部 SRAM
验证并跳转执行:通常有简单签名校验,成功后跳转到 SRAM 执行
约束条件
容量极小:4KB~64KB(内部 SRAM 宝贵)
功能受限:只能支持最基础的驱动(如简单 NAND 读、UART 协议)
无法初始化 DDR:DDR 需要复杂时序配置,BootROM 通常不包含完整 DDR 初始化
典型例子
| SoC | BootROM 大小 | 支持启动介质 |
|---|---|---|
| STM32 | 约 16KB | UART、USB、SPI、I2C |
| i.MX6 | 约 32KB | NAND、SD、SPI NOR、UART、USB |
| RK3399 | 约 64KB | eMMC、SD、NAND、SPI NOR、USB |
二、Bootloader(引导加载程序)
本质
存储在外部非易失存储器(Flash、eMMC、SD 卡)中的可升级软件,用户可自由修改。
主要职责
完整硬件初始化:初始化 DDR 内存、时钟树、存储控制器、显示、网络等
加载操作系统:从文件系统或裸分区读取 Linux Kernel、DTB 或 RTOS 镜像
提供交互界面:命令行(如 U-Boot 的 CLI)、脚本支持、环境变量
支持多种启动方式:从网络(TFTP)、USB、MMC 等灵活选择
固件升级:通常在 Bootloader 中实现 flash 烧写命令
容量与复杂度
容量:通常 100KB~1MB(压缩后)
功能强大:包含文件系统驱动(FAT、EXT4)、网络协议栈(TCP/IP)、USB 主机栈
典型例子
| Bootloader | 常见平台 | 特点 |
|---|---|---|
| U-Boot | ARM、MIPS、RISC-V | 最主流,功能最全 |
| ATF + U-Boot | ARMv8(如 RK3399、树莓派4) | 安全启动分离 |
| Coreboot | x86/ARM | 主要用于 PC/服务器 |
| RedBoot | 嵌入式 | 较老,eCos 生态 |
| 厂商私有 | 如 Rockchip MiniLoader | 简化版,只负责加载 U-Boot |
三、两者关系:级联启动模型
为什么不能跳过 BootROM?
没有 BootROM:CPU 无法知道从哪个地址取第一条指令(存储器可能是空的或未初始化)
为什么需要 Bootloader:BootROM 太小,无法处理复杂存储介质(如文件系统、网络协议)
为什么 BootROM 不直接加载操作系统?
| 原因 | 说明 |
|---|---|
| 容量限制 | BootROM 只有几十 KB,无法包含驱动完整文件系统、USB、网络协议栈 |
| 内存限制 | 内部 SRAM 只有几十~几百 KB,无法容纳 Linux Kernel(几 MB) |
| 灵活性 | BootROM 固化的,无法修复 bug 或适配新硬件 |
| 安全边界 | BootROM 只做最小信任根,复杂逻辑交给可升级的 Bootloader |
四、实际芯片案例
案例1:STM32(无外置 DDR,裸机/RTOS)
上电 → BootROM → [可选:System Bootloader (UART/USB/SPI)] → 用户程序
没有独立的 Bootloader:BootROM 可直接跳转到用户 Flash
System Bootloader 是 BootROM 内的可选模式,不是独立程序
案例2:i.MX6(带 DDR,运行 Linux)
上电 → BootROM → 加载 SPL (4KB) → SPL 初始化 DDR → 加载 U-Boot → 加载 Kernel
三级启动:BootROM → SPL → U-Boot → Kernel
SPL 是 Bootloader 的一部分,但由 BootROM 加载
案例3:RK3399(ARMv8,ATF 架构)
上电 → BootROM → 加载 ddr.bin (初始化 DDR) → 加载 U-Boot SPL → 加载 ATF → 加载 U-Boot → 加载 Kernel
更复杂:安全监控(ATF)介入,启动链更长
五、关键区别总结表
| 特性 | BootROM | Bootloader |
|---|---|---|
| 存储位置 | 芯片内部掩膜 ROM | 外部 Flash、eMMC、SD 卡 |
| 可修改性 | ❌ 不可修改(出厂固化) | ✅ 可升级、可配置 |
| 大小 | 4KB~64KB | 100KB~1MB+ |
| 执行位置 | 芯片内部 SRAM 或 XIP Flash | DDR 内存(初始化后) |
| 初始化能力 | 极简硬件,通常无法初始化 DDR | 完整硬件初始化 |
| 功能 | 加载第一级启动代码 | 加载 OS、提供命令行、网络启动 |
| 典型代码 | 汇编 + 简单 C | U-Boot、Coreboot、RedBoot |
| 存在必要性 | 必须(CPU 第一条指令的来源) | 非必须(裸机可以直接被 BootROM 加载) |
| 开发难度 | 芯片厂商实现,用户无法修改 | 用户可移植、可定制 |
六、常见理解误区
❌ 误区1:“Bootloader 就是 U-Boot”
正确:U-Boot 是 Bootloader 的一种实现,还有 Coreboot、RedBoot、GRUB(x86)等
❌ 误区2:“BootROM 也算 Bootloader”
正确:BootROM 是“启动程序”,但不是通常说的 Bootloader。术语上 Bootloader 特指存储在外部、可升级的程序
❌ 误区3:“所有芯片都需要 Bootloader”
正确:单片机(无 OS)用户程序可直接被 BootROM 加载,不需要额外 Bootloader;有 OS 或需要复杂启动配置的才需要
❌ 误区4:“BootROM 可以初始化 DDR”
正确:部分 SoC(如 i.MX6)的 BootROM 不初始化 DDR,需由 SPL 初始化;少数 SoC(如某些 TI 芯片)BootROM 支持简单 DDR 配置