3、Flash架构:NAND Flash与NOR Flash的区别、内部阵列结构、Page/Block/Plane概念
好,咱们今天聊聊Flash架构。说实话,Flash这玩意儿在存储领域太常见了,但很多人对它的内部结构其实是一知半解的。我当年刚入行时,也踩过不少坑。比如有一次,我设计的嵌入式系统里用了NOR Flash做代码存储,结果发现擦写次数根本不够用,后来才意识到应该用NAND。嗯,这就是没搞清楚两者区别的代价。
3.1 NAND Flash与NOR Flash:到底差在哪?
先说说最核心的区别。你想想看,NOR Flash和NAND Flash,名字就差一个字,但内部逻辑完全不同。
NOR Flash,说白了就是“随机访问型”。它的存储单元是并联的,每个单元都能独立寻址。这意味着你可以像读内存一样,直接读任意地址的数据。我习惯用它来存代码,因为CPU可以直接在NOR上执行程序(XIP,eXecute In Place),不需要先拷贝到RAM里。
NAND Flash呢,是“串行访问型”。它的存储单元是串联的,读写必须按页(Page)进行。你不能直接读某个字节,得先把整页数据读出来。这听起来有点麻烦,但好处是——密度高、成本低、容量大。我建议做数据存储时优先考虑它,比如U盘、SSD、手机存储,全是NAND的天下。
我列个表,方便你对比:
| 特性 | NOR Flash | NAND Flash |
|---|---|---|
| 访问方式 | 随机访问(字节级) | 页访问(块级) |
| 读速度 | 快(~100ns) | 较慢(~25μs 首次) |
| 写速度 | 慢(~10μs/字节) | 快(~200μs/页) |
| 擦除速度 | 慢(~1s/块) | 快(~2ms/块) |
| 密度 | 低(< 512Mb) | 高(可达Tb级) |
| 寿命 | 10万~100万次 | 1千~10万次 |
| 典型应用 | 代码存储、BIOS | 数据存储、SSD |
核心要点:NOR适合存代码,NAND适合存数据。别搞反了,否则你会后悔的。
3.2 内部阵列结构:NAND的“串”与NOR的“并”
咱们深入一点,看看芯片内部到底长什么样。
NOR Flash的阵列结构,每个存储单元都连接着位线(Bit Line)和字线(Word Line)。你可以把它想象成一张网格,每个交叉点就是一个存储单元。这种结构的好处是——读操作非常快,因为你可以直接选中某个单元。但坏处是——面积大,因为每个单元都需要独立的接触孔。我做过一个项目,用NOR Flash做128Mb的存储,结果芯片面积比同容量的NAND大了三倍多。
NAND Flash的阵列结构,就完全不同了。它的存储单元是串联成一串的,通常32个或64个单元串在一起,形成一个“NAND串”。这个串的一端接位线,另一端接源线。你想想看,这样设计的好处是什么?——单元之间共享接触孔,面积大大缩小。我建议你记住这个数字:NAND的单元面积可以做到NOR的1/4到1/8。这就是为什么NAND能轻松做到Tb级容量。
嗯,这里要注意:NAND的读操作是“串行”的。你要读某个单元,得先把整个串上的其他单元都打开,然后才能读到目标单元的数据。这就像排队,你得等前面的人走完,才能轮到你。
个人经验:我在设计NAND控制器时,发现一个常见误区——很多人以为NAND的读延迟是固定的。其实不是,它取决于你读的是哪个Page。如果Page在同一个Block里,读延迟会小很多。我曾经因为这个疏忽,导致系统响应时间不稳定,后来加了预取机制才解决。
3.3 Page、Block、Plane:NAND的三层结构
好,接下来是重点。NAND Flash有三个核心概念:Page、Block、Plane。我建议你把这几个概念刻在脑子里,因为所有NAND的操作都离不开它们。
3.3.1 Page(页)
Page是NAND读写的最小单位。什么意思?就是你没法只读一个字节,必须读一整页。常见的Page大小有2KB、4KB、8KB、16KB。我最近用的3D NAND,Page已经到16KB了。
每个Page又分为两个区域:
- 主数据区(Main Area):存用户数据,比如你的照片、文档。
- 备用区(Spare Area / OOB):存元数据,比如ECC校验码、坏块标记、逻辑地址映射。
举个例子,一个8KB的Page,通常主数据区是8KB,备用区是256字节。你写数据时,主数据区写满,备用区自动写入ECC。我习惯在设计驱动时,把备用区的前几个字节留给坏块标记,这样扫描坏块时效率高。
注意:Page的读写是原子的。如果你写了一半断电,那整个Page的数据都可能损坏。所以,我建议你在写Page之前,先确保电源稳定,或者加个电容做掉电保护。
3.3.2 Block(块)
Block是NAND擦除的最小单位。一个Block包含多个Page,常见的有64个、128个、256个Page。比如,一个Block有128个Page,每个Page 8KB,那这个Block就是1MB。
为什么擦除要以Block为单位?因为NAND的物理结构决定了——你不能只擦除一个Page,必须把整个Block都擦掉。这就像你没法只删除一本书的一页,必须把整章撕掉。
我遇到过一个问题:有一次,我需要更新一个文件中的几个字节,结果发现必须先把整个Block读出来,修改,然后擦除整个Block,再写回去。这个过程叫“读-改-写”,非常耗时。后来我用了日志结构(Log-Structured)的写入方式,才避免了频繁的擦除操作。
避坑指南:我曾经在一个项目里,因为频繁擦写同一个Block,导致那个Block提前报废。后来我加了磨损均衡(Wear Leveling)算法,才把寿命提上来。记住:NAND的擦写次数是有限的,别逮着一个Block猛薅。
3.3.3 Plane(平面)
Plane是NAND内部的一个并行单元。一个Die(芯片)通常包含多个Plane,比如2个、4个。每个Plane有自己的Page寄存器,可以独立执行读写操作。
Plane的作用是什么?——并行化。你想想看,如果只有一个Plane,那一次只能读一个Page。如果有4个Plane,那理论上可以同时读4个Page。这就是为什么高端SSD的读写速度那么快,因为它们内部有多个Plane在并行工作。
我建议你在设计NAND控制器时,尽量利用Plane的并行性。比如,把数据分散到不同的Plane上,这样读写速度能提升好几倍。我做过一个测试:单Plane读速度是200MB/s,4个Plane并行读,速度飙到了750MB/s。
嗯,这里有个细节:不同Plane之间的操作是独立的,但共享同一个I/O总线。所以,你不能同时往两个Plane里写数据,但可以一个在读,另一个在写。这叫“交错操作”(Interleaving)。
| 层级 | 最小操作单位 | 典型大小 | 操作类型 |
|---|---|---|---|
| Page | 读写 | 2KB ~ 16KB | 读、写 |
| Block | 擦除 | 64 ~ 256 Pages | 擦除 |
| Plane | 并行单元 | 多个Block | 并行读写 |
3.4 总结一下
好,咱们把今天的内容串一下:
- NOR vs NAND:NOR随机访问,适合存代码;NAND串行访问,适合存数据。
- 内部阵列:NOR是并联结构,面积大;NAND是串联结构,密度高。
- Page/Block/Plane:Page是读写单位,Block是擦除单位,Plane是并行单位。
我个人觉得,理解这三层结构是掌握NAND Flash的关键。你想想看,如果你连Page和Block都分不清,那后面学FTL(Flash Translation Layer)和垃圾回收时,肯定会一头雾水。
下次咱们聊NAND的读写时序和ECC校验,到时候我会分享一个我踩过的坑——因为ECC配置不对,导致数据静默损坏。嗯,那是个挺惨的教训。