NAND Flash是构成固态存储的基本存储单元其采用IO的接口方式与控制器相连。控制器对NAND Flash进行操作时需要通过命令交互的方式对NAND Flash进行操作。下面对NAND Flash的操作进行解析可以发现在研发FTL的时候可以充分发掘NAND Flash提供的操作命令来优化读写性能。分析介绍的NAND FlashMicron提供的MT29F16G08AA为蓝本。该芯片能够提供16Gb 的存储容量具体性能指标如下所示

 

wKiom1OlvSvBus7RAAA91JypxJs002.jpg

 

  Organization

     Page size: 2048+64 bytes

     Block size: 64 Pages

     Plane size: 2048 Blocks

  Read performance

     Random Read: 25us (MAX)

     Sequential Read: 25ns (MIN)

  Write performance

     Program page: 220us (TYP)

     Block erase: 1.5ms (TYP)

  Data retention: 10 years

  Endurance: 100,000 erase cycles

我们知道NAND Flash的最小读写单元是page最小擦除单元是Block。与控制器的接口方式是IO接口NAND Flash的内部原理如下图所示

 

wKioL1OlvSKz9WQ-AAC_VzFp6SE971.jpg

 

从上图可以看出I/Ox信号用于传输数据或者地址信息通常有8位或者16位数据宽度。其余信号为控制信号包括片选信号、命令选择信号、地址选择信号、写控制信号、读控制信号、写保护信号、状态信号。在NAND Flash内部提供了多种寄存器包括地址/命令寄存器和状态寄存器。NAND Flash控制其就是和这些寄存器打交道完成数据读写/擦除操作。NAND Flash的核心是NAND Flash ArrayNAND Flash Array前有两个非常重要的寄存器数据寄存器和Cache寄存器。有了这两个寄存器之后可以将读写操作进行流水处理从而提高数据读写性能。数据流水的思路如下图所示

 

wKioL1OlvTfDobYNAADLeR8g3TQ661.jpg

 

用户数据通过NAND Flash控制器首先写入Cache Register随后很快将Cache中的数据导入Data Register。数据从CacheData寄存器需要很短的延迟。数据进入Data Register之后可以写入具体的NAND Flash写入操作需要200us左右的延迟。流水的价值在于在数据从Data RegisterNAND Flash写入的时候用户又可以通过控制器将数据写入Cache Register。因此提高了整体数据吞吐量但是从单个请求来讲增加了延迟。

Micron NAND Flash的基本操作命令表如下图所示

 

wKiom1OlvXyiCaYQAAGWrZfn-OM964.jpg

 

从上表可以看出NAND Flash操作命令并不复杂主要分为页读、页编程、块擦除、状态查询等命令类型。实现一个驱动程序或者控制器的时候就需要实现上述NAND Flash命令。

NAND Flash控制器的角度来看一个Page页的顺序读时序如下图所示

 

wKiom1OlvZGxx4C3AACWaUu6z54645.jpg

 

首先发送0x00 Page页读命令在命令期之后发送读地址。如果Page数据已经准备完毕那么状态信号R/B将会由低变高当该信号跳变之后开始读取数据。从NAND Flash芯片内部来看读命令发送之后Page数据将会被装载到内部的Cache寄存器中随后状态指示信号由低变高。之后数据在读信号的控制下从Cache寄存器读入IO接口总线上。

值得一提的是NAND Flash芯片也支持随机读即读地址可以与Page页不对齐。实际上这种随机读是有限制的即随机读只能发生在Page页读完成之后时序图如下所示

 

wKioL1OlvXiCL0rsAABluKAXbYw278.jpg

 

在一个Page页读完成之后可以发送业内随机读地址最后在读信号的控制下将随机读数据从Cache Page中输出到外部IO总线上。

Nand Flash的另一个重要操作就是写操作在NAND Flash中写操作就是page的编程操作。Page页是编程的最小单元其操作时序可以描述如下

 

wKioL1OlvYyx_UWlAAB4EM4VNGU532.jpg

 

FTL软件中为了避免“写时块擦除”操作会引入类似于Log文件系统的方式对写入的逻辑page进行重映射即实现out-of-place的写入方式。在这种写入方式中如果用户写入的数据小于一个page页那么需要将无需更新的数据从old-page中拷贝出来然后和新数据合并写入新的page中。为了提高这个操作的性能NAND Flash提供了一种数据迁移的命令并且在数据迁移的过程中可以任意修改page中的数据。采用这种命令来实现out-of-place的数据更新方式将会有效提高IO性能。数据迁移的操作时序如下图所示

 

wKiom1OlvdLhi2BWAACAbGE_qAc733.jpg

 

通过0x00命令将数据从Flash Array中读取至寄存器中然后通过0x85命令直接将寄存器中的数据写入至一个新的page页中。在写入之前可以修改数据寄存器中的值从而实现了老数据的迁移和新数据的合并并且可以完成逻辑page页的重映射。

NAND Flash的一个非常重要的操作是数据块的擦除。块擦除是非常耗时的操作ms数量级但是操作命令非常的简单该时序图如下所示

 

wKiom1Olve6AapA9AACw9Muqzq0761.jpg

 

需要擦除一个block块是需要发送0x60命令并且需要指定块地址。擦除操作正在进行的时候状态指示信号R/B一直处于低电平状态。一旦从低电平状态恢复成高电平时说明块擦除操作完成。完成之后通过0x70命令获取擦除操作是否存在故障。从而确定该块在后继写入的时候是否能够继续使用。

上述提到的这些接口时序是NAND Flash控制器需要完成的。由于其功能比较有限所以开发难度并不是很大可以采用verilog开发这类控制器。对于软件开发人员而言不会涉及到这些NAND Flash的操作命令除非在一些嵌入式或者单片机开发系统中才有可能涉及到这些命令。例如可以通过单片机的GPIO模拟NAND Flash的接口时序然后通过软件的方式实现与NAND Flash的数据交换。此时软件开发就需要非常熟悉这些接口时序以及接口命令了。

固态存储在不断的往企业级存储领域推进了解底层NAND Flash的工作机制对存储系统研发是非常有必要的。只有这样才可以清楚的了解到每一个IO操作在各个层次都具体做了些什么事情才有可能更好的优化、发挥存储系统的性能。