Flash 存储器基础:从 NOR 到 NAND,从 SLC 到 QLC

好,咱们正式开始啃 Flash 这块硬骨头。做 NVM 开发,Flash 是绕不过去的基础设施。我个人习惯把 Flash 理解成「电子纸」—— 能写、能擦、能读,但每次擦写都有寿命。这一章咱们把 NOR 和 NAND 的架构差异、SLC/MLC/TLC/QLC 的原理、Page 和 Block 的概念彻底讲透。

NOR Flash vs NAND Flash:架构决定命运

先看一张对比图,我当年第一次看到这个结构时,心里想的是:「这不就是内存和硬盘的区别吗?」 嗯,还真有点那个意思。

NOR Flash 与 NAND Flash 架构对比 NOR Flash 架构 • 存储单元并联在 Bit Line 上 • 随机读取速度快(≈ SRAM) • 擦除粒度大(64KB~128KB) • 写入速度慢,寿命约 10 万次 NAND Flash 架构 • 存储单元串联成串(NAND String) • 随机读取慢,但连续读取快 • 擦除粒度小(4KB~8KB) • 写入快,寿命约 1 万次(TLC) 典型应用 • BIOS/UEFI 固件存储 • 嵌入式代码就地执行(XIP) 典型应用 • SSD、U 盘、eMMC • 大容量数据存储 💡 核心差异: NOR 的随机读取性能好,适合代码存储;NAND 的连续读写性能好,适合数据存储。

说白了,NOR 像一本字典 —— 你可以随便翻到哪一页就读,但写起来很慢。NAND 像一卷卫生纸 —— 你得从头撕到尾,但撕起来很快。我在做嵌入式 Bootloader 时,就吃过 NOR 写入慢的亏:烧一次固件要等 30 秒,后来换成 NAND 的 SPI Flash,3 秒搞定。

SLC / MLC / TLC / QLC:一个 Cell 能存多少比特?

你想想看,Flash 存储单元本质上就是一个浮栅晶体管。通过控制浮栅里的电子数量,来改变阈值电压。能区分几个电压等级,就能存几个比特。

类型 每 Cell 比特数 电压等级数 擦写寿命(次) 读取速度 写入速度
SLC 1 2 10 万 最快 最快
MLC 2 4 1 万 快 中等
TLC 3 8 3 千 ~ 5 千 中等 慢
QLC 4 16 1 千 ~ 3 千 慢 最慢

关键认知: 每 Cell 比特数越高,容量越大,但寿命越短、速度越慢。这不是技术缺陷,是物理规律 —— 电压窗口被切得越细,干扰越敏感。

我曾经在一个工业级项目里,客户要求 SSD 每天写满一次,连续用 5 年。算下来需要 1825 次 P/E 循环。TLC 勉强够,但我建议用 MLC,留 5 倍余量。结果客户选了 TLC,第 3 年就开始出坏块。嗯,这就是现实。

Page 与 Block:Flash 的读写基本单位

做 NVM 开发,必须把 Page 和 Block 刻在脑子里。我见过太多新手把 Flash 当硬盘用,直接按字节写,结果数据全乱套。

  • Page(页):读写的最小单位。NAND 的 Page 通常是 4KB、8KB、16KB。NOR 的 Page 一般是 256B 或 512B。
  • Block(块):擦除的最小单位。NAND 的一个 Block 包含 64 或 128 个 Page。NOR 的 Block 通常是 64KB 或 128KB。

为什么不能按字节擦除?因为 Flash 的擦除操作需要施加高电压脉冲,这个脉冲的物理范围就是 Block 大小。你想想看,如果允许按字节擦,那控制电路得复杂到什么程度?成本根本扛不住。

避坑指南: 我曾经在写 FTL(Flash Translation Layer)时,没注意 Block 和 Page 的对齐关系。结果每次写 512 字节,都触发了一次读-改-写操作,性能直接腰斩。后来改成按 Page 对齐写入,吞吐量翻了一倍。

Flash 操作的三板斧:读、写、擦

Flash 的操作就三种,但每种都有严格的约束。我习惯用一张表来记:

操作 单位 约束 典型耗时(NAND)
读(Read) Page 无特殊约束 25~50 μs
写(Program) Page 只能将 1 写成 0(即只能清 0) 200~500 μs
擦(Erase) Block 将整个 Block 恢复为全 1 1~3 ms

这里有个容易搞混的点:写操作只能把 1 变成 0,不能把 0 变成 1。要把 0 变回 1,必须擦除整个 Block。所以 Flash 的写入策略是「先擦后写」—— 写之前,目标 Block 必须是擦除状态(全 1)。

⚠️ 重要警告: 不要试图在同一个 Page 上连续写两次!第一次写完后,第二次写会破坏已有数据。我见过有人用 Flash 模拟 EEPROM,没做磨损均衡,结果同一个 Page 被写了 3 次,数据全乱码了。

Flash 的物理特性:为什么需要坏块管理?

Flash 出厂时就有坏块,而且随着使用,坏块会越来越多。这不是质量问题,是物理特性。NAND 的工艺密度太高,不可能保证每个 Cell 都完美。

  • 出厂坏块:厂商会在出厂时标记,通常 Block 0 是好的,其他 Block 可能有坏块。
  • 使用坏块:随着 P/E 循环增加,氧化层磨损,Cell 失效。
  • 读干扰:频繁读取某个 Page,会导致相邻 Page 的电子被干扰,数据出错。
  • 写干扰:写某个 Page 时,高电压会影响同一 Block 内的其他 Page。

我记得有一次调试 SSD 固件,发现某个 Block 的读取错误率突然飙升。排查了半天,发现是读干扰导致的 —— 那个 Block 被频繁读取了 100 万次,相邻 Page 的阈值电压偏移了。解决方案是加读干扰刷新(Read Disturb Refresh),每读一定次数就搬移数据。

小结:这一章你该记住什么?

  • NOR 适合代码存储,NAND 适合数据存储。
  • SLC 寿命最长、速度最快,QLC 容量最大、寿命最短。
  • Page 是读写单位,Block 是擦除单位。
  • 写操作只能 1→0,擦除操作才能 0→1。
  • 坏块管理是 Flash 开发的必修课,别想着绕过去。