3. 嵌入式存储介质:NOR Flash、NAND Flash、eMMC、SD卡的特点与区别,以及它们对分区策略的影响

做BSP开发,说白了就是跟各种存储介质打交道。你想想看,Bootloader要存、内核要存、文件系统也要存,选什么介质、怎么分区,直接决定了系统的启动速度和可靠性。这一章,我就把几种常见的存储介质掰开揉碎了讲清楚。

3.1 四种存储介质的核心差异

先看一张总览表,后面我们再逐个细聊。

特性 NOR Flash NAND Flash eMMC SD卡
接口 SRAM-like,地址/数据总线 I/O串行,命令/地址/数据复用 MMC协议,8位并行 SPI/SDIO协议
读取速度 快(随机读极快) 较快(顺序读快) 快(带Cache) 中等(受限于接口)
写入速度 慢(需先擦除) 快(页编程) 快(FTL优化) 中等
擦除方式 按扇区(64KB~256KB) 按块(128KB~2MB) 内部FTL管理 内部FTL管理
坏块管理 无坏块问题 出厂即有坏块,需管理 内部处理 内部处理
XIP(原地执行) 支持 不支持 不支持 不支持
典型容量 1MB~256MB 128MB~8GB 4GB~256GB 1GB~1TB
成本 高 低 中等 低

3.2 NOR Flash:Bootloader的黄金搭档

NOR Flash最大的特点就是支持XIP。什么意思?就是CPU可以直接从NOR Flash里面取指令执行,不需要先把代码拷贝到RAM里。这对Bootloader来说太重要了。

我记得在做一个工业控制器项目时,用的就是NOR Flash存Bootloader。上电后CPU直接跳转到NOR的起始地址,代码就跑起来了。整个过程不到100毫秒,非常干脆。

核心优势: NOR Flash的随机读取速度极快,几乎和RAM一样。但写入和擦除很慢,而且容量做不大。所以它最适合存启动代码,而不是大块数据。

分区策略上,NOR Flash通常这样划分:

  • 起始地址(0x0): 存放一级Bootloader(SPL),通常只有几KB。
  • 中间区域: 存放二级Bootloader(U-Boot),几百KB到几MB。
  • 末尾区域: 存放环境变量或备份数据。

注意: NOR Flash的擦除粒度很大,通常是64KB或128KB。如果你只改一个字节,也得把整个扇区擦掉再重写。所以环境变量这种频繁修改的数据,最好单独放在一个小扇区里,或者用冗余备份策略。

3.3 NAND Flash:大容量存储的性价比之选

NAND Flash就不一样了。它不支持XIP,代码必须先读到RAM里才能执行。但它的容量大、成本低,非常适合存内核、文件系统这些大块头。

不过,NAND Flash有个让人头疼的问题——坏块。出厂时就可能有坏块,使用过程中还会产生新的坏块。我曾经在一个项目中吃过亏,没做坏块管理,结果产品用了半年后启动不了了。从那以后,我对NAND的坏块处理就格外上心。

NAND Flash的分区策略要考虑以下几点:

  • Bootloader分区: 通常放在最前面,但必须用MLC/伪SLC模式或ECC校验保护起来。因为Bootloader代码对可靠性要求极高。
  • 内核分区: 建议用UBIFS或yaffs2这类专门为NAND设计的文件系统。
  • 数据分区: 需要预留足够的备用块,用于替换坏块。

我的习惯: 在NAND上做分区时,我会在Bootloader里先扫描一遍所有块,建一个坏块表。然后分区的时候,跳过这些坏块,只用好块。这样能避免很多启动问题。

3.4 eMMC:集成度最高的存储方案

eMMC本质上就是把NAND Flash和一个FTL(Flash Translation Layer)控制器封装在一起。你不需要关心坏块管理、磨损均衡这些底层细节,直接像操作硬盘一样操作它就行。

eMMC的分区策略和硬盘很像:

  • Boot分区: eMMC内部有专门的Boot分区,可以配置成只读,用来存放Bootloader。
  • RPMB分区: 用于存放安全相关的数据,比如密钥。这个分区需要认证才能访问。
  • 用户分区: 剩下的空间,可以分成多个GPT分区,放内核、文件系统、用户数据。

我建议在eMMC上使用GPT分区表,而不是MBR。因为GPT支持更多分区,而且有备份分区表,更可靠。

避坑指南: 我曾经遇到过eMMC的Boot分区配置错误,导致板子无法从eMMC启动。后来发现是EXT_CSD寄存器里的PARTITION_CONFIG字段没设对。所以,操作eMMC时一定要仔细看芯片手册的分区配置部分。

3.5 SD卡:灵活但不可靠的存储介质

SD卡和eMMC类似,内部也有FTL。但SD卡是可插拔的,这就带来了一个问题——热插拔。如果系统正在写数据时突然拔卡,数据可能损坏,甚至文件系统崩溃。

SD卡的分区策略:

  • Bootloader: 不建议放在SD卡上,除非你用的是SD卡启动模式。这种情况下,Bootloader必须放在SD卡的特定扇区(比如扇区0)。
  • 文件系统: 建议用FAT32或exFAT,因为兼容性好。但要注意,FAT32不支持单个文件超过4GB。
  • 数据分区: 如果对可靠性要求高,可以用ext4,但需要内核支持。

注意: SD卡的寿命和可靠性远不如eMMC。如果产品需要长时间稳定运行,我建议优先考虑eMMC。SD卡更适合做数据导出或固件升级的临时存储。

3.6 存储介质对分区策略的影响

说了这么多,其实核心就一句话:不同的存储介质,决定了你的分区策略必须不同。

下面这张SVG图,展示了不同介质下的典型分区布局:

不同存储介质的典型分区布局 NOR Flash 分区布局 SPL (4KB) U-Boot (512KB) 环境变量 备份/保留 NAND Flash 分区布局 Bootloader Kernel (4MB) RootFS (UBIFS) 数据/备用块 eMMC 分区布局 Boot分区 RPMB 用户分区(GPT) 内核 + RootFS + 数据 SD卡 分区布局 MBR FAT32分区 (Boot) ext4分区 (数据/升级包) 说明:不同介质的物理特性决定了分区的大小、位置和文件系统选择。NOR适合XIP,NAND需要坏块管理,eMMC和SD卡依赖内部FTL。

总结一下我的经验:

  • NOR Flash: 分区要小、要少,尽量用静态分区。因为擦除慢,不适合动态调整。
  • NAND Flash: 分区要预留备用块,文件系统要选UBIFS或yaffs2。Bootloader必须带ECC校验。
  • eMMC: 分区可以灵活,用GPT分区表。Boot分区要配置成只读,防止误写。
  • SD卡: 分区要简单,用FAT32。如果做启动卡,Bootloader必须放在固定扇区。

嗯,这一章的内容就到这里。记住,选存储介质和做分区策略,没有绝对的对错,只有合不合适。多想想你的产品需要什么,再决定怎么分。