第3章:NAND Flash基础——SLC/MLC/TLC/QLC的区别,Page/Block/Plane/Die的概念,读写擦除特性

各位同学,今天我们来聊聊车载存储系统的基石——NAND Flash。说实话,我在车载行业摸爬滚打这么多年,见过太多因为不懂Flash特性而翻车的案例。有的项目选型时只看容量和价格,结果上车后各种掉速、坏块、数据丢失,最后不得不返工重做。所以这一章,我建议大家认真看,这些都是血泪换来的经验。

3.1 SLC/MLC/TLC/QLC:一字之差,天壤之别

先说说这四种Flash的区别。说白了,它们就是每个存储单元能存几个bit的问题。

  • SLC(Single-Level Cell):每个单元存1bit,只有0和1两种状态。简单粗暴,但速度快、寿命长。我记得早期车载ECU用的基本都是SLC,虽然贵,但可靠。
  • MLC(Multi-Level Cell):每个单元存2bit,有4种电压状态。容量翻倍,但寿命和速度都打了折扣。
  • TLC(Triple-Level Cell):每个单元存3bit,8种电压状态。现在消费级SSD的主流,性价比高,但写入寿命只有SLC的十分之一左右。
  • QLC(Quad-Level Cell):每个单元存4bit,16种电压状态。容量最大,但寿命和性能最差。说实话,我在车载项目里基本不敢用QLC,除非是做冷数据存储。

核心差异速查表:

类型 每单元bit数 擦写寿命(P/E) 读取速度 写入速度 典型应用
SLC 1 ~100,000次 最快 最快 工业控制、车载关键数据
MLC 2 ~10,000次 较快 较快 高端车载娱乐系统
TLC 3 ~3,000次 中等 中等 车载导航、行车记录
QLC 4 ~1,000次 较慢 较慢 冷数据归档(慎用)

你可能会问:「为什么寿命差这么多?」原因很简单——电压状态越多,区分相邻状态的难度就越大。每次擦写都会对氧化层造成微小的损伤,时间长了,电压窗口就会漂移,数据就读不出来了。我在项目中遇到过TLC Flash用了两年就开始出现大量ECC纠错失败的情况,后来不得不降级使用。

3.2 Page/Block/Plane/Die:Flash的物理层级

搞懂了存储单元,我们再来看看Flash的物理结构。这就像理解一栋楼——有房间、楼层、单元、整栋楼。

  • Page(页):读写的最小单位。通常是4KB、8KB或16KB。你想想看,每次读数据,最少也得读一页。写数据也一样,不能只写一个字节。
  • Block(块):擦除的最小单位。一个Block包含多个Page,通常是64页或128页。这里有个关键点——擦除操作只能以Block为单位进行,不能只擦除一个Page。
  • Plane(平面):多个Block组成一个Plane。每个Plane有自己的缓存寄存器,可以并行操作。我习惯在驱动层利用Plane并行来提升性能。
  • Die(晶粒):一个独立的Flash芯片。多个Die可以封装在一起,通过片选信号来区分。车载上常见的eMMC或UFS,内部就是多个Die的组合。

我的经验:在车载Linux中,文件系统选型时一定要考虑Block大小。比如你用的Flash擦除块是2MB,那文件系统的块大小最好对齐到2MB的整数倍,否则会出现写放大问题。我曾经在一个项目中没注意这个,结果写入性能直接腰斩。

3.3 读写擦除特性:Flash的脾气你得摸透

Flash的读写擦除,说白了就是三个操作:读、写、擦。但每个操作都有自己的脾气。

读操作

读是最快的操作,但也不是随便读。Flash读数据时,需要先发送读命令和地址,然后等待数据从存储阵列传输到缓存寄存器。这个等待时间叫tR(Read Latency),一般在几十微秒级别。嗯,这里要注意——读操作不会改变存储单元的状态,所以理论上可以无限次读。

写操作(编程)

写操作就复杂多了。Flash写数据时,是通过隧穿效应将电子注入浮栅。这个过程需要高压,而且速度慢。写一个Page通常需要几百微秒到几毫秒。更关键的是——写操作只能将1变成0(即从擦除状态变成编程状态)。如果你想将0变回1,必须先擦除。

避坑指南:我曾经在项目里遇到一个bug——应用程序频繁修改一个文件的小部分内容,结果导致整个Block被反复擦写。这就是典型的「写放大」问题。后来我改用日志结构的文件系统(如UBIFS),才解决了这个问题。记住:频繁的小数据修改,对Flash来说是灾难。

擦除操作

擦除是Flash最慢的操作,通常需要几毫秒到几十毫秒。擦除操作会将整个Block的所有bit恢复为1(即擦除状态)。这里有个重要特性——Flash的擦除次数是有限的,这就是我们前面说的P/E Cycle。

为什么会这样?因为每次擦除都会对氧化层造成不可逆的损伤。当擦除次数达到上限后,这个Block就变成坏块了。车载设备的工作环境恶劣,温度变化大,这会加速Flash的老化。我建议在车载项目中,至少预留20%的备用块用于坏块替换。

3.4 实战中的注意事项

好了,理论讲完了,我们来点实际的。在车载Linux系统中,你该怎么用好Flash?

  1. 选型建议:关键数据(如系统分区、日志)用SLC或MLC;非关键数据(如地图、媒体)可以用TLC。QLC慎用,除非你做好了充分的寿命评估。
  2. 分区对齐:确保文件系统的块大小与Flash的擦除块大小对齐。比如Flash擦除块是2MB,那分区起始地址最好是2MB的整数倍。
  3. 磨损均衡:必须启用Flash控制器的磨损均衡功能,或者使用支持磨损均衡的文件系统(如UBIFS、F2FS)。
  4. ECC纠错:TLC和QLC对ECC的要求更高。我建议至少使用4-bit ECC,对于QLC可能需要8-bit甚至更高。
  5. 坏块管理:出厂时就有坏块,使用过程中还会产生新坏块。必须做好坏块映射和替换机制。

一句话总结:Flash不是硬盘,它有自己独特的脾气。读快写慢,擦除更慢,寿命有限。在车载系统中,你必须尊重这些特性,否则系统会以各种奇怪的方式「报复」你。

下一章,我们会深入讲解Flash Translation Layer(FTL)的工作原理,以及它在车载Linux中的实现。到时候我会分享一个我在实际项目中优化FTL性能的案例,保证让你有收获。

公众号:蓝海资料掘金营,微信deep3321