4、NAND闪存组织架构:Die、Plane、Block与Page的层级关系
好,咱们今天聊聊NAND闪存内部是怎么搭起来的。你拿到一颗NAND芯片,别把它想得太神秘。说白了,它就是一个超级复杂的“存储大楼”。这栋楼里,有楼层、有房间、有柜子、有抽屉。Die、Plane、Block、Page,就是这四层结构。
我刚开始接触NAND时,也搞混过Block和Page的关系。后来调了一个坏块管理的驱动,才彻底搞明白——嗯,不搞清楚这些层级,你连地址都发不对。
4.1 最高层级:Die(晶粒)
Die,也叫LUN(Logical Unit Number)。你可以把它理解为一颗独立的芯片。一个NAND封装里,可能藏着1个、2个甚至4个Die。每个Die都有自己的片选信号(CE#),能独立干活。
举个例子,我手头有颗8GB的NAND,里面其实是4个2GB的Die拼在一起的。操作系统看到的是一个大容量,但底层是4个“小芯片”在并行工作。
关键点:Die之间是相互独立的。一个Die在擦除,另一个Die可以同时读数据。这就是所谓的“多Die交错操作”,能大幅提升性能。
4.2 第二层级:Plane(平面)
一个Die里,又被切成了若干个Plane。常见的是2个或4个。Plane存在的意义是什么?说白了,就是为了让你能并行操作。
每个Plane有自己的缓存寄存器(Cache Register)和数据寄存器(Data Register)。你想想看,如果只有一个Plane,那读一个Page的时候,整个Die都得等着。但如果有两个Plane,你可以同时从两个Plane里各读一个Page出来。
我记得有一次做性能优化,发现读带宽上不去。查了半天,原来是驱动里没开Plane并行模式。改了一行配置,吞吐量直接翻倍。这种坑,踩过一次就忘不了。
小技巧:支持Multi-Plane操作的NAND,发送命令时可以用特定的指令(如00h-01h-00h-02h)来同时操作两个Plane。但要注意,这两个Plane的地址必须在同一个Die内。
4.3 第三层级:Block(块)
Block是擦除操作的最小单位。这一点非常重要——你不能只擦除一个Page,必须整个Block一起擦。
为什么这么设计?这是NAND的物理特性决定的。浮栅晶体管的电子注入/释放,需要较高的电压和较长的时间。如果允许按Page擦除,那控制电路会变得极其复杂,而且擦除干扰也会更严重。
一个Block里,通常包含64个、128个或256个Page。具体数量取决于工艺和密度。比如,SLC的Block里Page数少一些,TLC/QLC的Block里Page数就多得多。
避坑指南:我曾经遇到过一块NAND,用着用着突然出现大量坏块。排查后发现,是因为频繁对同一个Block做擦写,导致那块区域提前“退休”了。所以,磨损均衡(Wear Leveling)一定要做好,别逮着一个Block猛薅。
4.4 第四层级:Page(页)
Page是读写操作的最小单位。你读数据,一次至少读一个Page;你写数据,一次至少写一个Page。Page的大小,常见的有4KB、8KB、16KB,甚至更大。
每个Page又分为两个区域:主数据区(Main Area)和备用区(Spare Area,也叫OOB)。主数据区存你的用户数据,备用区存ECC校验码、坏块标记、逻辑地址映射表等元数据。
举个例子,一个16KB的Page,可能主数据区是16KB,备用区是1KB。这1KB的空间,就是给控制器做“后勤保障”用的。
我个人习惯,在设计FTL(闪存转换层)时,会把逻辑页号(LPN)和物理页号(PPN)的映射关系,也存一部分到备用区里。这样掉电后重建映射表会快很多。
4.5 层级关系一览
为了让你看得更清楚,我画了一张结构图。这张图展示了从Die到Page的完整层级关系。
4.6 地址映射与操作限制
搞清楚了层级,咱们再看看地址是怎么组织的。一个完整的NAND地址,包含以下几部分:
- Die地址:选择哪个芯片(通过CE#片选信号)
- Plane地址:选择Die内的哪个平面
- Block地址:选择Plane内的哪个块
- Page地址:选择Block内的哪个页
- Column地址:选择Page内的哪个字节(用于随机读/写)
这里有个容易犯错的点。你发地址时,必须按照NAND协议规定的顺序来。比如,传统的ONFI协议,地址周期是先发Column地址,再发Row地址(包含Block和Page信息)。顺序搞反了,数据就读到沟里去了。
我曾经调试一个驱动,发现读出来的数据全是乱的。用逻辑分析仪抓了波形,才发现是地址发送顺序错了。嗯,这种低级错误,犯过一次就长记性了。
4.7 实际操作中的注意事项
最后,给你几个实际项目中用得上的建议:
- 坏块管理要按Block来:NAND出厂就有坏块,用着用着还会产生新坏块。坏块标记通常存在Block的第一个Page的OOB区里。你擦除时,如果发现擦除失败,这个Block就该标记为坏块了。
- 读写操作要按Page对齐:你写数据时,如果数据量不是Page大小的整数倍,就得做读-改-写操作。这很慢,而且会增加写放大。我建议你在上层就把数据整理成Page对齐的。
- 擦除操作要小心:擦除一个Block需要几毫秒。在这期间,这个Block是不能读写的。如果你的系统有实时性要求,得考虑这个延迟。
- Multi-Plane操作有约束:不是所有Plane组合都能并行。有些NAND要求并行操作的Plane必须在同一个Die内,而且操作类型必须相同(都是读,或都是写)。
个人经验:我设计FTL时,会把逻辑地址空间按Block大小做分区。每个分区对应一个Block池。这样,磨损均衡和垃圾回收都容易管理。你想想看,如果逻辑地址和物理Block是一一对应的,那映射表就简单多了。
好了,这一章的内容就到这儿。Die、Plane、Block、Page这四层关系,是理解NAND操作的基础。你把这些搞清楚了,后面学命令序列、时序参数,就会轻松很多。