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?

解决方案通常是这样的:

  1. CPU 内部有一小块 ROM(叫 BootROM),上电后自动执行。
  2. BootROM 初始化必要的硬件(比如 NAND 控制器),从 NAND 的固定位置(通常是 Block 0)读取一小段代码(叫 SPL 或 Preloader)。
  3. 这段小代码再初始化 DDR RAM,然后把完整的 Bootloader 从 NAND 读到 RAM 里。
  4. 最后跳转到 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 类似:

  1. BootROM 初始化 SD 主机控制器。
  2. 发送 CMD0 让 SD 卡进入 SPI 模式或 SD 模式。
  3. 读取 MBR(主引导记录),找到第一个分区。
  4. 从分区读取 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 启动方式与启动链的关系

不同的存储介质,决定了启动链的层级结构。我画了一张图,帮你理清这个关系。

存储介质与启动链层级关系 存储介质与启动链层级关系 BootROM(芯片内部) SPL / Preloader U-Boot / Bootloader Linux Kernel 存储介质存放位置 NOR / SPI Flash(XIP) NAND Flash(需 SPL) eMMC / SD 卡 说明: • NOR / SPI Flash:BootROM 可直接读取执行,启动链最短(1级跳转)。 • NAND Flash:BootROM 先读 SPL,SPL 初始化 RAM 后再读 U-Boot(2级跳转)。 • eMMC / SD 卡:BootROM 通过 MMC 协议读取 Boot Partition 或用户分区(1-2级跳转)。 • 启动链层级越多,启动时间越长,但灵活性越高。 • 选型时,根据系统对启动速度和存储容量的要求,选择合适的介质。

从这张图可以看得很清楚:

  • 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,但要做好坏块管理。