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: 分区要小、要少,尽量用静态分区。因为擦除慢,不适合动态调整。
- NAND Flash: 分区要预留备用块,文件系统要选UBIFS或yaffs2。Bootloader必须带ECC校验。
- eMMC: 分区可以灵活,用GPT分区表。Boot分区要配置成只读,防止误写。
- SD卡: 分区要简单,用FAT32。如果做启动卡,Bootloader必须放在固定扇区。
嗯,这一章的内容就到这里。记住,选存储介质和做分区策略,没有绝对的对错,只有合不合适。多想想你的产品需要什么,再决定怎么分。