第3章 SSD存储介质:闪存
3.1 闪存物理结构
3.1.1 闪存器件原理
1978年诞生的世界上第一块固态硬盘就是基于DRAM的。但由于保存在DRAM中的数据有掉电易失性
,当然还有成本因素,所以现在的固态硬盘一般都不采用DRAM,而是使用闪存作为存储介质,并且是NAND闪存
固态硬盘的工作原理很多也都是基于闪存特性的。比如,闪存在写之前必须先擦除,不能覆盖写
,于是固态硬盘才需要垃圾回收(Garbage Collection,或者叫Recycle);闪存每个块(Block)擦写次数达到一定值后,这个块要么变成坏块
,要么存储在上面的数据不可靠,所以固态硬盘固件必须做磨损平衡,让数据平均写在所有块上,而不是盯着几个块拼命写。还有很多类似的例子,固态硬盘内部很多算法都是在为闪存服务的。所以,欲攻固态硬盘,闪存首当其冲
闪存是一种非易失性存储器
,也就是说,掉电了数据也不会丢失。闪存基本存储单元(Cell)是一种类NMOS的双层浮栅(Floating Gate)MOS管,如图3-1所示
图3-1 浮栅晶体管结构 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
在源极(Source)和漏极(Drain)之间电流单向传导的半导体上形成存储电子的浮栅,浮栅上下被绝缘层包围,存储在里面的电子不会因为掉电而消失
,所以闪存是非易失性存储器
写操作是在控制极加正电压
,使电子通过绝缘层进入浮栅极。擦除操作正好相反,是在衬底加正电压,把电子从浮栅极中吸出来,如图3-2所示
图3-2 左:写原理;右:擦除原理 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3.1.2 SLC、MLC和TLC
一个存储单元存储1bit数据的闪存
,叫它为SLC(Single Level Cell),存储2bit数据的闪存为MLC(Multiple Level Cell),存储3bit数据的闪存为TLC(Triple Level Cell),如表3-1所示。现在已经有厂商在研发QLC,即一个存储单元存储4bit数据
表3-1 SLC、MLC、TLC原理 表格来源于《深入浅出SSD:固态存储核心技术、原理与实战》
对SLC来说,一个存储单元存储两种状态,浮栅极里面的电子多于某个参考值的时候,把它采样为0,否则就判为1
图3-3是闪存芯片里面存储单元的阈值电压分布函数,横轴是阈值电压
,纵轴是存储单元数量
。其实在0或1的时候,并非所有的存储单元都是同样的阈值电压,而是以这个电压为中心的一个分布。读的时候采样电压值落在1范围里面,就认为是1;落在0范围里面,就认为是0
图3-3 SLC电压分布 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
擦除之后,闪存读出来的值为1,充过电之后,就是0
。所以,如果需要写1,就什么都不用干;写0,就需要充电到0
对MLC来说,如果一个存储单元存储4个状态,那么它只能存储2bit的数据,如图3-4所示。通俗来说就是把浮栅极里面的电子个数进行一个划分,比如低于10个电子判为0;11~20个电子判为1;21~30个电子判为2;多于30个电子判为3
图3-4 MLC电压分布 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
依此类推,TLC若是一个存储单元有8个状态,那么它可以存储3bit的数据,它在MLC的基础上对浮栅极里面的电子数又进一步进行了划分,如图3-5所示
图3-5 TLC电压分布 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
同样面积的一个存储单元,SLC、MLC和TLC分别可以存储1bit、2bit、3bit的数据,所以在同样面积的DIE上,闪存容量依次变大
但同时,一个存储单元电子划分得越多,那么在写入的时候,控制进入浮栅极的电子个数就要越精细,所以写耗费的时间就越长;同样的,读的时候,需要尝试用不同的参考电压去读取,一定程度上加长了读取时间。所以会看到在性能上,TLC不如MLC,MLC不如SLC
如表3-2所示是SLC、MLC和TLC在性能和寿命(Endurance)上的一个直观对比
表3-2 SLC、MLC、TLC参数比较 表格来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3.1.3 闪存芯片架构
闪存芯片就是由成千上万这样的存储单元按照一定的组织结构组成的。图3-6所示是一个闪存块(Block)的组织架构。一个Wordline对应着一个或若干个Page
,具体是多少取决于是SLC、MLC或者TLC。对SLC来说,一个Wordline对应一个Page;MLC则对应2个Page,这两个Page是一对(Lower Page和Upper Page);TLC对应3个Page(Lower Page、Upper Page和Extra Page,不同闪存厂家叫法不一样)。一个Page有多大,那么Wordline上面就有多少个存储单元,就有多少个Bitline
。一个Block当中的所有这些存储单元都是共用一个衬底的
图3-6 闪存Block组织架构 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
一个闪存内部的存储组织结构如图3-7所示:
- 一个闪存芯片有若干个DIE(或者叫LUN)
- 每个DIE有若干个Plane
每个Plane有若干个Block
- 每个Block有若干个Page
每个Page对应着一个Wordline
- Wordline由成千上万个存储单元构成
图3-7 闪存内部组织架构 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
DIE/LUN是接收和执行闪存命令的基本单元
。如图3-7所示,LUN0和LUN1可以同时接收和执行不同的命令(但还是有一定限制的,不同厂家的闪存限制不同)。但在一个LUN当中,一次只能独立执行一个命令,不能对其中某个Page写的同时,又对其他Page进行读访问
一个LUN又分为若干个Plane,常见的是1个或者2个Plane,现在也有4个Plane的闪存了。每个Plane都有自己独立的Cache Register和Page Register,其大小等于一个Page的大小。固态硬盘主控在写某个Page的时候,先把数据从主控传输到该Page所对应Plane的Cache Register当中,然后再把整个Cache Register当中的数据写到闪存阵列;读的时候则相反,先把这个Page的数据从闪存介质读取到Cache Register,然后再按需传给主控。按需就是我们读取数据的时候,没有必要把整个Page的数据都传给主控,而是按需选择数据传输。但要记住,无论是从闪存介质读数据到Cache Register,还是把Cache Register的数据写入闪存介质,都以Page为单位
,如图3-8所示
图3-8 Page缓存的用法 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
为什么需要Cache Register和Page Register两个缓存?主要目的是优化闪存的访问速度
。闪存支持Cache读、写操作,如图3-8所示。Cache读支持在传输前一个Page数据给主控的时候(Cache Register→主控),可以从闪存介质读取下一个主控需要读的Page的数据到Page Register(闪存介质→Page Register),这样数据在闪存总线传输的时间就可以隐藏在读闪存介质的时间里(或者相反,取决于哪个时间更长);Cache Program也是如此,它支持闪存写前一个Page数据的同时(Page Register→闪存介质),传输下一个要写的数据到Cache Register(主控→Cache Register),这样数据在闪存总线传输可以隐藏在前一个Page的写时间里
当然,有两个Register的闪存也支持正常的读写模式,这时候,用户可以把Cache Register和Page Register看成是一个缓存
我们通常所说的闪存读写时间,并不包含数据从闪存到主控之间的数据传输时间,也不包括数据在Cache Register和Page Register之间的传输时间
- 闪存写入时间:是指一个Page的数据从Page Register当中写入闪存介质的时间
- 闪存读取时间:是指一个Page的数据从闪存介质读取到Page Register的时间
闪存一般都支持Multi-Plane(或者Dual-Plane)操作。那么什么是Multi-Plane操作呢?
- 对写来说,主控先把数据写入第一个Plane的Cache Register当中,数据保持在那里,并不立即写入闪存介质,等主控把同一个LUN上的另外一个或者几个Plane上的数据传输到相应的Cache Register当中,再统一写入闪存介质。假设写入一个Page的时间为1.5ms,传输一个Page的时间为50μs:如果按原始的Single Plane操作,写两个Page需要至少(1.5ms+50μs)×2;但如果按照Dual-Plane操作,由于隐藏了一个Page的写入时间,写入两个Page只要1.5ms+50×2μs,缩减了几乎一半的时间,写入速度几乎翻番
- 对读来说,使用Dual-Plane操作,两个不同Plane上的Page数据会在一个闪存读取时间加载到各自的Cache Register当中,这样用一个读取时间读取到两个Page的数据,读取速度加快。假设读取时间和数据传输时间相当,都是50μs,Single Plane读取传输两个Page需要50μs×4=200μs,Dual-Plane则需要50μs×2+50μs=150μs,时间为前者的75%,读取速度也有很大的提升
闪存的擦除是以Block为单位的
。因为在组织结构上,一个Block当中的所有存储单元是共用一个衬底的(Substrate)。当你对某衬底施加强电压,那么上面所有浮栅极的电子都会被吸出来。每个闪存Block都有擦写次数的限制,这个最大擦写次数按SLC、MLC、TLC依次递减:SLC的擦写次数可达10万次
,MLC一般为几千到几万次,TLC降到几百到几千次。随着闪存工艺的不断进步(现在已进入1Xnm时代),闪存容量不断加大,但性能与可靠性却在变差。要克服闪存的这些不利因素,固态硬盘固件算法需要面对更多、更大的挑战
3.1.4 读、写、擦原理
1 擦除
如图3-9所示,擦除前,浮栅上有可能有电子,Pwell加20V电压,经过足够时间后,由于量子隧道效应,电子从浮栅到沟道里面,完成一个Block的擦除,阈值电压都变成了-VT ,状态为“1”
。一个LUN上的MOS管共用一个Pwell,但是其他不用擦除的Block的栅极电压是悬空,不会有隧道效应
图3-9 擦除操作电压示例 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
2 写
如图3-10所示,擦除后所有的单元阈值电压为-VT ,写电压如下:要写的单元Wordline为高电压,Bitline=0V;由于量子隧道效应,电子从沟道到浮栅,成为“0”
。不写的单元Bitline为2V,在沟道里的效应阻碍了量子隧道效应发生
图3-10 写入操作电压示例 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3 读
不读的Wordline=5V,管子保持导通;要读的单元Wordline=0V,-VT 的管子导通,Bitline端的传感器能够检测到,所以读到“1”,而经过写的+VT的管子不导通,传感器读为“0”
图3-11 读操作电压示例 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3.1.5 三维闪存
因为集成密度高、单位比特成本低和可靠性高等众多优点,闪存占据了手机、平板、固态硬盘等绝大部分的非易失性存储市场。可是因为技术上的限制,这些优势越来越难以维持下去
即使2次曝光技术(Double Patterning Technology)和4次曝光技术(Quadruple Patterning Technology)的引入提高了制造工艺,但随着一代又一代半导体制造技术的演进,二维平面单元尺寸逐渐减小,单元间的相互干扰却在逐渐增加。基于二维平面单元结构的尺寸缩小已经无法进一步降低比特成本了,即达到了技术上的瓶颈
图3-12为过去十年的单元尺寸与单元相互干扰的变化趋势图。从上半部分可以看出,二维闪存单元尺寸不断下降,对应到下半部分就是单元间的相互干扰不断增加,但到了三维闪存后,尺寸居然又再次变大了,所以,单元间相互干扰大幅度减小
图3-12 过去十年的单元尺寸(左)与单元相互干扰(右)的变化趋势 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
为了克服二维平面单元结构的技术瓶颈,自2006年以来,各种三维闪存结构陆续被提出来。其中一种叫作TCAT,已经于2013年开始了规模化量产。三维闪存结构并不是利用传统的缩小单元的方法,而是以提高堆叠栅极结构(WL)的数目来提高芯片的集成密度
图3-14是《Inside NAND Flash Memories》一书提供的某一类三维闪存的结构示意图,在这种三维闪存中,沟道是竖起来的,一层一层盖楼的是连接到栅极的Wordline
图3-14 三维闪存立体图 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
与二维平面闪存相比,TCAT更加稳定、可靠而且性能水平更加优越。如图3-16所示,
- 单元间相互干扰降低了84%
- 擦写寿命却提高了10倍以上
- 编程时间(tPROG)也减少了一半
- 阈值电压Vth 随着擦写增多带来的偏移也减小了67%
图3-16 二维闪存和TCAT三维闪存特性对比 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
自从24层堆叠的三维闪存可大规模生产以来,32层、48层及64层堆叠的三维闪存也接连投产。如图3-17所示,三维闪存的存储密度在每一代几乎都实现了翻倍
图3-17 三维闪存存储密度增长图 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
不过三维闪存也面临下面两个挑战:
- 1)堆叠栅极层数目增加带来的问题。 正如前面所说,三维闪存通过增加堆叠栅极层的数目来提高比特密度,而且每一代堆叠栅极层数目都会增加30%~50%,这会带来许多困难,比如串电流的减小,高层与低层单元特征的差异性增大
- 2)单元模具厚度减小带来的问题。 跟二维闪存类似,随着工艺一代一代迭代,最小尺寸也在不断减小,所以单元模具厚度不断减小,单元间的干扰也得到了增强
如图3-18所示,随着堆叠栅极层数目的增加,每个Block的Page数目不断增加。在读的过程中,对一个Block来说,累积的读取数目增加,导致读干扰会变严重。为了降低读干扰,需要降低读参考电压Vread ,这样就会导致串电流减小,使得提供给传感运放的信号更微弱
图3-18 层数越多,串电流变小,读次数增加 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
如图3-19所示,高层与低层之间的单元会存在差异。通道孔的尺寸大小和栅极厚度也存在差异,这些结构上的差异会带来编程/擦除速度的差异、单元间干扰的差异以及数据保存的差异等
图3-19 高层和底层单元差异 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
底层单元的通道孔小,所以耦合率更高,擦写速度更快。但是,底层单元的栅极更薄,所以数据保存期更短
3.1.6 Charge Trap型闪存
闪存的一种技术——Charge Trap,闪存不只有Floating Gate,还有Charge Trap
。中文可以翻译成电阱,CT像个陷阱一样,把电荷困在里面存起来,如图3-20所示
图3-20 浮栅晶体管与CT晶体管对比 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
CT与浮栅最大的不同是存储电荷的元素不同,后者是用导体存储电荷,而前者是用高电荷捕捉(Trap)密度的绝缘材料(一般为氮化硅,SI3N4)来存储电荷
。CT的绝缘材料上面就像布了很多陷阱,电子一旦陷入其中,就难以逃脱,而浮栅是导体材料,电子可以在里面自由移动。有人是这样来形容两者区别的:浮栅就像水,电子可在里面自由移动;而CT就像是奶酪,电子在里面移动是非常困难的,如图3-21所示
图3-21 浮栅像水,CT就像奶酪 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
为什么要强调电子不容易移动?
要知道,浮栅晶体管对浮栅极下面的绝缘层很敏感,该氧化物厚度变薄(制程不断减小导致的)或者老化(Degradation,擦写次数多了),浮栅极里面存储的电子进出变得容易。浮栅极里面的电子可以自由移动,因此对氧化层变得敏感。如果里面的电子本来就深陷其中,行动困难,即使绝缘层老化,电子还是不容易出来。因此,相对浮栅晶体管来说,CT的一个优势就是:对隧道氧化层不敏感,当厚度变薄或者擦除导致老化时,CT表示压力不大
浮栅晶体管的浮栅极材料是导体,任何两个彼此绝缘且相隔很近的导体间都会构成一个电容器。因此,任何两个存储单元的浮栅极都构成一个电容器
,一个浮栅极里面电荷的变化都会引起别的存储单元浮栅极电荷的变化
一个浮栅极与其附近的浮栅极之间,都存在耦合电容,如图3-22所示,这个电容大小与彼此之间距离成反比:距离越短,电容越大,彼此影响越大。随着闪存制程减小,存储单元之间影响越来越大。因此,存储单元间距也是影响制程继续往前的一个因素。CT对存储单元间距表示压力不大,因为存储电荷的是绝缘体,而非导体
图3-22 浮栅晶体管之间耦合电容 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
与浮栅晶体管相比,CT擦写电压可以更小。为什么?
CT和浮栅晶体管对比图如图3-23所示,虽然这只是个示意图,但CT实际上确实比浮栅晶体管更矮:控制极到衬底之间的距离短
。因此,要产生相同的隧道电场,加在控制极的电压可以更小(E=U/d)。更小的写电压,使得隧道氧化层压力更小,因此绝缘氧化层损耗也慢。当然,还会更省电
图3-23 CT和浮栅晶体管对比 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
CT相比浮栅晶体管有很多优势:
- 对隧道氧化层要求不是那么苛刻
- 更小的存储单元间距
- 隧道氧化层磨损更慢
- 更节能
- 工艺实现容易
- 可以在更小的尺寸上实现
- 但是,CT也不能完胜。在Read Disturb和Data Retention方面,CT闪存就不如浮栅极闪存
CT技术现在主要是应用在3D闪存上。如今除了美光使用浮栅极技术外,其他主流闪存商家都是用CT技术来制造3D闪存
3.1.7 3D XPoint
闪存用在固态硬盘上,使用SATA接口,要想更快可用SAS接口,甚至PCIe接口。其实最快的还是DRAM,可以支持字节级别的访问,但是DRAM上的数据如果不通电,马上就丢了。所以现代计算机同时使用DRAM和闪存存储数据
图3-24 新型存储器容量增长 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
图3-24所示是各种新型存储器的容量成长之路,目前比较成熟的是相变存储器PCM——PRAM
- 忆阻器:ReRAM
- 铁电存储器:FeRAM
- 磁阻RAM:MRAM
- 相变存储器:PRAM,PCM
- 导电桥接RAM:cbRAM,又称可编程金属元存储器PMC
- SONOS RAM:Silicon-Oxide-Nitride-Oxide-Silicon
- 导电金属氧化物存储器:CMOx
所谓的相变存储器,就是在原子级别发生了相变,利用这个来存储数据
。就像是玻璃经过相变成了晶体。这还是很好理解的,想想我们最常见的水,液体的时候形状不定,但是温度降低后,就发生相变,成为了固体——雪,雪就是晶体,有着稳定的晶体结构。如图3-25所示,左边是玻璃态,右边是晶体态,明显,晶体态更整齐
图3-25 相变晶体原理 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
物理原理讲完了,下面开始讲电气原理。不像DRAM里面有晶体管,PCM其实是通过一种微小的电阻作用使得玻璃融化,相变为晶体。技术日新月异,现在人类已经能高效地控制这种物理作用了,曾经写需要几微秒,读需要几纳秒,现在PCM已经能到皮秒的量级了,也就是纳秒的1000分之一,即10-12 秒
表3-3 几种存储器特性对比 表格来源于《深入浅出SSD:固态存储核心技术、原理与实战》
来看看PCM和常见存储器的对比。表3-3中PCM的数据还在优化,最新的器件读写速度比表格里面快多了,里面的速度不是总线数据传输速度,而是存储介质的读写速度。这个表格的数据比较旧,主要还是对存储器在功耗、寿命、功能等方面进行比较
。可以看出,PCM的特点:
- 掉电数据不丢失
- 可以按照字节访问
- 软件简单
- 写之前不需要擦除操作
- 功耗低,和闪存差不多
- 读写速度快
- 寿命远长于闪存
图3-27所示是一个PCM存储单元,读的时候只要测量GST上面金属节点的电压就知道了,晶体态时电阻低、电压低,无定形态时电阻高、电压高。其实测电阻就是测电压,假如底部接地,那么低阻时顶点电压低(和底部导通),可以表示“0”;高阻时隔断,顶点电压高,可以表示“1”
图3-27 PCM存储单元 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
图3-27所示中,柱子就是加热器,通过电流之后加热GST,导致它发生相变,不过在不同的温度下,经过一定时间,相变的结果不一样。如图3-28所示,高温Tm下短脉冲加热从晶体态变成无定形态,较高温Tx长脉冲加热时从无定形态变成晶体态。图3-29所示是读写的温度时间控制波形
图3-28 不同温度脉冲对相变的影响 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
图3-29 读写操作通过温度时间控制完成功能 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
闪存里面有Bitline和WordLine,通过这两个组成的矩阵来管理上亿个存储单元
。图3-30所示是PCM的Bitline和WordLine结构,通过两条线可以精确控制每一个单元。写的时候控制电流的大小来加热完成相变;读的时候通过测量Bitline的电压值就能知道是低阻还是高阻,从而获得0、1值
图3-30 PCM组织结构 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3.2 闪存实战指南
3.2.1 异步时序
闪存接口有同步异步之分,一般来说,异步传输速率慢,同步传输速率快
- 异步接口没有时钟,每个数据读由一次RE_n信号触发,每个数据写由一次WE_n信号触发
- 同步接口有一个时钟信号,数据读写和时钟同步
ONFI2.3协议规定的一个典型的闪存芯片管脚图,见图3-31。这个芯片对外输出数据位宽为8bit,Ssync是同步,Async是异步
图3-31 闪存芯片管脚图 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
比较一下两种接口下的管脚定义,大部分都是一样的,区别就是表3-4中所示的四类信号
表3-4 同步异步管脚定义对比 表格来源于《深入浅出SSD:固态存储核心技术、原理与实战》
先来看看异步数据写入的时序图,见图3-32
图3-32 异步写数据时序图 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
上图中有5个信号:
- CLE:Command Latch Enable,CLE有效时IOx发送命令
- CE_n:Chip Enable,这个信号用来选通一个逻辑上的芯片——Target。为什么说是逻辑上的芯片?因为物理芯片里面封装了很多Target,每个Target都是完全独立的,只是有可能共享数据信号,所以通过CE_n来选择当前数据传输的是哪个Target,业内一般把Target叫作CE
- WE_n:Write Enable,写使能,这个信号是用户发给闪存的,有效时意味着用户发过来的写数据可以采样了
- ALE:Address Latch Enable,ALE有效时IOx发送地址
- IOx:数据总线
同时有很多时间参数,这里只介绍几个关键的参数:
- tWP :WE_n低电平脉冲的宽度
- tWH :WE_n高电平保持时间
- tWC :tWP与tWH合起来一个周期的时间
- tDS :数据建立时间,意思就是8bit数据要都达到稳定状态,最多这么长时间
- tDH :数据稳定时间,这段时间里数据信号稳定,可以来采样
时序图3-32,数据写入的时候,数据总线不能传输地址和命令,所以ALE和CLE无效。这个Target有数据传输,所以CE_n有效。每一个WE_n周期对应一次有效的数据传输
图3-33 异步读数据时序图 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
图3-33所示的异步数据读出时序,其中多了两个信号
- RE_n:读使能。这个信号是用户发给闪存的,每发一个读使能,闪存就在数据总线上准备好数据,等用户采样
- R/B_n:Ready/Busy。闪存正在进行内部读的时候,Busy_n有效,当操作完成且数据准备好之后,Ready有效,用户可以来读了
所以,用户向闪存发了读命令之后,Ready信号拉高,意味着数据准备好了。接着,用户发RE_n信号去读数据,每个RE_n周期,闪存发送一个有效数据到数据总线上,供用户采样,如图3-33所示
3.2.2 同步时序
同步时序最重要的两个信号是时钟CLK和DQS
。现在的闪存基本都采用了DDR(Double Data Rate)技术,就是说每个时钟周期传输两拨数据。图3-34是同步模式下的数据写入时序图,介绍一下几个信号
- CLK:时钟。时钟信号由用户产生,在时钟信号的上升沿和下降沿都有数据被触发,实现DDR,意味着100MHz的时钟频率数据传输速率是200MT/s
- W/R_n:Write/Read_n。写的时候高电平,读的时候低电平
- DQS:Data Strobe。DQS用来区分出每个数据传输周期,便于接收方准确接收数据。读数据时,DQS由闪存产生,DQS上下沿和数据对齐。写数据时,DQS由用户产生,DQS中间对应数据的中间稳定区域。所以,DQS可以看成数据的同步信号
- DQ[7:0]:数据总线
图3-34 同步写数据时序图 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
几个关键的时间参数:
- tCALS :CLE、W/R_n和ALE的建立时间
- tDQSS :数据输入到第一个DQS跳变沿的时间
了解了各种信号和时间参数,我们就能看懂上面的数据写入时序图。CLE和ALE同时有效之后的第一个CLK上升沿,数据开始准备并输出。经过tDQSS时间后,DQS开始跳变,并且跳变沿位于DQ数据信号的稳定位置。之后每半个时钟周期,输出一组数据
再来看看下面的读数据时序图图3-35,和写入差不多,只不过W/R_n信号是低电平,同时DQS跳变沿和数据上升沿同步
图3-35 同步读数据时序图 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3.2.3 闪存命令集
固态硬盘主控是通过一系列闪存命令与闪存进行通信的。每款闪存芯片都定义了其支持的命令,以ONFI 2.3协议为例
,它定义的命令如表3-5所示。用户要使用这些功能时发送命令即可,比如读数据,就发送00h~30h,不过具体命令时序和使用方式要看专门的定义
表3-5 闪存命令集 表格来源于《深入浅出SSD:固态存储核心技术、原理与实战》
下面介绍一下几个比较常用的命令:
- Read:00~30h,读数据。读一个Page数据用这个命令
- Read Multi-plane:00~32h,同时读多个Plane的数据。多个Plane各读1个Page
- Change Read Column:05h~E0h,修改读列地址。Read命令从闪存介质读出一个Page的数据到闪存芯片里面的缓存,一个Page一般是8KB或者16KB,但是用户不一定需要所有数据,所以通过这个命令来修改传输数据的偏移地址。从某个Page内偏移地址开始进行数据传输
- Block Erase:60h~D0h,擦除一个Block
- Read Status:70h,查看最近一次操作的结果是成功还是失败
- Read Status Enhanced:78h,它和70h有什么区别?它是用在Multi-LUN操作的状态查看,可以指定查看哪个LUN的状态
- Page Program:80h~10h,写一个Page数据
- Page Program Multi-plane:80h~11h,同时写多个Plane的数据,写性能可以翻几倍
- Read ID:90h,可以读到在JEDEC注册的Manufacturer ID和Device ID
- Read Parameter Page:ECh,可以读到这个CE的各种配置参数,比如支持ONFI的哪个版本,是否支持Multi-plane,异步或同步时序模式是哪一种等
- Get Features/Set Features:EEh/EFh,这两个命令给用户提供设定一些参数的接口,比如设置同步异步或者选择传输速率
3.2.4 闪存寻址
图3-36所示是一个Target,就是之前说的一个可以独立工作的逻辑芯片。它包含2个LUN,每个LUN有2个Plane,每个Plane有很多Block,每个Block又有很多Page
图3-36 闪存内部架构 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
为了访问这些资源,闪存里面使用了行地址(Row Address)和列地址(Column Address)
。列地址就是Page内部的偏移地址。ONFI协议中,行地址的定义如图3-37所示,从高位到低位依次为LUN、Block和Page地址,至于具体位宽,则和每个芯片的容量有关
图3-37 闪存地址划分 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
如图3-38所示,Plane是在Block地址的最低位。ONFI要求Multi-plane操作的时候,每个Plane的Page地址必须相同,Block地址不同的闪存要求不一样。比如Intel/Micron和东芝的闪存,在Multi-plane操作时,可以是不同的Block,但是三星的闪存,要求几个Plane操作的Block地址要相同。因为占的是Block地址的最低几位,所以进行Multi-Plane的时候,Plane一般有奇偶之分
图3-38 Plane地址位 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3.2.5 读、写、擦时序
读时序 如图3-39所示,在用户发送命令00~30h之间传输了所读的地址,包括2个列地址和3个行地址。发完命令后,SR[6](Status Register,状态寄存器,bit 6)状态转为Busy,经过一段时间之后SR[6]状态转为Ready,数据就可以读了
图3-39 读时序 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
写时序 如图3-40所示,用户发了80h命令之后,发送写地址,一般列地址是0,因为要把一个Page写满,如果不从头开始写满一个Page,往往会导致数据出错。发完地址tADL时间之后,开始传输数据到闪存的缓存。数据传完,发送命令10h,闪存芯片开始向介质写入数据,SR[6]状态为Busy,在写操作完成后状态转为Ready
图3-40 写时序 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
擦除比较简单,如图3-41所示,在命令60h和D0h之间发送LUN和Block行地址即可,因为擦除是以Block为单位
图3-41 擦除时序 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3.2.6 ONFI与Toggle协议之争
前面讲的主要都是ONFI。事实上,闪存不只涉及ONFI协议,还有Toggle协议
,对比一下管脚定义,其实区别也没那么大,见图3-42
图3-42 ONFI和Toggle管脚定义对比 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
Toggle同步模式下不用时钟,写数据用DQS差分信号跳变沿触发,读数据根据主控发的REN差分信号跳变沿发送读请求,DQS跳变沿输出数据
3.3 闪存特性
3.3.1 闪存存在的问题
1 闪存坏块
闪存块(Block)具有一定的寿命,当一个闪存块接近或者超出其最大擦写次数时,可能导致存储单元永久性损伤,如图3-43,不能再使用。随着闪存工艺不断向前发展,晶体管的尺寸越来越小,擦写次数也变得越来越少
图3-43 闪存损坏状态 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
闪存中的存储单元先天就有一些是坏的,或者说是不稳定的。并且随着闪存的不断使用,坏的存储单元越来越多。所以,用户写入闪存的数据,必须要有ECC纠错码保护
,这样即使其中的一些比特发生反转,读取的时候也能通过ECC纠正过来。但若出错的比特数超过纠错能力范围,数据就会丢失,对这样的闪存块,应该弃之不再使用
闪存先天有坏块,也就是说有出厂坏块
。并且,用户在使用过程中会新添坏块,所以必须有坏块管理机制
2 读干扰
另外,还应注意读干扰(Read Disturb)问题
。从闪存读取原理来看,当你读取一个闪存页(Page)的时候,闪存块当中未被选取的闪存页的控制极都会加一个正电压,以保证未被选中的MOS管是导通的。这样问题就来了,频繁地在一个MOS管控制极加正电压,就可能导致电子被吸进浮栅极,形成轻微写,从而最终导致比特翻转
,如图3-44所示。但是,这不是永久性损伤,重新擦除闪存块还能正常使用。要注意的是,读干扰影响的是同一个闪存块中的其他闪存页,而非读取的闪存页本身
图3-44 读干扰原理 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3 写干扰
除了读干扰会导致比特翻转,写干扰(Program Disturb)也会导致比特翻转
。还是要回到闪存内部的写原理上来,如图3-45所示
图3-45 写干扰原理 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
写一个闪存页的时候,数据是0和1混合的。由于擦除过的闪存块所有的存储单元初始值是1,只有写0的时候才真正需要操作。如图3-45所示,方框里的单元是写0,即需要写的,圆圈里的单元的代表写1,并不需要写操作。这里把方框里的单元称为Programmed Cells,圆圈里的单元称为Stressed Cells。写某个闪存页的时候,我们是在其Wordline控制极加一个正电压,图3-47中是20V。Programmed Cells所在的String是接地的;不需要写的单元所在的String接一个正电压,图3-47中为10V。这样最终产生的后果是,Stressed Cell也会被轻微写。与读干扰不同的是,写干扰影响的不仅是同一个闪存块当中的其他闪存页,自身闪存页也会受到影响。相同的是,都会因不期望的轻微写导致比特翻转,都会产生非永久性损伤,经擦除后,闪存块还能再次使用
4 存储单元间的耦合
还有一个问题,就是存储单元之间的耦合影响(Cell-to-Cell interference)。前面提到,浮栅极闪存存储电荷的是导体,因此存储单元之间存在耦合电容,这会使存储单元内的电荷发生意外变化,最终导致数据读取错误。
5 电荷泄漏
存储在闪存存储单元的电荷,如果长期不使用,会发生电荷泄漏。这同样会导致非永久性损伤,擦除后闪存块还能使用
3.3.2 寿命
图3-46这张0和1的分布图,横轴是电压,纵轴是存储单元的数量
。0的区域表示被写过的那些单元电压分布区间,1的区域是被擦过的那些单元电压分布区间。所以说,如果要正确地读到数据,0和1这两个区间要尽量分割清楚,保证它们的主峰之间有足够远的距离。除此之外,阈值电压也不能太偏
图3-46 SLC电压分布 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
要读的单元栅极加0V电压,这时擦过的晶体管阈值电压是-Vt ,导通,沟道有电流,Bitline端的传感器能够检测到,读到“1”。而经过写的晶体管阈值电压是+Vt ,不导通,沟道电流很小,读为“0”。随着擦写次数的增加,会发生3种故障:
- 擦过的晶体管阈值电压变大,从-Vt 向0V靠近,这样读的时候沟道电流变小,传感器检测不到,读出错
- 写过的晶体管阈值电压变小,从+Vt 向0V靠近,有可能会被误检测为擦过的状态
- 写过的晶体管阈值电压变大,如图3-47所示,>5V,即使控制极加5V电压,它也是截止的,有可能在其他的单元读的时候,把整个Bitline都给关了
图3-47 读操作电压示例 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
浮栅晶体管对浮栅极下面的绝缘层(Tunnel氧化物)很敏感,该氧化物厚度变薄(制程不断减小导致的)或者老化(Degradation,擦写次数多了)对浮栅极里面的电荷影响很大。我们之前介绍了Charge Trap晶体管,其实随着擦写次数增多,浮栅晶体管的氧化层渐渐老化,产生不少Charge Trap,这些陷阱会吃掉电子,导致写之后,进入浮栅的电子数量会减少,最终的结局就是0和1两个区间不断靠近
如图3-48所示,上面是写后的阈值电压,下面是擦除后的阈值电压,很明显,擦除后的阈值电压在擦很多次之后显著变高。所以,一般擦除之后会做校验,方法是把所有的Wordline设为0V,再去检测每个Bitline的电流。如果某个Bitline电流是0,就意味着有个单元的擦除阈值电压接近0V,导致晶体管关断。所以这个闪存块应该标为坏块
图3-48 阈值电压变化图 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
了解了闪存寿命的原理之后,看看固态硬盘设计实践中怎么解决这个问题。一般有以下方法:
- Wear Leveling:通过磨损平衡算法,让所有的闪存块均衡擦写,避免少数闪存块先挂掉,导致固态硬盘容量下降
- 降低写放大:写放大越低,固态硬盘的磨损速度越慢
- 用更好的纠错算法:纠错能力越强,容许的出错率越高,故采用更好的纠错算法可以延长硬盘使用寿命
3.3.3 闪存测试
固态硬盘内部需要对闪存做测试,原因是:
- 闪存厂商卖给你的闪存不一定都是好的,总是有概率存在故障芯片
- 固态硬盘制造过程中有合格率问题,不能保证每个闪存芯片都焊接得完美无缺
- 固态硬盘制造商为了降低成本,会从各种渠道获得低价闪存芯片,这些芯片质量没有保障,需要固态硬盘制造商自己筛选
图3-49 BGA焊接空洞 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
图3-49所示是BGA封装的焊球X光片,可以看出里面有个空洞,导致电路信号故障。所以,固态硬盘出厂前要对每一块闪存进行测试,测试方法如下:
- 测试每个CE是否可以正常操作,比如Reset、Read ID等
- 对每个LUN、Plane进行读写测试,要考虑到一定的比特翻转率,看看写入的数据和读出差距有多大。写入数据要选择不同的数据类型,比如连续的0或者连续的1。存储器件测试有很多专用数据格式,有兴趣的读者可翻看各种论文,也可以参考著名的内存测试软件memtest的测试方法
3.3.4 MLC使用特性
对MLC来说,擦除一个闪存块的时间大概是几毫秒。闪存的读写则是以闪存页为基本单元的。一个闪存页大小主要有4KB、8KB、16KB几种。对MLC或者TLC来说,写一个闪存块当中的闪存页,应该顺序写Page0、Page1、Page2、Page3……禁止随机写入,比如Page2、Page3、Page5、Page0……为什么?原因主要有二:
- 一个存储单元包含两个闪存页数据,要先写Lower Page,再写Upper Page
- 相邻单元之间有耦合电容,工艺上要求后面的闪存页写操作时前面的闪存页已经写过
但对读来说,没有这个限制。SLC也没有这个限制
MLC有其特有的一些问题:
- 正如前面提到的,MLC最大擦写次数会变小。这样,就更需要Wear Leveling技术来保证整个存储介质的使用寿命
- 对MLC来说,一个存储单元存储了2bit的数据,对应着两个Page:Lower Page和Upper Page。假设Lower Page先写,然后在写Upper Page的过程中,由于改变了整个单元的状态,如果这个时候掉电,那么之前写入的Lower Page数据也会丢失。也就是说,写一个闪存页失败,可能会导致另外一个闪存页的数据损坏
- 前面说到,不能随机写。不能先写Upper Page,然后再写Lower Page,这点就限制了我们不能随意地写
- 写Lower Page时间短,写Upper Page时间长,所以会看到有些闪存页写入速度快,有些闪存页写入速度慢
两条存储行业的规矩:
- 一般在没有盘内缓存的情况下,我们认为写到硬盘的数据如果已经返回写成功,那么这个数据就是安全的。数据写到物理介质上就可以放心了
- 如果数据在写的过程中发生了异常掉电,那么该数据即使丢了也可以接受,毕竟用户认为数据还没写完
但是Lower Page数据损坏打破了这个常识:尽管已经成功写到了盘里,但是假如该数据位于Lower Page上,很不幸的是,恰好过了不久,后面有数据写对应的Upper Page时发生了异常掉电,那就会导致Lower Page上已经写好的数据也被破坏。也就是说,固态硬盘正在写的时候,如果发生了异常掉电,有可能会丢失之前写入的数据
消费级固态硬盘研发工程师采用了很多技术来防止这种情况发生
- 只写Lower Page:成本比较高,只适合关键数据和土豪
- Lower Page和Upper Page打包写:每次数据量多凑点,争取Lower Page和Upper Page都写(需要闪存支持One Pass Programming)
- 定期填充Upper Page:消费级固态硬盘要求省电,所以会频繁进入省电模式,可能安静个几百毫秒就自动休眠了。休眠之前检查是不是有Lower Page写过了,有Upper Page还没写的情况,就把Upper Page也写一下
- 写Lower Page数据时,备份该数据到别的闪存块上,直到它对应的Upper Page数据写完。这样即使掉电导致Lower Page数据丢失,也可使用备份数据进行还原
- MLC闪存块当SLC块使用,强迫用户数据写到SLC块,随后以垃圾回收的方式把数据从SLC闪存块搬到MLC闪存块
3.3.5 读干扰
读干扰为什么会导致性能下降?下面将解释原因。
读干扰会导致浮栅极进入电子。由于有额外的电子进入,会导致晶体管阈值电压右移(Data Retention问题导致阈值电压左移),如图3-50所示
图3-50 阈值电压偏移 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
由于晶体管阈值电压偷偷发生了变化(变大了),闪存内部逻辑如果还是按照之前的参考电压加在控制极上然后去判断数据,肯定会发生误判,也就是读到错误的数据
阈值电压右移的速度,也就是读干扰影响数据的程度,一方面与读该闪存块上数据的次数有关,读得越多,右移越多,影响越大;一方面还跟闪存块的擦除次数有关,擦写次数越多,绝缘效果越差,电子进入浮栅极就越容易,读干扰的影响也就越大
闪存使用者如何应对读干扰呢?
一般做法是记录每个闪存块读的次数,赶在这个数值达到阈值(闪存厂家提供)之前,把闪存块上所有的数据刷新一遍(读出来,擦除,然后写回),或者把数据搬到别的地方。回到开头那个问题,读干扰为什么会导致固态硬盘性能下降?就是因为一个闪存块上的数据读的次数太多了,固件需要赶在数据出错前,把整个闪存块数据刷新或者搬移,避免数据出错,但这会占用底层带宽,导致主控读写性能下降
有人研究发现,减小Vpass (加在没有被读的那个Wordline上的电压)可以缓解读干扰。因为Vpass 变小,电场减弱,吸入电子的能力减弱,自然能缓解读干扰的影响。但是,一方面,现在闪存厂商都没有开放调Vpass 电压的接口给用户;另一方面,过低的Vpass 可能导致读失败。该方法只能起到缓解作用,不能从源头上杜绝读干扰的影响
3.3.6 闪存数据保存期
无论用任何存储技术,存储的数据都不能永远保存,都会有个保存时间。闪存中,数据保存时间的问题叫作Data Retention
。到了期限,数据就会出错,标志就是从闪存读出来的数据无法用ECC纠错成功。我们知道闪存一般有以下错误:
电气问题
:比如虚焊或者芯片故障,导致正常命令无法执行或者数据错误率异常高。这种问题在闪存或固态硬盘出厂测试时就会被发现读、写、擦失败
:基本命令执行失败,通过状态位可以读到结果。这些问题在芯片使用过程中也有可能发生,但是概率非常小ECC纠错失败
:其实就是数据错误率太高,超过了纠错算法的纠错能力。Data Retention是其中一个元凶
闪存存储的机理是通过量子隧道效应,电子跃迁到浮栅层并停留在那里。随着时间的流逝,电子还是有一定概率离开浮栅层,回到沟道里面,离开的电子多了就有可能导致写过的单元读出来的结果跟擦除过的一样,也就是说数据出错了。Data Retention和浮栅层下面的氧化层厚度有关,毕竟氧化层越厚,电子离开的概率越小。有研究表明,氧化层厚度如果是4.5nm,那么理论上数据可以保存10年
图3-52是闪存基本单元浮栅晶体管的截面图。最上面是控制层,中间是浮栅层,浮栅上面是多晶硅氧化层,下面是隧道氧化层。控制电压很高的时候,会产生量子隧穿效应,电子从衬底Substrate出发,穿过隧道氧化层,进入浮栅保存起来,就完成了写操作。反之,在控制层加很强的负电压,电子就从浮栅量子隧穿,回到衬底,这个操作叫作擦除。不过,控制层不加电压的时候,氧化层依然会产生一个电场,叫作本征电场,它是由浮栅里面的电子产生的。在这个电场的作用下,电子会从浮栅慢慢泄露,泄漏的多了,数据就会发生错误。从写入操作到电子慢慢泄漏,直到数据出错,这个期限叫作数据保存期,在SLC时代,这个时间很久,有好几年,但是到了TLC时代,不到一年,有的只有几个月
图3-52 浮栅晶体管的本征电场和TAT效应 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
那为什么闪存用得越久,数据保存时间越短呢?这要怪一个效应:Trap-assisted tunneling(TAT)。如图3-52(b)所示,我们知道隧道氧化层是绝缘的,但是随着闪存的使用,历经很多次的擦写,氧化层和浮栅层的爱情终于要走到终点了,因为经过这么年风风雨雨,氧化层老了,有不少通过它的电荷被滞留下来,绝缘体有了导电性。这样,电荷从浮栅跑得就更快了。所以,闪存擦写次数越多,数据保存时间就越短。到最后快到额定擦写次数的时候,比如3000次,刚写的数据就很容易出错
不过,氧化层并不总是在截留电荷,有时候它拦截的电荷也会离开,叫作Charge de-trapping。只不过离开的既有正电荷,也有负电荷,所以对阈值电压的影响是双向的
怎样解决Data Retention的问题呢?一般固态硬盘会采用Read Scrub技术,或者叫数据巡检、扫描重写技术等
Sun公司开发的大名鼎鼎的ZFS(Zettabyte File System)文件系统
。ZFS的设计者发现,有很多用户的数据长期没有读过,更别说被重写了。即使是数据读取频繁的数据库应用,也存在长期不被访问的数据,它们寂寞地躲在角落里,长期无人问津。但是,不管什么类型的磁盘,总是会有概率发生比特翻转,导致数据出错,等你需要这份数据的时候,错误有可能比较严重,根本恢复不出原样。在ZFS文件系统中,每个数据块都有自己的校验码Checksum,只要被读了,就可以通过Checksum发现数据是否出错,提前对出错的数据块进行纠错。所以,ZFS提供了一个功能叫Scrub,对文件系统进行扫描,提前发现那些出错的数据,并纠错重写
固态硬盘的Read Scrub技术跟ZFS类似,在固态硬盘不忙的时候,按照一定的算法,扫描全盘,如果发现某个闪存页翻转比特数量超过一定阈值,就重写数据到新的地方。这样做的好处是避免数据放太久从而导致比特翻转数量超过ECC算法的纠错能力,这样能减少ECC不可纠错误
3.4 闪存数据完整性
闪存的一个特性就是随着闪存的使用以及数据存储时间的变长,存储在闪存里面的数据容易发生比特翻转,出现随机性错误。这个问题随着闪存制程的变小越发严重。因此,使用闪存作为存储介质的固态硬盘,需要采用一些数据完整性的技术来确保用户数据可靠不丢失
。常见的技术有:
- ECC纠错
- RAID数据恢复
- 重读(Read Retry)
- 扫描重写技术(Read Scrub)
- 数据随机化
3.4.1 读错误来源
闪存数据发生错误,主要有以下几个原因:
1 擦写次数增多
随着闪存块擦写次数增多,氧化层逐渐老化,电子进出存储单元越来越容易
,因此存储在存储单元的电荷容易发生异常,导致数据读错误,如图3-53所示
图3-53 同一个闪存芯片内不同闪存块在不同寿命时的RBER 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
2 Data Retention
随着时间的推移,存储在存储单元的电子会流失,整个阈值电压分布向左移动,导致读数据的时候发生误判
,如图3-54所示
图3-54 阈值电压分布随着时间偏移 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
3 读干扰
读一个Wordline数据时,需要施加Vpass 电压在其他Wordline上,导致其他闪存页发生轻微写
。如果读的次数过多,轻微写累积起来就会使阈值电压分布发生右移,导致读数据时候发生误判,即读数据错误,如图3-55所示
图3-55 读干扰后阈值电压偏移 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
4 存储单元之间干扰
由于存储电子的浮栅极是导体,两个导体之间构成电容,一个存储单元电荷的变化会导致其他存储单元电荷变化,而受影响最大的就是与它相邻的存储单元
。周围的单元是不同的状态时,中心单元的阈值电压是不一样的,如图3-56所示
图3-56 周围单元不同状态时的阈值电压分布 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
5 写错误
写错误一般发生在MLC或者TLC 2-pass(先写Lower Page,然后再写Upper Page)写过程中
。写Upper Page的时候,它是基于之前Lower Page的状态,然后再写每个存储单元到目标状态。如果写Upper Page的时候,Lower Page数据已经出错(注意写Upper的时候,Lower Page的数据是不会经过控制器ECC纠错的,写过程发生在闪存内部),就会导致存储单元写到一个不期望的状态,即发生写错误
TLC 1-pass program则没有这个问题,因为Lower Page和Upper Page是一次性同时写入,写Upper Page不依赖于Lower Page数据。当然,如果一开始擦除状态就不对,那么还是会发生写错误
3.4.2 重读
闪存有几种缺陷,对于电压分布平移的问题尚可想办法恢复,因为数据之间还是清楚隔离的
图3-57以MLC为例,每个存储单元存储两个比特的数据,一共有四种状态。当四种状态的电压分布发生平移后,如果还是采用之前的参考电压去读取的话,就可能会出现读取数据失败的情况。使用重读技术后,我们可以不断改变参考电压,来尝试找到可以读出数据的电压点,直到正确读出数据。理论上,只要这四种状态的电压分布没有发生重叠,就可以通过重读恢复数据
图3-57 平移后电压分布 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
还有更复杂的重读,叫作Advanced Read Retry。先读附近的单元确定状态,再用不同参考电压读两次要读的单元,根据附近单元数据决定选择哪一个
3.4.3 ECC纠错码
固态硬盘控制器上面都有ECC纠错模块,有些闪存内部也集成了ECC纠错模块
。常用闪存ECC纠错算法有:
- BCH(Bose、Ray-Chaudhuri与Hocquenghem三位大神名字的首字母)
- LDPC(Low Density Parity Check Code)
- 目前市面上很多固态硬盘控制器上采用的是BCH,但采用LDPC正成为一种趋势
用户数据最终都是写在闪存页(Page)上面,闪存页空间除了用户空间,还有额外的预留空间,这部分空间可以用来写ECC校验数据
。用户数据大小固定,需要更强的纠错能力,这就需要更多的ECC空间。因此,纠错强度受限于闪存页的预留空间。越多的预留空间就能提供越强的ECC纠错能力
目前绝大多数固态硬盘都采用静态ECC纠错方案
,ECC纠错单元(用户数据)和ECC校验数据大小在整个固态硬盘生命周期都是固定的,也就是说纠错能力始终保持不变。由于闪存在使用初期内部发生比特翻转的概率小,而随着闪存的使用,出错概率逐渐变大,因此有些固态硬盘开始采用动态ECC纠错方案:开始使用更少的纠错码,这样在闪存的页里面可以存储更多的用户数据;随着固态硬盘的使用,纠错能力需要加强,用户数据在闪存页里面占的比例变小,纠错码所占比例变大。动态ECC纠错方案就是随着固态硬盘的使用,动态调整其ECC纠错能力。动态ECC纠错有什么好处?如果开始使用更少的ECC校验数据,那么每个页能写入的用户数据就更多,相当于固态硬盘拥有更多的OP(Over Provisioning,预留空间),减小了写放大;同时,在数据从控制器写入或者读取闪存的通道上,用户数据越多,ECC校验数据越小,带宽利用率高
其实,动态ECC的优势不仅体现在随着时间的推移ECC纠错能力会发生变化,而且体现在固态硬盘的闪存位置上每个Die甚至每个闪存页有不同的纠错能力
。在固态硬盘闪存阵列里,有些Die可能质量好点,有些Die可能质量差点,好的Die可以用更少的ECC纠错代码;相反,差的Die就需要更强的ECC纠错。对MLC来说,Lower Page相对Upper Page更稳定一些,因此可以使用弱一些的ECC保护;相反,Upper Page则需要更强的ECC保护
3.4.4 RAID
当闪存中数据比特发生翻转的个数超出ECC纠错能力范围后,ECC纠错就无能为力了
。在一些企业级,以及越来越多的消费级固态硬盘上,都在使用RAID(Redundant Arrays of Independent Disks)纠错技术
。类似磁盘阵列,固态硬盘内部本质就是一个闪存阵列,所以可以借鉴磁盘阵列技术来确保数据的完整性。固态硬盘的RAID一般采用RAID 5
以图3-58所示为例,某个固态硬盘的闪存阵列由5个Die构成,Die 0~3存储的是用户数据,Die P则存储校验数据,为Die 0、Die 1、Die 2和Die 3数据之“异或”。假设Die 1上出现ECC不可纠的错误,那么可以通过读取Die 0、Die 2、Die 3和Die P对应位置上的数据,然后做“异或”,就能恢复出Die 1上的数据
图3-58 RAID 5 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
采用RAID 5的固态硬盘只能恢复单个ECC不可纠的数据,如果出现多个ECC不可纠的错误,它也无能为力
由于采用了冗余纠错技术,它需要额外的空间来存储冗余数据(校验数据),因此必然会牺牲用户空间
图3-59 传统RAID 5 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
如图3-59所示,对传统磁盘RAID 5来说,数据按照条带来写。比如一个磁盘组有4个磁盘,其中一个是校验盘,条带大小为48KB,被拆成三个16KB写到三个盘上,最后一盘是校验数据——三个16KB数据的“异或”值。修改任何一个16KB数据块,都需要重新生成校验数据,并更新校验数据块
一般固态硬盘内部的RAID是由不同Die上的Block组成的阵列,绑定在一起:同时被写,同时被垃圾回收,同时被擦除。好处是稳定,缺点是不够灵活。固态硬盘内部的RAID Block太大了,不太灵活,使得空间被浪费。比如进入休眠之前必须把没写完的条带剩余空间用随机数填满,增加写放大。RAID Block个头大,效率就降低了,有时RAID阵列中某个Block有效数据还很多,但是因为整个阵列有效数据少,不得不整体垃圾回收
3.4.5 数据随机化
在写闪存的时候,如果只是简单地把数据加纠错码写进去,那会遇到很多错误,有时候是写失败,有时候是读出来的数据错误率太高。为什么?因为数据没有随机化
。闪存是通过控制栅施加电压来存储数据的,对某些写入的数据样式很敏感,不断地输入全0或者全1,很容易导致闪存内部电量不均衡,从而造成信号抗干扰性下降,导致这些数据在闪存中可靠性变差
图3-60 没有随机化(虚线)和随机化(实线)电压分布对比 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
从物理原理上看,闪存写入数据需要做随机化有两个原因:
- 1)
让0和1的分布充分隔离
。 图3-60是MLC内部的各个存储状态电压分布图,实线是随机化后的分布,每个状态都充分隔离;虚线是没有随机化的分布,有些状态的分布明显变宽了,随着时间流逝或者寿命缩短,这些分布会和周边发生交集,导致读数据出错 - 2)
降低相邻单元之间的耦合电压产生的影响
。 如3-61所示,对一个单元影响最大的是其周围的4个直接相邻的单元,这些单元的状态直接影响到中间单元的阈值电压
图3-61 周围单元对中心单元的影响 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
因此,固态硬盘控制器或者闪存内部都有数据随机化模块,它对用户写入的数据加入扰码,使最终写入闪存的数据0和1基本保持均衡,减小数据发生比特翻转的概率。一般闪存厂商会推荐使用AES加密算法实现数据随机化
数据随机化在数据最终写到闪存之前,ECC加校验数据之后,数据流如图3-62所示,数据随机化也可以在ECC校验之前做,两者顺序可交换
图3-62 数据随机化数据流 图片来源于《深入浅出SSD:固态存储核心技术、原理与实战》
致谢《深入浅出SSD:固态存储核心技术、原理与实战》
希望本文对大家有帮助,上文若有不妥之处,欢迎指正
分享决定高度,学习拉开差距