http://gugongshuai.blog.163.com/blog/static/169967462201151454038762/
摘要:主要介绍了基于嵌入式Linux的NAND Flash坏块管理设计和实现方案,详细阐述了坏块映射表的建立、维护及其相关算法,同时分析了此坏块算法在Linux内核及Bootloader中的具体应用。测试结果表明该算法能够处理NANDFlash的相关坏块问题,具有较高的稳定性。
关键词:NAND Flash;嵌入式IAnux;映射表;坏块管理
在拥有诸多优点的同时,NAND Flash由于生产工艺的问题,其在出厂时可能存在一定的坏块。这些固有坏块不能用于存储数据,已被产家标识好。另外,使用过程中由于读写次数增多,好块也会变得不稳定或失效,成为坏块,这就是出厂后产生的坏块。
NAND Flash在生产及使用过程中都有可能产生坏块,这将使得系统变得不稳定。应用中一般采用跳块策略来管理坏块,但它不能解决系统运行中产生的坏块情况。针对此情形,本文提出基于嵌入式Linux系统平台下的一种基于坏块映射的NAND Flash坏块管理的方案,并详细介绍其相关映射算法和整套系统的相关坏块管理流程。
1 坏块管理层次结构
Linux下的MTD(Memory Technology Device)是用于管理ROM、Flash等内存设备的一层子系统,它使编写管理内存设备驱动变得更加简单。
MTD子系统将Flash设备或其分区抽象为MTD设备,使底层驱动只需实现MTD设备,而向上层文件系统提供标准的接口,如MTD字符设备、MTD块设备。
如图1所示,本方案设计中,将坏块管理层(BBMlayer)紧靠在驱动层之上MTD层之下,从而使得MTD层对坏块不可见,并使坏块的管理是基于整个芯片而不是某个分区,便于上层文件系统实现损耗平衡。
a.JPG
BBM层基于驱动层提供的读、写、擦除相关操作实现接口read()、write()、erase()、read_oob()、write_oob()、isbad()、mark_bad()。对于其上层MTD子系统而言,关于坏块的相关接口将不存在,物理介质类似于NORFlash。其中read_oob()、write_oob()接口为文件系统提供相关用途,如JFFS2的cleanmarker相关载体。
2 坏块管理模块的设计实现
2.1 坏块管理原理
本文的设计的坏块管理是基于坏块映射原理的一种实现。在本坏块映射的设计中,NAND Flash被划分为基本空间和预留空间。基本空间为用户看到的NANDFlash的总的存储空间。基本空间中的坏块被映射到预留空间中的相应好块。基本映射关系如图2所示。映射管理信息记录在坏块映射表中,它存储在预留空间。
b.JPG
2.2 坏块映射表的描述
在预留空间存在4种形式的块:空闲的好块、坏块、被映射的块、存放映射表的块。
存放映射表的块较为特殊,其中映射表不仅描述基本空间中的坏块映射相关信息,还描述预留空间占整个Flash空间的比例等。
设计中一张坏块表存于一个Flash块,表的信息存于块中最前面的相关页中。表的头部长度固定,表的整个长度可变,与坏块数目相关。
坏块映射表结构描述如下:
c.JPG
其中hdr_crc和tbl_crc用于检验表的完整性;rese_start_blk即预留空间的起始块号;version用于标识该表的版本;num_bad_blk用于描述已发现的坏块数,即坏块映射表项的数目;map_tbl为记录坏块映射表项内容的首地址。任何一个映射表项包括坏块块号及其映射的好块的块号。
由于使用过程中会产生新的坏块,映射表中的表项需要增加,从而要更新Flash中的映射表。为了防止系统意外掉电产生映射表不一致问题,采用日志技术。其中version版本号标识映射表的新旧,在更新Flash映射表的同时,版本号递增,同时Flash旧版本映射表并不立即擦除。只有出现预留空间不足的情况,擦除旧版本映射表的动作才执行。此方案还有利于调试,查看映射表的更改历史记录。
在出现坏块Bn后,通常包括两个动作:写映射表和标识坏块。标识坏块是通过在块的00B相应字节写非0xFF来实现。
为了支持意外掉电情形,每个版本的映射表必须在Flash里保存两份,如果发现最高的版本映射表没有两份,或者两份不一致,则属于非正常情况,必须重新建立映射表。
考虑如下情况:写完映射表Vn,接着标识坏块Bn,此时掉电,则下次系统启动后,出现映射表的坏快Bn,实际上并没有被标识,导致不一致问题。写2份Vn可以解决此问题:写第一份Vn后,标识坏块Bn,接着再写第二份Vn。这样即使在标识坏块Bn时掉电,下次系统加电时由于没有发现2份版本相同且最高的映射表,从而识别出此非正常情况。
同时,维护2份同版本坏块表可以处理存放映射表的块突然坏死而导致系统无法启动的异常,起到备份的作用。
2.2.1 坏块映射表的管理算法
系统初始化时读入坏块表的内容,在内存中建立所有坏块的映射信息。由于每次发现新的坏块而更新坏块表时,都会写入两个版本一样的坏块表,所以在读入坏块表时就要检查两个表是否有效和一致,可以分为以下情况:
①发现2张最高版本并且有效的坏块表Vn+1——系统按表Vn+1建立映射;
②只发现1张最高版本并且有效的坏块表Vn+1,并且有2张有效坏块表Vn——发生在上次写完一个Vn+1后突然掉电,使得第二个表Vn+1未写入或写入不完整,这时需要恢复,以建立完整映射,恢复算法如图3所示。
d.JPG
③只发现一张最高版本并且有效地坏块表Vn+1,并且有1张有效坏块表Vn——发生在写第二张Vn+1突然掉电,并且之前写第二张Vn也发生掉电;
④仅发现一张坏块表V0——发生在系统写第二张V0时掉电,此时系统需重新扫描建立映射表V1;
⑤没有发现任何坏块表——系统最初状态;
⑥两个完整的坏块表Vn+1,但num_bad_blk不一样——这种情况发生在更新第二个坏块表Vn+1时,写的时候出错,产生一个新的坏块,从而第二次更新的坏块表Vn+1的坏块数增加了。
对于情况①,只需在系统最初建立前建立好映射关系即可。
对于情况②,它经常出现在系统在写或者擦除Flash数据块时突然断电,导致数据或者ECC变化,从而Flash读导致ECC不正确。实际上Fl-ash块并没有坏。根据此种情况,将首先为此块分配一个映射块,并把数据拷入映射块。接着对此块进行torture操作,如果发现它为好块,则将之前映射操作撤销,将数据重新拷入此好块。如果此块确实已坏,则将此块标记为坏块,并更新映射表。
对于情况③,分配一个新的映射块,把有效数据写入新块,并建立映射信息。
对于情况④,分配一个新的映射块,并将此块查出,然后建立映射信息。
对于情况⑤,扫描整个Flash,建立映射表Vn、V0。
对于情况⑥,则采用坏块多的映射表Vn+1,并用它更新Vn+2、Vn+2。
2.2.2 坏块管理及上层接口实现
该模块实现基于上节所述坏块管理算法对Flash的所有有效块的使用。它主要是处理运行中产生坏块的情况,并让上层程序屏蔽此信息。
NAND Flash的坏块包含如下三种类型:
◆Flash上存在的出厂坏块;
◆读过程发生比特反转而被视为的坏块;
◆操作过程(读,写,擦除)中产生的新的坏块。
对于此模块主要完成后两种动态坏块类型的处理过程。对于出厂坏块,只需在初始化时检测出来并将其映射到一个好块,以后的读写过程中对映射块操作即可。
对于运行中产生的坏块,从操作类型(读、写、擦除)来进行分别处理。
①读过程中的比特反转导致ECC错误,由于比特反转是NAND工艺决定的,且是不可避免的随机行为,所以不能简单地根据ECC错误就将其当作坏块处理。具体处理流程如图4所示,通过torture操作判断此“坏块”已真正成为坏块。
e.JPG
如果NAND Flash在执行擦除或写操作过程时发生断电,则所操作的块内的数据具有不确定性。下次读该块的内容时,可能发生无法纠正的ECC错误。为了能处理这种情况,图4中的torture处理,其实现原理就是选择一些数据写入该块,再读出,如果不一致则该块已变成坏块。
②写过程中发生错误,则该块成为坏块。处理方法为:为其分配一个新的有效块,将坏块原有数据拷贝到有效块,并同时写入新的数据,最后更新映射表,标识坏块。写操作的错误处理算法如图5所示。
f.JPG
③擦除过程发生错误,则该块成为坏块。处理方法为:为其分配一个新的有效块,并擦除此有效块,更新映射表,标识坏块。
2.3 BootIoader的坏块管理
在Bootloader层采用Linux内核相同的坏块管理策略,并复用相关代码。Bootloader在内存建立起的坏块映射表可以通过内存共享的方式,传递给Linux内核,从而减少内核重新扫描坏块映射表的时间,加快系统启动速度。
3 测试
Cases测试方法:对一切可能情况实行模拟测试,最后进行压力测试。
3.1 坏块场景模拟测试
①出厂坏块;
②运行中产生坏块:读操作产生坏块,写操作产生坏块,擦操作产生坏块,比特反转产生伪坏块。
3.2 坏块表一致性场景模拟
①2张相同Vn+1;
②1张Vn+1和2张相同Vn;
③1张Vn+1和1张Vn;
④1张Vn;
⑤没有任何坏块表;
⑥2张不相同的Vn+1。
3.3 压力测试
系统不间断运行10天后,工作状态仍然正常。
3.4 文件系统测试
系统能够支持对坏块敏感的文件系统squashfs、cramfs,其测试案例均通过。这表明该坏块管理方法能有效管理NAND Flash。
4 总结
本文提出了一种基于嵌入式Linux整套系统的NAND Flash坏块管理实现方案,并详细介绍其坏块映射算法。此方案目前已经应用到数字电视开发平台。在系统平台上的相关坏块动态产生、突然掉电等大量测试表明此方案稳定可靠。
NAND Flash的坏块管理设计
摘要:主要介绍了基于嵌入式Linux的NAND Flash坏块管理设计和实现方案,详细阐述了坏块映射表的建立、维护及其相关算法,同时分析了此坏块算法在Linux内核及Bootloader中的具体应用。测试结果表明该算法能够处理NANDFlash的相关坏块问题,具有较高的稳定性。
关键词:NAND Flash;嵌入式IAnux;映射表;坏块管理
在拥有诸多优点的同时,NAND Flash由于生产工艺的问题,其在出厂时可能存在一定的坏块。这些固有坏块不能用于存储数据,已被产家标识好。另外,使用过程中由于读写次数增多,好块也会变得不稳定或失效,成为坏块,这就是出厂后产生的坏块。
NAND Flash在生产及使用过程中都有可能产生坏块,这将使得系统变得不稳定。应用中一般采用跳块策略来管理坏块,但它不能解决系统运行中产生的坏块情况。针对此情形,本文提出基于嵌入式Linux系统平台下的一种基于坏块映射的NAND Flash坏块管理的方案,并详细介绍其相关映射算法和整套系统的相关坏块管理流程。
1 坏块管理层次结构
Linux下的MTD(Memory Technology Device)是用于管理ROM、Flash等内存设备的一层子系统,它使编写管理内存设备驱动变得更加简单。
MTD子系统将Flash设备或其分区抽象为MTD设备,使底层驱动只需实现MTD设备,而向上层文件系统提供标准的接口,如MTD字符设备、MTD块设备。
如图1所示,本方案设计中,将坏块管理层(BBMlayer)紧靠在驱动层之上MTD层之下,从而使得MTD层对坏块不可见,并使坏块的管理是基于整个芯片而不是某个分区,便于上层文件系统实现损耗平衡。
a.JPG
BBM层基于驱动层提供的读、写、擦除相关操作实现接口read()、write()、erase()、read_oob()、write_oob()、isbad()、mark_bad()。对于其上层MTD子系统而言,关于坏块的相关接口将不存在,物理介质类似于NORFlash。其中read_oob()、write_oob()接口为文件系统提供相关用途,如JFFS2的cleanmarker相关载体。
2 坏块管理模块的设计实现
2.1 坏块管理原理
本文的设计的坏块管理是基于坏块映射原理的一种实现。在本坏块映射的设计中,NAND Flash被划分为基本空间和预留空间。基本空间为用户看到的NANDFlash的总的存储空间。基本空间中的坏块被映射到预留空间中的相应好块。基本映射关系如图2所示。映射管理信息记录在坏块映射表中,它存储在预留空间。
b.JPG
2.2 坏块映射表的描述
在预留空间存在4种形式的块:空闲的好块、坏块、被映射的块、存放映射表的块。
存放映射表的块较为特殊,其中映射表不仅描述基本空间中的坏块映射相关信息,还描述预留空间占整个Flash空间的比例等。
设计中一张坏块表存于一个Flash块,表的信息存于块中最前面的相关页中。表的头部长度固定,表的整个长度可变,与坏块数目相关。
坏块映射表结构描述如下:
c.JPG
其中hdr_crc和tbl_crc用于检验表的完整性;rese_start_blk即预留空间的起始块号;version用于标识该表的版本;num_bad_blk用于描述已发现的坏块数,即坏块映射表项的数目;map_tbl为记录坏块映射表项内容的首地址。任何一个映射表项包括坏块块号及其映射的好块的块号。
由于使用过程中会产生新的坏块,映射表中的表项需要增加,从而要更新Flash中的映射表。为了防止系统意外掉电产生映射表不一致问题,采用日志技术。其中version版本号标识映射表的新旧,在更新Flash映射表的同时,版本号递增,同时Flash旧版本映射表并不立即擦除。只有出现预留空间不足的情况,擦除旧版本映射表的动作才执行。此方案还有利于调试,查看映射表的更改历史记录。
在出现坏块Bn后,通常包括两个动作:写映射表和标识坏块。标识坏块是通过在块的00B相应字节写非0xFF来实现。
为了支持意外掉电情形,每个版本的映射表必须在Flash里保存两份,如果发现最高的版本映射表没有两份,或者两份不一致,则属于非正常情况,必须重新建立映射表。
考虑如下情况:写完映射表Vn,接着标识坏块Bn,此时掉电,则下次系统启动后,出现映射表的坏快Bn,实际上并没有被标识,导致不一致问题。写2份Vn可以解决此问题:写第一份Vn后,标识坏块Bn,接着再写第二份Vn。这样即使在标识坏块Bn时掉电,下次系统加电时由于没有发现2份版本相同且最高的映射表,从而识别出此非正常情况。
同时,维护2份同版本坏块表可以处理存放映射表的块突然坏死而导致系统无法启动的异常,起到备份的作用。
2.2.1 坏块映射表的管理算法
系统初始化时读入坏块表的内容,在内存中建立所有坏块的映射信息。由于每次发现新的坏块而更新坏块表时,都会写入两个版本一样的坏块表,所以在读入坏块表时就要检查两个表是否有效和一致,可以分为以下情况:
①发现2张最高版本并且有效的坏块表Vn+1——系统按表Vn+1建立映射;
②只发现1张最高版本并且有效的坏块表Vn+1,并且有2张有效坏块表Vn——发生在上次写完一个Vn+1后突然掉电,使得第二个表Vn+1未写入或写入不完整,这时需要恢复,以建立完整映射,恢复算法如图3所示。
d.JPG
③只发现一张最高版本并且有效地坏块表Vn+1,并且有1张有效坏块表Vn——发生在写第二张Vn+1突然掉电,并且之前写第二张Vn也发生掉电;
④仅发现一张坏块表V0——发生在系统写第二张V0时掉电,此时系统需重新扫描建立映射表V1;
⑤没有发现任何坏块表——系统最初状态;
⑥两个完整的坏块表Vn+1,但num_bad_blk不一样——这种情况发生在更新第二个坏块表Vn+1时,写的时候出错,产生一个新的坏块,从而第二次更新的坏块表Vn+1的坏块数增加了。
对于情况①,只需在系统最初建立前建立好映射关系即可。
对于情况②,它经常出现在系统在写或者擦除Flash数据块时突然断电,导致数据或者ECC变化,从而Flash读导致ECC不正确。实际上Fl-ash块并没有坏。根据此种情况,将首先为此块分配一个映射块,并把数据拷入映射块。接着对此块进行torture操作,如果发现它为好块,则将之前映射操作撤销,将数据重新拷入此好块。如果此块确实已坏,则将此块标记为坏块,并更新映射表。
对于情况③,分配一个新的映射块,把有效数据写入新块,并建立映射信息。
对于情况④,分配一个新的映射块,并将此块查出,然后建立映射信息。
对于情况⑤,扫描整个Flash,建立映射表Vn、V0。
对于情况⑥,则采用坏块多的映射表Vn+1,并用它更新Vn+2、Vn+2。
2.2.2 坏块管理及上层接口实现
该模块实现基于上节所述坏块管理算法对Flash的所有有效块的使用。它主要是处理运行中产生坏块的情况,并让上层程序屏蔽此信息。
NAND Flash的坏块包含如下三种类型:
◆Flash上存在的出厂坏块;
◆读过程发生比特反转而被视为的坏块;
◆操作过程(读,写,擦除)中产生的新的坏块。
对于此模块主要完成后两种动态坏块类型的处理过程。对于出厂坏块,只需在初始化时检测出来并将其映射到一个好块,以后的读写过程中对映射块操作即可。
对于运行中产生的坏块,从操作类型(读、写、擦除)来进行分别处理。
①读过程中的比特反转导致ECC错误,由于比特反转是NAND工艺决定的,且是不可避免的随机行为,所以不能简单地根据ECC错误就将其当作坏块处理。具体处理流程如图4所示,通过torture操作判断此“坏块”已真正成为坏块。
e.JPG
如果NAND Flash在执行擦除或写操作过程时发生断电,则所操作的块内的数据具有不确定性。下次读该块的内容时,可能发生无法纠正的ECC错误。为了能处理这种情况,图4中的torture处理,其实现原理就是选择一些数据写入该块,再读出,如果不一致则该块已变成坏块。
②写过程中发生错误,则该块成为坏块。处理方法为:为其分配一个新的有效块,将坏块原有数据拷贝到有效块,并同时写入新的数据,最后更新映射表,标识坏块。写操作的错误处理算法如图5所示。
f.JPG
③擦除过程发生错误,则该块成为坏块。处理方法为:为其分配一个新的有效块,并擦除此有效块,更新映射表,标识坏块。
2.3 BootIoader的坏块管理
在Bootloader层采用Linux内核相同的坏块管理策略,并复用相关代码。Bootloader在内存建立起的坏块映射表可以通过内存共享的方式,传递给Linux内核,从而减少内核重新扫描坏块映射表的时间,加快系统启动速度。
3 测试
Cases测试方法:对一切可能情况实行模拟测试,最后进行压力测试。
3.1 坏块场景模拟测试
①出厂坏块;
②运行中产生坏块:读操作产生坏块,写操作产生坏块,擦操作产生坏块,比特反转产生伪坏块。
3.2 坏块表一致性场景模拟
①2张相同Vn+1;
②1张Vn+1和2张相同Vn;
③1张Vn+1和1张Vn;
④1张Vn;
⑤没有任何坏块表;
⑥2张不相同的Vn+1。
3.3 压力测试
系统不间断运行10天后,工作状态仍然正常。
3.4 文件系统测试
系统能够支持对坏块敏感的文件系统squashfs、cramfs,其测试案例均通过。这表明该坏块管理方法能有效管理NAND Flash。
4 总结
本文提出了一种基于嵌入式Linux整套系统的NAND Flash坏块管理实现方案,并详细介绍其坏块映射算法。此方案目前已经应用到数字电视开发平台。在系统平台上的相关坏块动态产生、突然掉电等大量测试表明此方案稳定可靠。