4. 启动设备与存储介质:NOR Flash、NAND Flash、eMMC、SD卡、SPI Flash的特性对比与启动方式
做嵌入式这些年,我接触过形形色色的存储介质。每次选型,说白了就是在速度、容量、成本和启动方式之间做权衡。你想想看,一个系统能不能快速、稳定地启动,很大程度上取决于你选了什么存储设备。
这一章,我把最常见的几种存储介质拉出来,逐个拆解。咱们不光看数据手册上的参数,更要聊聊它们在实际启动链里是怎么工作的。
4.1 NOR Flash:老牌劲旅,XIP的底气
NOR Flash 是我个人最早接触的启动介质。它的最大特点,就是支持 XIP(Execute In Place,原地执行)。什么意思?CPU 可以直接在 NOR Flash 上读指令、跑代码,不需要先把代码拷贝到 RAM 里。
核心优势:随机读取速度快,代码可以直接在上面跑。
致命短板:写入和擦除速度慢,容量做不大,价格贵。
我记得在做一个工业控制器时,用的就是 NOR Flash。系统上电后,CPU 直接跳转到 NOR 的起始地址,开始执行 Bootloader。整个过程干净利落,没有等待 RAM 初始化的烦恼。
不过要注意,NOR Flash 的擦除粒度通常是 64KB 或 128KB 的块。你要是想改一个字节,得先把整个块读出来、擦掉、再写回去。嗯,这里有个坑——频繁擦写会加速老化。
我曾经踩过的坑:在 NOR Flash 上做日志存储,频繁写数据。结果几个月后,那个块就坏了。后来我改用 NAND 或者 eMMC 做日志,NOR 只放固件。
4.2 NAND Flash:大容量担当,但启动有点麻烦
NAND Flash 的容量大、成本低,几乎是所有大容量存储的标配。但它的启动方式,比 NOR 复杂得多。
为什么?因为 NAND 不支持 XIP。CPU 不能直接在 NAND 上执行代码。它必须先把 NAND 里的代码读到 RAM 里,然后跳转到 RAM 执行。
这就引出了一个经典问题:“先有鸡还是先有蛋?”——RAM 还没初始化,怎么把代码从 NAND 搬到 RAM?
解决方案通常是这样的:
- CPU 内部有一小块 ROM(叫 BootROM),上电后自动执行。
- BootROM 初始化必要的硬件(比如 NAND 控制器),从 NAND 的固定位置(通常是 Block 0)读取一小段代码(叫 SPL 或 Preloader)。
- 这段小代码再初始化 DDR RAM,然后把完整的 Bootloader 从 NAND 读到 RAM 里。
- 最后跳转到 RAM 里的 Bootloader,继续启动。
你看,NAND 启动至少需要两级跳转。这也是为什么很多 SoC 的启动流程里,会有 BootROM → SPL → U-Boot → Kernel 这样的链条。
个人建议:NAND 有坏块问题。出厂时就可能有坏块,使用过程中还会产生新坏块。所以,存放 Bootloader 的区域,一定要做坏块管理和 ECC(纠错码)。我习惯在 SPL 阶段就启用硬件 ECC,否则启动到一半卡死,你连调试的机会都没有。
4.3 eMMC:集成度最高的选择
eMMC 本质上就是把 NAND Flash 和一个控制器封装在一起。这个控制器负责坏块管理、ECC、磨损均衡。对开发者来说,你看到的是一个标准的 MMC 接口,不用操心底层 NAND 的破事。
eMMC 的启动方式有两种:
- 传统 MMC 启动模式:BootROM 通过 MMC 协议,从 eMMC 的 Boot Area Partition 读取代码。
- 用户分区启动:从 eMMC 的用户数据分区启动,通常用于加载 U-Boot 或内核。
我在做手机和平板项目时,几乎清一色用 eMMC。它的好处很明显:
- 接口简单,协议成熟。
- 启动速度快,因为控制器内部有缓存。
- 容量大,从 4GB 到 256GB 随便选。
注意:eMMC 的 Boot Area Partition 是只读的(硬件保护)。你需要在量产时,通过特定的命令把 Bootloader 烧进去。一旦烧好,普通擦写命令动不了它。这能防止 Bootloader 被意外破坏。
4.4 SD卡:可插拔的启动介质
SD 卡和 eMMC 的底层协议几乎一样,都是 MMC 协议的子集。区别在于,SD 卡是可插拔的,eMMC 是焊在板子上的。
SD 卡启动常见于开发板、树莓派、单板电脑。它的启动流程和 eMMC 类似:
- BootROM 初始化 SD 主机控制器。
- 发送 CMD0 让 SD 卡进入 SPI 模式或 SD 模式。
- 读取 MBR(主引导记录),找到第一个分区。
- 从分区读取 Bootloader。
我个人觉得,SD 卡最大的价值在于调试阶段。你可以随时换一张卡,更新固件。但量产产品里,我很少用 SD 卡做启动介质——接触不良、容易脱落、速度不稳定,都是问题。
避坑指南:SD 卡启动时,BootROM 对卡的速度等级很敏感。我曾经用一张 Class 4 的卡,启动死活失败。换成 Class 10 的卡,一次过。所以,开发阶段尽量用高速卡,别在卡上省成本。
4.5 SPI Flash:小身材,大用途
SPI Flash 通常是 NOR 类型的,通过 SPI 接口连接。它容量小(几 MB 到几十 MB),但引脚少、体积小、成本低。
SPI Flash 的启动方式:
- 很多 SoC 支持直接从 SPI Flash 启动(XIP 模式)。
- 如果不支持 XIP,BootROM 会把 SPI Flash 里的代码读到内部 SRAM 里执行。
我在物联网设备、路由器、光模块里,经常看到 SPI Flash 的身影。它最适合放 Bootloader 和配置文件。
一个典型场景:路由器上电,CPU 从 SPI Flash 读取 U-Boot,U-Boot 再初始化网络,从 TFTP 服务器下载固件。这样,SPI Flash 只需要 16MB 就够了,成本极低。
4.6 特性对比一览表
下面这张表,是我做选型时经常参考的。你可以存下来,下次选型直接翻。
| 特性 | NOR Flash | NAND Flash | eMMC | SD 卡 | SPI Flash |
|---|---|---|---|---|---|
| 接口 | 并行/SPI | 并行 | MMC | SD/SPI | SPI |
| 支持 XIP | ✅ 是 | ❌ 否 | ❌ 否 | ❌ 否 | ✅ 部分支持 |
| 读取速度 | 快 | 较快 | 快 | 中等 | 中等 |
| 写入速度 | 慢 | 快 | 快 | 中等 | 慢 |
| 容量 | 小(≤512MB) | 大(≥1GB) | 大(≥4GB) | 大(≥1GB) | 小(≤64MB) |
| 坏块管理 | 不需要 | 必须 | 内置 | 内置 | 不需要 |
| 启动复杂度 | 低(直接跳转) | 高(需 SPL) | 中(需分区) | 中(需分区) | 低(直接跳转) |
| 典型用途 | Bootloader、固件 | 文件系统、大容量存储 | 系统盘、App 存储 | 开发调试、便携存储 | 配置、小固件 |
4.7 启动方式与启动链的关系
不同的存储介质,决定了启动链的层级结构。我画了一张图,帮你理清这个关系。
从这张图可以看得很清楚:
- NOR 和 SPI Flash 走的是“直通车”,BootROM 直接读,启动最快。
- NAND Flash 需要“换乘”,先读 SPL,再读 U-Boot,最后读内核。
- eMMC 和 SD 卡 虽然也需要分区读取,但协议成熟,控制器帮忙做了很多事。
我的经验:如果项目对启动时间有硬性要求(比如汽车电子、工业控制),优先选 NOR 或 SPI Flash。如果对容量有要求(比如 Linux 系统),eMMC 是最省心的选择。NAND 虽然便宜,但坏块管理和 ECC 会占用不少开发时间。
4.8 小结
这一章,我们把五种常见的启动存储介质过了一遍。每种介质都有自己的脾气:NOR 快但贵,NAND 大但麻烦,eMMC 省心但成本高,SD 卡灵活但不稳定,SPI Flash 小巧但容量有限。
选型没有绝对的好坏,关键看你的系统需要什么。我个人习惯是:
- 小系统(RTOS、裸机):用 NOR 或 SPI Flash。
- 大系统(Linux、Android):用 eMMC。
- 开发调试:用 SD 卡。
- 成本敏感、容量要求高:用 NAND,但要做好坏块管理。