Flash存储器深度解析:NAND vs NOR Flash,内部架构、读写机制与磨损均衡策略

说到嵌入式系统的非易失存储,Flash 是绕不开的主角。很多刚入行的朋友问我:「NAND 和 NOR 到底怎么选?」我的回答通常是:先搞清楚你的代码是在上面跑,还是你的数据要往里面塞。这两种 Flash 的差异,说白了就是架构基因不同导致的。

我最早接触 NOR Flash 是在做一款工业控制器的时候。当时需要在芯片上直接执行代码,NOR 的 XIP(片上执行)特性帮了大忙。后来做消费类产品,容量需求上来了,才真正开始跟 NAND 打交道。嗯,这两者的区别,咱们得从最底层的存储单元说起。

存储单元与基本架构差异

NOR Flash 的每个存储单元都并联在位线上,像个「或非门」阵列。这种结构让它能随机访问——你给个地址,它就能直接读出那个字节。NAND 呢?单元是串联的,像一串链条,读写必须按页进行。

对比维度 NOR Flash NAND Flash
存储单元连接方式 并联(每位独立连接位线) 串联(32/64 个单元串成一串)
读取方式 随机访问,按字节/字读取 按页读取(通常 2KB~16KB)
写入方式 按字节/字编程 按页编程
擦除方式 按扇区擦除(64KB~256KB) 按块擦除(128KB~几MB)
典型容量 1MB~512MB 1GB~1TB
读速度(随机) ~100ns(接近SRAM) ~25μs(页加载时间)

你看这个表格,NOR 的随机读速度是纳秒级的,NAND 是微秒级的。差了两个数量级。但 NAND 的容量密度高,成本低,大容量场景下几乎没有对手。

关键认知:NOR 适合存代码(XIP),NAND 适合存数据(文件系统、音视频)。如果你需要在 Flash 上直接运行程序,选 NOR;如果只是存数据,选 NAND。

读写机制深度对比

咱们来拆解一下读写过程。NOR 的读操作很简单:给地址,数据就出来了。写操作呢?需要先擦除再编程。擦除是把所有位从 0 变成 1,编程是把需要的位从 1 变成 0。这个「先擦后写」的机制,是所有 Flash 的共性。

NAND 的读操作分两步:先发读命令和地址,等芯片把整页数据搬进内部缓存,再从缓存读出来。写操作也是先擦除块,然后按页编程。我遇到过一个问题:有次在 NAND 上做日志存储,没注意页编程的「写后读校验」机制,结果写进去的数据读出来是错的。后来才加上 ECC 校验。

实战技巧:NAND 的页编程时间通常 200~700μs,块擦除时间 1~4ms。设计时序时,别把这两个时间算得太紧。我习惯留 20% 的余量。

坏块管理与 ECC

NAND 出厂时就可能有坏块,这是它的「出厂缺陷」。NOR 基本没有这个问题。NAND 的坏块管理是必须做的,不做的话,数据随时可能丢。

我曾经在一个项目里用了某品牌的 NAND,出厂坏块率大概 2%。当时没做坏块跳过,结果量产到第 1000 台的时候,有 20 台在格式化阶段就挂了。从那以后,我所有的 NAND 驱动都强制包含坏块表(BBT)。

ECC 方面,SLC NAND 通常需要 1-bit ECC 每 512 字节,MLC 需要 4-bit 甚至 8-bit。现在主流的做法是用 BCH 或 LDPC 纠错码。我建议你直接用硬件 ECC 引擎,软件算太慢,而且容易出错。

注意:不要相信 NAND 芯片手册上写的「不需要 ECC」——那是针对特定测试条件。实际项目中,ECC 是标配。没有 ECC 的 NAND 系统,就像没系安全带的司机。

磨损均衡策略

Flash 的擦写次数是有限的。SLC 约 10 万次,MLC 约 3000~10000 次,TLC 只有 1000~3000 次。磨损均衡就是让所有块被擦写的次数尽量平均,避免某些块提前「退休」。

磨损均衡分两种:动态均衡和静态均衡。动态均衡只在写入时选择擦写次数少的块;静态均衡还会把长期不动的冷数据搬走,腾出「年轻」的块给热数据用。

均衡策略 原理 适用场景 额外开销
动态磨损均衡 写入时选擦写次数最少的空闲块 日志、缓存等频繁写入场景 低(仅需维护块擦写计数表)
静态磨损均衡 定期将冷数据迁移到高擦写块 文件系统、数据库等混合读写场景 中(需要扫描和搬移数据)
全局磨损均衡 所有块统一管理,冷热数据动态交换 高可靠性工业/车载存储 高(需要 GC 和映射表)

我做过一个对比测试:同样的 NAND,不做磨损均衡,写入 500GB 数据后就有块失效;做了动态均衡,撑到 2TB 才开始出现坏块。静态均衡能再延长 30%~50% 的寿命。

我的建议:如果你的系统写入量不大(比如每天写几 MB),动态均衡就够了。如果写入频繁(比如视频监控、数据采集),必须上静态均衡。别省这点代码量,省下来的代价是数据丢失。

NAND vs NOR 架构对比图

下面这张图展示了两种 Flash 的内部架构差异。你可以看到 NOR 的位线是独立的,NAND 的单元是串起来的。这个结构差异决定了它们的读写方式完全不同。

NAND vs NOR Flash 内部架构对比 NOR Flash 架构 位线 字线 每个单元独立连接位线 NAND Flash 架构 位线 字线 单元串联成串(32/64个) NOR:每个单元独立 → 随机读快,适合 XIP NAND:单元串联 → 密度高、成本低,适合大容量数据存储 NOR 特性 • 随机读:~100ns • 写速度:慢(~5μs/字节) • 擦除块:64KB~256KB • 寿命:10万次(SLC) NAND 特性 • 页读:~25μs • 页写:~200μs • 擦除块:128KB~几MB • 寿命:1K~10万次 选型建议 代码执行 → NOR 数据存储 → NAND 小容量 → NOR 大容量 → NAND

实际项目中的选型建议

我总结了几条经验,供你参考:

  • 代码直接在 Flash 上跑:选 NOR。它的随机读延迟低,CPU 可以直接取指执行。我做过一个 Bootloader,放在 NOR 上,上电 50ms 就能开始执行。
  • 大容量数据存储:选 NAND。1GB 以上的场景,NOR 的价格会让你心疼。NAND 的每 MB 成本只有 NOR 的 1/10 左右。
  • 混合场景:代码放 NOR,数据放 NAND。很多 SoC 都支持这种双 Flash 方案。我最近一个项目就是这么做的,效果很好。
  • 极端环境:工业级 NOR 的温度范围更宽(-40°C~125°C),NAND 通常只有 -40°C~85°C。如果环境温度高,优先考虑 NOR。

避坑指南:我曾经在一个项目里把 NAND 当 NOR 用——直接映射到地址空间,结果读一个字节要等 25μs,CPU 直接卡死。后来才加上 Cache 和预取机制。记住:NAND 不能 XIP,必须用 DMA 或缓存。