说说NANDFLASH以及相关ECC校验方法

说说NANDFLASH以及相关ECC校验⽅法
Flash名称的由来,Flash的擦除操作是以block块为单位的,与此相对应的是其他很多存储设备,是以bit位为最⼩读取/写⼊的单位,Flash是⼀次性地擦除整个块:在发送⼀个擦除命令后,⼀次性地将⼀个block,常见的块的⼤⼩是128KB/256KB,全部擦除为1,也就是⾥⾯的内容全部都是0xFF了,由于是⼀下⼦就擦除了,相对来说,擦除⽤的时间很短,可以⽤⼀闪⽽过来形容,所以,叫做Flash Memory。所以⼀般将Flash翻译为(快速)闪存。
NAND Flash 在嵌⼊式系统中有着⼴泛的应⽤,负载平均和坏块管理是与之相关的两个核⼼议题。Uboot 和 Linux 系统对 NAND 的操作都封装了对这两个问题的处理⽅法。本⽂⾸先讲述Nandflash基础知识,然后介绍现有的⼏类坏块管理(BBM)⽅法,通过分析典型嵌⼊式系统的 NAND 存储表,指出了轻量级管理⽅法的优势所在,分析了当前⼴泛使⽤的轻量级管理⽅法,指出其缺陷所在并详细说明了改进⽅法。基础知识
Flash的硬件实现机制
Flash的内部存储是MOSFET,⾥⾯有个悬浮门(Floating Gate),是真正存储数据的单元。
在Flash之前,紫外线可擦除(uv-erasable)的EPROM,就已经采⽤了Floating Gate存储数据这⼀技术了。
典型的Flash内存物理结构
数据在Flash内存单元中是以电荷(electrical charge) 形式存储的。存储电荷的多少,取决于图中的外部门(external gate)所被施加的电压,其控制了是向存储单元中冲⼊电荷还是使其释放电荷。⽽数据的表⽰,以所存储的电荷的电压是否超过⼀个特定的阈值Vth来表⽰,因此,Flash的存储单元的默认值,不是0(其他常见的存储设备,⽐如硬盘灯,默认值为0),⽽是1,⽽如果将电荷释放掉,电压降低到⼀定程度,表述数字0。
NandFlash的简介
Nand flash成本相对低,说⽩了就是便宜,缺点是使⽤中数据读写容易出错,所以⼀般都需要有对应的软件或者硬件的数据校验算法,统称为ECC。但优点是,相对来说容量⽐较⼤,现在常见的Nand Flash都是1GB,2GB,更⼤的8GB的都有了,相对来说,价格便宜,因此适合⽤来存储⼤量的数据。其在嵌⼊式系统中的作⽤,相当于PC上的硬盘,⽤于存储⼤量数据。
SLC和MLC
Nand Flash按照内部存储数据单元的电压的不同层次,也就是单个内存单元中,是存储1位数据,还是多位数据,可以分为SLC和MLC。那么软件如何识别系统上使⽤过的SLC还是MLC呢?
Nand Flash设计中,有个命令叫做Read ID,读取ID,读取好⼏个字节,⼀般最少是4个,新的芯⽚,⽀持5个甚⾄更多,从这些字节中,可以解析出很多相关的信息,⽐如此Nand Flash内部是⼏个芯⽚(chip)所组成的,每个chip包含了⼏⽚(Plane),每⼀⽚中的页⼤⼩,块⼤⼩,等等。在这些信息中,其中有⼀个,就是识别此flash是SLC还是MLC。
oob / Redundant Area / Spare Area
每⼀个页,对应还有⼀块区域,叫做空闲区域(spare area)/冗余区域(redundant area),⽽Linux系统中,⼀般叫做OOB(Out Of Band),这个区域,是最初基于Nand Flash的硬件特性:数据在读写时候相对容易错误,所以为了保证数据的正确性,必须要有对应的检测和纠错机制,此机制被叫做EDC(Error Detection Code)/ECC(Error Code Correction, 或者 Error Checking and Correcting),所以设计了多余的区域,⽤于放置数据的校验值。
Oob的读写操作,⼀般是随着页的操作⼀起完成的,即读写页的时候,对应地就读写了oob。
关于oob具体⽤途,总结起来有:
1. 标记是否是坏快
2. 存储ECC数据
3. 存储⼀些和⽂件系统相关的数据。如jffs2就会⽤到这些空间存储⼀些特定信息,⽽yaffs2⽂件系统,会在oob中,存放很多和⾃⼰⽂件
系统相关的信息。
Bad Block Management坏块管理
Nand Flash由于其物理特性,只有有限的擦写次数,超过那个次数,基本上就是坏了。在使⽤过程中,有些Nand Flash的block会出现被⽤坏了,当发现了,要及时将此block标注为坏块,不再使⽤。于此相关的管理⼯作,属于Nand Flash的坏块管理的⼀部分⼯作。
Wear-Leveling负载平衡
Nand Flash的block管理,还包括负载平衡。
正是由于Nand Flash的block,都是有⼀定寿命限制的,所以如果你每次都往同⼀个block擦除然后写⼊数据,那么那个block就很容易被⽤坏了,所以我们要去管理⼀下,将这么多次的对同⼀个block的操作,平均分布到其他⼀些block上⾯,使得在block的使⽤上,相对较平均,这样相对来说,可以更能充分利⽤Nand Flash。
ECC错误校验码磨内喷水
Nand Flash物理特性上使得其数据读写过程中会发⽣⼀定⼏率的错误,所以要有个对应的错误检测和纠正的机制,于是才有此ECC,⽤于数据错误的检测与纠正。Nand Flash的ECC,常见的算法有海明码和BCH,这类算法的实现,可以是软件也可以是硬件。不同系统,根据⾃⼰的需求,采⽤对应的软件或者是硬件。
相对来说,硬件实现这类ECC算法,肯定要⽐软件速度要快,但是多加了对应的硬件部分,所以成本相对要⾼些。如果系统对于性能要求不是很⾼,那么可以采⽤软件实现这类ECC算法,但是由于增加了数据读取和写⼊前后要做的数据错误检测和纠错,所以性能相对要降低⼀些,即Nand Flash的读取和写⼊速度相对会有所影响。
弹簧线其中,Linux中的软件实现ECC算法,即NAND_ECC_SOFT模式,就是⽤的对应的海明码。
⽽对于⽬前常见的MLC的Nand Flash来说,由于容量⽐较⼤,动辄2GB,4GB,8GB等,常⽤BCH算法。BCH算法,相对来说,算法⽐较复杂。
笔者由于⽔平有限,⽬前仍未完全搞懂BCH算法的原理。
BCH算法,通常是由对应的Nand Flash的Controller中,包含对应的硬件BCH ECC模块,实现了BCH算法,⽽作为软件⽅⾯,需要在读取数据后,写⼊数据之前,分别操作对应BCH相关的寄存器,设置成BCH模式,然后读取对应的BCH状态寄存器,得知是否有错误,和⽣成的BCH校验码,⽤于写⼊。
其具体代码是如何操作这些寄存器的,由于是和具体的硬件,具体的nand flash的controller不同⽽不同,⽆法⽤同⼀的代码。如果你是nand flash驱动开发者,⾃然会得到对应的起nand flash的controller部分的datasheet,按照⼿册说明,去操作即可。
不过,额外说明⼀下的是,关于BCH算法,往往是要从专门的做软件算法的⼚家购买的,但是Micron之前在⽹上放出⼀个免费版本的BCH 算法。
位反转
Nand Flash的位反转现象,主要是由以下⼀些原因/效应所导致:
1. 漂移效应(Drifting Effects)
漂移效应指的是,Nand Flash中cell的电压值,慢慢地变了,变的和原始值不⼀样了。
2. 编程⼲扰所产⽣的错误(Program-Disturb Errors)
此现象有时候也叫做,过度编程效应(over-program effect)。
对于某个页⾯的编程操作,即写操作,引起⾮相关的其他的页⾯的某个位跳变了。
3. 读操作⼲扰产⽣的错误(Read-Disturb Errors)
此效应是,对⼀个页进⾏数据读取操作,却使得对应的某个位的数据,产⽣了永久性的变化,即Nand Flash上的该位的值变了。
对应位反转的类型,Nand Flash位反转的类型和解决办法,有两种:
1. ⼀种是nand flash物理上的数据存储的单元上的数据,是正确的,只是在读取此数据出来的数据中的某位,发⽣变化,出现了位反转,
即读取出来的数据中,某位错了,本来是0变成1,或者本来是1变成0了。此处可以成为软件上位反转。此数据位的错误,当然可以通过⼀定的校验算法检测并纠正。
2. 另外⼀种,就是nand flash中的物理存储单元中,对应的某个位,物理上发⽣了变化,原来是1的,变成了0,或原来是0的,变成了
1,发⽣了物理上的位的数据变化。此处可以成为硬件上的位反转。此错误,由于是物理上发⽣的,虽然读取出来的数据的错误,可以通过软件或硬件去检测并纠正过来,但是物理上真正发⽣的位的变化,则没办法改变了。不过个⼈理解,好像也是可以通过擦除Erase 整个数据块Block的⽅式去擦除此错误,不过在之后的Nand Flash的使⽤过程中,估计此位还是很可能继续发⽣同样的硬件的位反转的
错误。
以上两种类型的位反转,其实对于从Nand Flash读取出来的数据来说,解决其中的错误的位的⽅法,都是⼀样的,即通过⼀定的校验算法,常称为ECC,去检测出来,或检测并纠正错误。
如果只是单独检测错误,那么如果发现数据有误,那么再重新读取⼀次即可。
实际中更多的做法是,ECC校验发现有错误,会有对应的算法去出哪位错误并且纠正过来。
其中对错误的检测和纠正,具体的实现⽅式,有软件算法,也有硬件实现,即硬件Nand Flash的控制器controller本⾝包含对应的硬件模块以实现数据的校验和纠错的。
Nand Flash的⼀些typical特性
1. 页擦除时间是200us,有些慢的有800us
2. 块擦除时间是1.5mst233
3. 页数据读取到数据寄存器的时间⼀般是20us
4. 串⾏访问(Serial access)读取⼀个数据的时间是25ns,⽽⼀些旧的Nand Flash是30ns,甚⾄是5
0ns
5. 输⼊输出端⼝是地址和数据以及命令⼀起multiplex复⽤的
6. Nand Flash的编程/擦除的寿命:即,最多允许10万次的编程/擦除,达到和接近于之前常见的Nor Flash,⼏乎是同样的使⽤寿命了。
7. 封装形式:48引脚的TSOP1封装或 52引脚的ULGA封装
Nand Flash控制器与Nand Flash芯⽚
我们写驱动,是写Nand Flash 控制器的驱动,⽽不是Nand Flash 芯⽚的驱动,因为独⽴的Nand Flash芯⽚,⼀般来说,是很少直接拿来⽤的,多数都是硬件上有对应的硬件的Nand Flash的控制器,去操作和控制Nand Flash,包括提供时钟信号,提供硬件ECC校验等等功能,我们所写的驱动软件,是去操作Nand Flash的控制器
然后由控制器去操作Nand Flash芯⽚,实现我们所要的功能。
由于Nand Flash读取和编程操作来说,⼀般最⼩单位是页,所以Nand Flash在硬件设计时候,就考虑到这⼀特性,对于每⼀⽚(Plane),都有⼀个对应的区域专门⽤于存放,将要写⼊到物理存储单元
文字处理系统中去的或者刚从存储单元中读取出来的,⼀页的数据,这个数据缓存区,本质上就是⼀个缓存buffer,但是只是此处datasheet⾥⾯把其叫做页寄存器page register⽽已,实际将其理解为页缓存,更贴切原意。
⽽正是因为有些⼈不了解此内部结构,才容易产⽣之前遇到的某⼈的误解,以为内存⾥⾯的数据,通过Nand Flash的FIFO,写⼊到Nand Flash⾥⾯去,就以为⽴刻实现了实际数据写⼊到物理存储单元中了,⽽实际上只是写到了这个页缓存中,只有当你再发送了对应的编程第⼆阶段的确认命令,即0x10,之后,实际的编程动作才开始,才开始把页缓存中的数据,⼀点点写到物理存储单元中去。
坏块的标记
具体标记的地⽅是,对于现在常见的页⼤⼩为2K的Nand Flash,是块中第⼀个页的oob起始位置的第1个字节(旧的⼩页⾯,pagesize是512B甚⾄256B的Nand Flash,坏块标记是第6个字节),如果不是0xFF,就说明是坏块。相对应的是,所有正常的块,好的块,⾥⾯所有数据都是0xFF的。
对于坏块的标记,本质上,也只是对应的flash上的某些字节的数据是⾮0xFF⽽已,所以,只要是数据,就是可以读取和写⼊的。也就意味着,可以写⼊其他值,也就把这个坏块标记信息破坏了。对于出⼚时的坏块,⼀般是不建议将标记好的信息擦除掉的。
uboot中有个命令是
nand scrub
就可以将块中所有的内容都擦除了,包括坏块标记,不论是出⼚时的,还是后来使⽤过程中出现⽽新标记的。
nand erase
只擦除好的块,对于已经标记坏块的块,不要轻易擦除掉,否则就很难区分哪些是出⼚时就坏的,哪些是后来使⽤过程中⽤坏的了。Uboot 的轻量级坏块管理⽅法
NAND 坏块管理都是基于坏块表(BBT)的,通过这张表来标识系统中的所有坏块。所以,不同的管理⽅法之间的差异可以通过以下⼏个问题来到答案。
如何初始化和读取坏块表?
产⽣新的坏块时,如何标记并更新坏块表?
如何保存坏块表?是否有保存时断电保护机制?
对 NAND 写⼊数据时,如果当前块是坏块,如何到可替换的好块?
起重安装Uboot 是⽬前使⽤最为⼴泛的 bootloader,它提供了两种轻量级坏块管理⽅法,可称之为基本型和改进型。通过下表,我们可以看到两者的差异。
虽然 uboot 的改进型坏块管理⽅法的做了⼀些改进,但它仍然有三个主要的缺点。
1. 出现坏块,则将数据顺序写⼊下⼀个好块。如果 NAND 中存放了多个软件模块,则每个模块都需要预留⼀个较⼤的空间作为备⽤的好
块,这会浪费较多的 NAND 空间。通常,每个模块预留的备⽤好块数为 NAND 芯⽚所允许的最⼤坏块数,该值因不同的芯⽚⽽有所不同,典型值为 20 或 80。假设 NAND 是⼤页类型,总共有 N 个模块,则总共需要预留的空间⼤⼩为 N*80*128KB。
磁疗远红外2. 读取 BBT 时仅检查签名,没有对 BBT 的数据做校验。
3. 没有掉电保护机制。如果在保存 BBT 时断电,BBT 将丢失。
针对现有管理⽅法的缺陷,本⽂提出了⼀种更加安全⾼效的管理⽅法,将从以下三个⽅⾯阐述其实现原理。
共⽤好块池机制
⾸先,使⽤⼀个统⼀的备⽤好块池,为所有存放在 NAND 中的模块提供可替换的好块。这样,就不需要在每个模块后⾯放置⼀个保留区,提⾼了 NAND 的空间利⽤率。
共⽤好块池⽰意图
共⽤好块池⽰意图
为了实现共⽤好块池,需要建⽴⼀个从坏块到好块的映射,所以,除了 BBT 之外,还需定义⼀个替换表(SBT)。这样⼀来,当读第 i 个块的数据时,如果发现 BBT 中记录该块为坏块,就去 SBT 中查询其替换块;如果写第 i 个块出错,需要在 BBT 中标记该块为坏块,同时从好块池中获取⼀个新的好块,假设其序号为 j,然后将此好块的序号 j 写⼊ SBT 中的第 i 个字节,⽽且 SBT 的第 j 个字节写序号 i。SBT 中的这种双向映射可确保数据的可靠性。此外,好块池中的块也有可能成为坏块,如果扫描时发现是坏块,则将 SBT 中的对应位置标记为 0x00,如果是在写的过程中出错,则除了在 SBT 对应位置标记 0x00 之外,还要更新双向映射数据。
BBT/SBT 映射⽰意图
安全的 BBT/SBT 数据校验机制
传统⽅法仅检查 BBT 所在块的签名,将读到的前⼏个字节和⼀个特征字符串进⾏⽐较,如果⼀致,就认为当前块的数据为 BBT,然后读取接下来的 BBT 数据,但并不对 BBT 的数据做校验。如果 BBT 保存在 NAND 中,数据的有效性是可以得到验证的,因为 NAND 控制器或驱动⼀般都会对数据做 ECC 校验。但是,⼤多数控制器使⽤的 ECC 算法也仅仅能纠正⼀个 bit、发现 2 两个 bit 的错误。如
果 BBT 保存在其他的没有 ECC 校验机制的存储体中,⽐如 NOR Flash,没有对 BBT 的数据进⾏校验显然是不安全的。
为了更加可靠和灵活地验证 BBT/SBT 数据,定义下⾯这个结构体来描述 BBM 信息。
BBM 头信息
typedef struct {
UINT8    acSignature[4];/* BBM 签名 */
UINT32    ulBBToffset;/* BBT 偏移 */
UINT32    ulSBToffset;/* SBT 偏移 */
UINT16    usBlockNum;/* BBM 管理的 block 数⽬ */
UINT16    usSBTstart;/* SBT 所在位置的起始 block 序号 */
UINT16    usSBtop;/* SBT top block */
UINT16    usSBnum;/* SBT number */
UINT32    ulBBTcrc;/* BBT 数据 CRC 校验码 */
UINT32    ulSBTcrc;/* SBT 数据 CRC 校验码 */
UINT32    ulHeadcrc;/* BBM 头信息 CRC 校验码 */
} BBM_HEAD
BBT/SBT 的保存形式
BBT/SBT 的保存形式
使⽤三重 CRC 校验机制,⽆论 BBT 保存在哪种存储体中,都可以更加严格地验证数据的有效性。
安全的掉电保存机制
传统的⽅法仅保存⼀份 BBT 数据,如果在写 BBT 时系统掉电,则 BBT 丢失,系统将可能⽆法正常启动或⼯作。为安全起见,本⽂所述⽅法将同时保留三个备份,如果在写某个备份时掉电,则还有两个完好的备份。最坏的情况是,如果在写第⼀个备份时掉电,则当前最新的⼀个坏块信息丢失。
读取坏块表时,顺序读取三个备份,如果发现三个备份的数据不⼀致,⽤记录的坏块数最多的备份为
当前的有效备份,同时⽴刻更新另外两备份。
总结
本⽂介绍了NandFlash基础知识和⼏类 NAND 坏块管理⽅法,指出了 uboot 的轻量级管理⽅法的缺陷,提出了⼀种改进的⽅法,提⾼了NAND 的利⽤率及坏块管理的安全性,可对嵌⼊式开发起到有很好的借鉴作⽤。
ECC定义
ECC校验是⼀种内存纠错原理,它是⽐较先进的内存错误检查和更正的⼿段。即纠错内存,简单的说,其具有发现错误,纠正错误的功能,⼀般多应⽤在⾼档台式电脑/服务器及上,这将使整个电脑系统在⼯作时更趋于安全稳定。
技术原理
内存是⼀种电⼦器件,在其⼯作过程中难免会出现错误,⽽对于稳定性要求⾼的⽤户来说,内存错误可能会引起致命性的问题。内存错误根据其原因还可分为和软错误。硬件错误是由于硬件的损害或缺陷造成的,因此数据总是不正确,此类错误是⽆法纠正的;软错误是随机出现的,例如在内存附近突然出现等因素都可能造成内存软错误的发⽣。
为了能检测和纠正内存软错误,在技术出现之前,⾸先出现的是内存“(Parity)”。内存中最⼩的单位是⽐特,也称为“位(bit)”,位有只有两种状态分别以1和0来标⽰,每8个连续的⽐特叫做⼀个字节(byte)。不带奇偶校验的内存每个字节只有8位,如果其某⼀位存储了错误的值,就会导致其存储的相应数据发⽣变化,进⽽导致应⽤程序发⽣错误。⽽奇偶校验就是在每⼀字节(8位)之外⼜增加了⼀位作为错误检测位。在某字节中存储数据之后,在其8个位上存储的数据是固定的,因为位只能有两种状态1或0,假设存储的数据⽤位标⽰为1、1、1、0、0、1、0、1,那么把每个位相加(1+1+1+0+0+1+0+1=5),结果是奇数。对于,校验位就定义为1,反之则为0;对于,则相反。当CPU读取存储的数据时,它会再次把前8位中存储的数据相加,计算结果是否与位相⼀致。从⽽⼀定程度上能检测出内存错误,只能检测出错误⽽⽆法对其进⾏修正,同时虽然双位同时发⽣错误的概率相当低,奇偶校验却⽆法检测出双位错误。
通过上⾯的分析我们知道内存是通过在原来的基础上增加⼀个数据位来检查当前8位数据的正确性,但随着数据位的增加Parity⽤来检验的数据位也成倍增加,就是说当数据位为16位时它需要增加2位⽤于检查,当数据位为32位时则需增加4位,依此类推。特别是当数据量⾮常⼤时,数据出错的⼏率也就越⼤,对于只能纠正简单错误的奇偶检验的⽅法就显得⼒不从⼼了,正是基于这样⼀种情况,⼀种新的内存技术应允⽽⽣了,这就是(错误检查和纠正),这种技术也是在原来的数据位上外加校验位来实现的。不同的是两者增加的⽅法不⼀样,这也就导致了两者的主要功能不太⼀样。它与不同的是
如果是8位,则需要增加5位来进⾏ECC错误检查和纠正,数据位每增加⼀倍,ECC只增加⼀位检验位,也就是说当数据位为16位时ECC位为6位,32位时ECC位为7位,数据位为64位时ECC位为8位,依此类推,数据位每增加⼀倍,ECC位只增加⼀位。总之,在内存中能够容许错误,并可以将错误更正,使系统得以持续正常的操作,不致因错误⽽中断,且ECC具有⾃动更正的能⼒,可以将Parity⽆法检查出来的错误位查出并将错误修正。
⽰例
ECC(Error Checking and Correcting,错误检查和纠正)内存,它同样也是在上额外的位存储⼀个⽤的代码。当数据被写⼊内存,相应的ECC代码与此同时也被保存下来。当重新读回刚才存储的数据时,保存下来的代码就会和读数据时产⽣的ECC代码做⽐较。如果两个代码不相同,他们则会被解码,以确定数据中的哪⼀位是不正确的。然后这⼀错误位会被抛弃,则会释放出正确的数据。被纠正的数据很少会被放回内存。假如相同的错误数据再次被读出,则纠正过程再次被执⾏。重写数据会增加处理过程的开销,这样则会导致系统性能的明显降低。如果是随机事件⽽⾮内存的缺点产⽣的错误,则这⼀的错误数据会被再次写⼊的其他数据所取代。

本文发布于:2024-09-22 17:28:18,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/270487.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   错误   坏块   内存   对应   硬件   检测   算法
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议