NAND学习笔记
本文的NAND均指RAWNAND。
SLC,MLC,TLC
NAND类型 | 理论可擦写次数 | 每单元存储bit数 |
---|---|---|
SLC | 100,000 | 1 |
MLC | 10,000 | 2 |
TLC | 3000~5000 | 3 |
NAND标准
NAND标准主要分为ONFi和JEDC标准。
ONFi标准的NAND通常支持Async,NVDDR,NVDDR2,NVDDR3模式,主要NAND厂商是Micron, Hynix, Intel, SanDisk。
JEDC标准的NAND通常支持Async,Toggle模式,主要NAND厂商是Samsung, Toshiba。
标准 | 发布时间 | Async | NV-DDR | NV-DDR2 | NV-DDR3 | Toggle 1.0 | Toggle 2.0 |
---|---|---|---|---|---|---|---|
ONFI 1.0 | 2006 | 50MT/s | |||||
ONFI 2.0 | 2008 | 50MT/s | 133MT/s | ||||
ONFI 2.1 | 2009 | 50MT/s | 200MT/s | ||||
ONFI 3.0 | 2011 | 50MT/s | 200MT/s | 400MT/s | |||
JESD230 | 2012 | 50MT/s | 200MT/s | 400MT/s | 133MT/s | ||
ONFI 3.2 | 2013 | 50MT/s | 200MT/s | 533MT/s | |||
JESD230B | 2014 | 50MT/s | 200MT/s | 533MT/s | 133MT/s | 400MT/s | |
ONFI 4.0 | 2014 | 50MT/s | 200MT/s | 667MT/s | 800MT/s | ||
JESD230C | 2016 | 50MT/s | 200MT/s | 667MT/s | 133MT/s | 400MT/s | |
ONFI 4.1 | 2017 | 50MT/s | 200MT/s | 667MT/s | 1200MT/s |
NV-DDR模式在ONFi2.3之前又作Sync模式。
Toggle模式
Toggle模式采用了一根双向的DQS信号, 不需要一根单独的时钟信号。
当Host向NAND发送数据时,DQS信号由Host端控制;Host接收数据时,DQS信号由NAND控制。
Sync模式下,时钟信号是连续发送的,而Toggle模式只在读写时传输DQS信号;因此Toggle模式比Sync模式省电。
NAND层次
LU0 | LU1 | .. | LUn |
---|---|---|---|
Block 0 | Block 0 | .. | |
Page 0 | |||
Page 1 | |||
... | |||
Page x | |||
Block 1 | Block 1 | .. | |
Page 0 | |||
... | |||
Page x | |||
Block 2 | Block 2 | .. | |
... | |||
Page Reg0 | Page Reg1 | .. |
- LUN(Logical Unit Number):指闪存能够执行命令、获取状态的最小单元。例如,可以在LUN0进行写入时,对LUN1进行读取。
- Block是最小的擦除单位。如果每个Block包含的Page个数不是2的幂,地址应与大于他的最近的2的幂对齐。
- Page是最小的读写单位。(某些闪存支持Partial Page,比如可以设置Column地址,来指定从Page的某个Offset开始,直到整个Page读完)
- Page Reg用来缓存即将存入Page,或刚从Page取出的数据。
NAND地址分为
- Column Address(行地址):表示数据在Page中的偏移量。在Row Address之前发送,但是如Block Erase之类的指令无需发送该地址。
- Row Address(列地址):LUN+Block+Page的地址。
坏块标记(Bad Block Marker)
在NAND出厂时,当某个Block有缺陷时,该Block的第一个Page的OOB处(通常会在当前Block的最前面3个Page,以及最后面3个Page)标记坏块信息(BBM)。
没有缺陷的Block此处应为0xFF,有缺陷则标记为0x0。其他不等于0xFF的值也将被认为是坏块。
在初次使用NAND闪存时,厂商通常会提供一个NAND烧写工具,该工具会遍历NAND上所有的BBM,并在NAND上创建一个表,称作BBT(Bad Block Table)。
这个表会把所有的坏块记录下来,方便后续访问NAND(有了BBT,就不需要每次读取一个新的Block之前再访问这个Block的BBM了)。
常用引脚
引脚 | I/O | 全称 | 说明 |
---|---|---|---|
CE# | I | Chip Enable | 当R/B#信号为低电平时(如正进行读写、擦除操作),CE#可以上拉,选择另一个NAND芯片进行操作。 |
R/B# | O | Ready/Busy Output | 低电平时表示LUN正忙 |
CLE | I | Command Latch Enable | 指令锁存使能,用于区分当前I/O口传的是命令还是地址。 |
ALE | I | Address Latch Enable | 地址锁存使能 |
WE# | I | Write Enable | 写使能 |
RE# | I | Read Enable | 读使能 |
IO0-7,8-15 | I/O | I/O Port | NAND总线宽度可以是8位,或者16位的,但是所有的地址传输只用低8位总线(高8位填0) |
DQS | I | Data Strobe | |
WP# | I | Write Protect | 拉底后,对闪存的写入、擦除命令失效 |
对NAND检测及初始化
- Controller拉底CE#,选中NAND。
- Controller向NAND发送Reset命令。
- Controller向NAND发送Read ID命令,若NAND回应了正确的ID,则可初步判断Controller与NAND的连接配置正确。
大部分ONFi、Toggle NAND初始的时候是Async模式,通过发送Set Feature命令后,可以切入ONFi Sync,或者Toggle模式。
Legacy NAND(Async模式)
NVDDR 模式
包括6种速度(Mode 0~5)
频率 | NVDDR模式 | NVDDR2模式 |
---|---|---|
20MHz | NVDDR Mode 0 | 无 |
33MHz | NVDDR Mode 1 | NVDDR2 Mode 0 |
40MHz | 无 | NVDDR2 Mode 1 |
50MHz | NVDDR Mode 2 | 无 |
66MHz | NVDDR Mode 3 | NVDDR2 Mode 2 |
83MHz | NVDDR Mode 4 | NVDDR2 Mode 3 |
100MHz | NVDDR Mode5 | NVDDR2 Mode 4 |
133MHz | 无 | NVDDR2 Mode 5 |
166MHz | 无 | NVDDR2 Mode 6 |
200MHz | 无 | NVDDR2 Mode 7 |
267MHz | 无 | NVDDR2 Mode 8 |
NAND 模式的切换
通过发送 SET FEATURE 命令
NVDDR2 模式
包括9种速度(Mode 0~8) 高速情况下,通常使用DQS RE_B差分
Toggle 模式
Toggle 模式多了一根DQS(Data Strobe)线,在DQS的上升 & 下降沿,对 通常,Toggle NAND能够兼容Legacy NAND的操作,
NAND空闲区
OOB(Out-of-Band)/Spare region
NAND Read Retry技术
NAND在一定的擦写次数后,其读取的电平阈值会发生漂移。因此,可以通过更改参考电压的方式延长闪存使用寿命。
Meta | D0 | BCH | D1 | BCH | D2 | BCH | D3 | BCH | D4 | BCH | D5 | BCH | D6 | BCH | D7 | BCH |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
32B | 128B | ? | 128B | ? | 128B | ? | 128B | ? | 128B | ? | 128B | ? | 128B | ? | 128B | ? |
i.MX6 的NAND控制器
i.MX6内建了GPMI(General Purpose Media Interface) NAND控制器,以及BCH硬件ECC加速模块进行NAND纠错。
GPMI模块兼容ONFi 2.2以及Toggle NAND协议。
此外,i.MX6的BCH模块最多能纠错62位数据(数据长度<1900字节)。
BCH控制器
BCH的主要功能是对NAND的数据进行纠错处理。
NAND BCH Layout
| P |
|<----------------------------------------------------->|
| |
| (Block Mark) |
| P' | | | |
|<-------------------------------------------->| D | | O' |
| |<---->| |<--->|
V V V V V
+---+----------+-+----------+-+----------+-+----------+-+-----+
| M | data |E| data |E| data |E| data |E| |
+---+----------+-+----------+-+----------+-+----------+-+-----+
^ ^
| O |
|<------------>|
| |
简写 | 说明 | |
---|---|---|
G | gf_len | Galois Field长度 |
E | ecc_strength | ECC纠错强度(可纠错的数据bit数?) |
M | metadata_size | metadata长度(Byte) |
C | ecc_chunk_size | 被校验的数据块长度(Byte),例如512B。第一块数据块包含了metadata因此第一块的长度比该数值稍大些 |
N | ecc_chunk_count | 被校验的数据块个数(包括第一个?) |
P' | data_page_size | datapage大小 |
P | 实际使用的page大小(Byte) | |
O | oob长度(Byte) | |
O' | 空闲的oob | |
D | BBM与ecc_chunk(data)位置结尾的差值 |
ECC纠错能力计算
计算公式:
NAND纠错满足如下关系
(E*G*N)/8 <= (O - M)
不等式整理得:
E <= (O - M)*8/(G*N)
GF13(BCH40)的生成多项式是:x^9+1
,
可以对<=900 Bytes数据纠错(所以,C=512B时采用GF13)
GF14(BCH20)的生成多项式是:x^10 + x
,
可以对<=1900 Bytes数据纠错(所以,C=1024B时采用GF14)
BCH 默认参数的计算
ecc_chunk_size=1 << `ECC Codeword size`
if (ecc_chunk_size == 512)
gf_len = 13
if (ecc_chunk_size == 1024)
gf_len = 14
ecc_strength = roundup(`ECC Codeword size`, 2)
metadata_size=10
ecc_chunk_count = `data_page_size`/ecc_chunk_size
P = 'data_page_size` + metadata_size + (gf_len*ecc_strength*ecc_chunk_count)/8
交换BBM的位置计算
在BCH向GPMI写入NAND数据之前,需要将写入BBM位置处的Byte复制到Metadata头部,并且在BBM位置仍然保留原来的BBM;这样就不会破坏原本该block上的坏块标记信息。
同时,需要保证BBM的位置落在data里,而不是ECC里(因为data里存放的数据是raw的,这样在decode完一个page的NAND数据后,BBM位置的数据就可以被Metadata头部的数据替换回来。
NAND驱动仍应对BBM在BCH Layout上的位置进行检查,防止其落入ECC的位置。
计算公式:
D = (gf_len*ecc_strength*(ecc_chunk_count-1))/8 + metadata_size
Async模式下,读取数据的波形
{signal: [
{name: 'CE#', wave: '1.0..............1.'},
{name: 'R/B#', wave: 'x.0..........10..x.'},
{name: 'CLE', wave: 'x.010......10....x.'},
{name: 'ALE', wave: 'x.0...1..0.......x.'},
{name: 'RE#', wave: '1.............n.|h.'},
{name: 'WE#', wave: '1..nh.n.|nh........', phase: 0.5},
{name: 'IO0-7', wave: 'x..3x|4.|x|3x|=.|x.', data: ['00', 'ADDR', '30', 'DATA']},
]}
Sync模式下,读取数据的波形
{signal: [
{name: 'CE#', wave: '1.0................1.'},
{name: 'R/B#', wave: 'x.0..........10....x.'},
{name: 'CLE', wave: 'x.010......10.1....x.'},
{name: 'ALE', wave: 'x.0...1..0....1....x.'},
{name: 'CLK(RE#)', wave: 'n....|..|.......n.|..'},
{name: 'WR#(WE#)', wave: 'x..1x.1..x.1xx0....x.'},
{name: 'IO0-7', wave: 'x..3x|4.|x|3x|====|x.', data: ['00', 'ADDR', '30', 'D0', 'D1', 'D2']},
{name: 'DQS', wave: 'x.............0P....x', phase: 0.5},
]}
Toggle模式下,读取数据的波形
{signal: [
{name: 'CE#', wave: '1.0................1.'},
{name: 'R/B#', wave: 'x.0..........10....x.'},
{name: 'CLE', wave: 'x.010......10......x.'},
{name: 'ALE', wave: 'x.0...1..0.........x.'},
{name: 'RE#', wave: '1.............01010|1', phase: 0.5},
{name: 'WE#', wave: '1..nh.n.|h.nh........'},
{name: 'IO0-7', wave: 'x..3x|4.|x|3x|====|x.', data: ['00', 'ADDR', '30', 'D0', 'D1', 'D2']},
{name: 'DQS', wave: 'z.............0101|z.'},
]}
部分i.MX芯片的ECC纠错能力
芯片 | BCH ECC能力 |
---|---|
imx23 | 20 |
imx28 | 20 |
imx6q | 40 |
imx6sx | 62 |
测试常用 NAND 列表
Env | NAND | pagesize(Byte) | blockcount | pageperblk | manufacturer | devicecode | iddata | MB |
---|---|---|---|---|---|---|---|---|
RTL | hy27ss16121a | 256+8 | 4096 | 32 | 0xAD | 0x46 | 32 | |
RTL | k9f5616q0c | 256+8 | 2048 | 32 | 0xEC | 0x45 | 16 | |
RTL | tc58dvm82f1ft00 | 256+8 | 2048 | 32 | 0x98 | 0x75 | 0x20 | 16 |
RTL | hy27ss08121a | 512+16 | 4096 | 32 | 0xAD | 0x36 | 64 | |
RTL | k9f5608q0c | 512+16 | 2048 | 32 | 0xEC | 0x35 | 32 | |
RTL | nand512w3a2 | 512+16 | 4096 | 32 | 0x20 | 0x76 | 0x00, 0x00 | 64 |
RTL | tc58dvg02a1fti0 | 512+16 | 8192 | 32 | 0x98 | 0x79 | 0x20 | 128 |
RTL | hy27uf162g2m | 1K+32 | 2048 | 64 | 0xAD | 0xCA | 0x00, 0x55 | 128 |
RTL | k9f1g16u0m | 1K+32 | 1024 | 64 | 0xEC | 0xC1 | 0x00, 0x55 | 64 |
RTL | mt29f2g16aab | 1K+32 | 2048 | 64 | 0x2C | 0xCA | 0x00, 0x55 | 128 |
RTL | tc58nyg0d9bxgj5 | 1K+32 | 512 | 128 | 0x98 | 0xB1 | 0x00, 0x61 | 64 |
RTL | hy27uf082g2m | 2K+64 | 2048 | 64 | 0xAD | 0xDA | 0x00, 0x15 | 256 |
RTL | k9f1g08u0m | 2K+64 | 1024 | 64 | 0xEC | 0xF1 | 0x00, 0x15 | 128 |
RTL | k9k8g08u0m | 2K+64 | 8192 | 64 | 0xEC | 0xD3 | 0x51, 0x95, 0x58 | 1024 |
RTL | mt29f2g08aab | 2K+64 | 2048 | 64 | 0x2C | 0xDA | 0x15, 0x15 | 256 |
RTL | nand02gw3b | 2K+64 | 2048 | 64 | 0x20 | 0xDA | 0x00, 0x15 | 256 |
RTL | nand04gw3b | 2K+64 | 4096 | 64 | 0x20 | 0xDC | 0x00, 0x15 | 512 |
RTL | tc58nvg0s3aft05 | 2K+64 | 1024 | 64 | 0x98 | 0xF1 | 0x80, 0x95, 0x40 | 128 |
RTL | k9gag08u0m | 4K+128 | 4096 | 128 | 0xEC | 0xD5 | 0x14, 0xB6, 0x74 | 2048 |
RTL | tc58nvg4d1dtg00 | 4K+218 | 4096 | 128 | 0x98 | 0xD5 | 0x00, 0x3A, 0x00 | 2048 |
RTL | k9kbgd8x1m | 8K+512 | 4152 | 64 | 0xEC | 0xD5 | 0x10, 0x66, 0x34, 0xC2 | 2076 |
RTL | k9gbg08u0m | 8K+436 | 4152 | 128 | 0xEC | 0xD7 | 0x94, 0x72, 0x54, 0x42 | 4152 |
RTL | k9gbgd8u0m | 8K+512 | 4152 | 128 | 0xEC | 0xD7 | 0x14, 0x76, 0x54, 0xC2 | 4152 |
RTL | k9fagd8u0m | 8K+640 | 4152 | 64 | 0xEC | 0xD5 | 0x10, 0x66, 0x34, 0xC2 | 2076 |
RTL | toggle20_k9gcgy8s0a | 8K+640 | 8192 | 128 | 0xEC | 0xAE | 0xE5, 0x7E, 0x7C, 0xC4 | 8192 |
RTL | sdtnqgama_008ga | 16K+1280 | 2132 | 256 | 0x45 | 0xDE | 0x94, 0x93, 0x76, 0xD7 | 8528 |
RTL | sdtnrgama_008gp | 16K+1280 | 2132 | 256 | 0x45 | 0xDE | 0x94, 0x93, 0x76, 0x50 | 8528 |
RTL | sdtnrgama_008g | 16K+1280 | 2132 | 256 | 0x45 | 0xDE | 0x94, 0x93, 0x76, 0x50 | 8528 |
MX8QXPLPD4 | MT29F128G08CBCCBH6 | 16K+1872 | 512 | 0x2C | 0x84 | 0x64 0x54 0xa9 |
参考
ONFi Specification
Raw NAND ECC
How Micron FortisFlash Technology Improves Performance and Endurance
gpmi-nand.c