nand的坏块管理机制以及BBT相关知识(持续更新)

        最近遇到一些BBT管理的问题,在查找问题原因的过程中将一些问题记录如下。其中较为繁杂,且得写几天。

        NAND Flash是一种高密度低成本的存储体,在各种设备中被广泛使用。U盘等USB存储设备、SD卡、手机、固态硬盘等各种设备中使用的都是NAND芯片。其内部结构是按照块/页进行组织的,一个NAND芯片包含若干个块,块内有页组成。每个页也包含data区和spare区。由于制作工艺和成本的原因, 在出厂的时候,NAND的spare区会存在坏块。那么如何对坏块进行管理呢?

      总体上来讲NAND坏块管理方法分类,可分为如下几类:

l        基于 FTL 芯片的坏块管理

       它使用一个额外的 FTL (FlashTranslation Layer)芯片对 NAND 进行管理,对外部屏蔽了坏块信息,U 盘、SD 卡、MMC 卡以及固态硬盘都使用这种管理方法。这种方式简化了 NAND 操作,但也使坏块信息对外部而言不可见,如果系统中出现了可能和坏块相关的问题,定位和调试变得困难,另外,FTL 芯片也需要额外的硬件成本。

l        基于NAND 文件系统的坏块管理

       JFFS2、 YAFFS2、 FlashFx 这些专门针对 NAND 的文件系统可以对坏块进行管理。

l        NAND 管理中间件

       有一些中间件(Middleware)专门用于 NAND 管理,比如 UBI。

l        轻量级 NAND 坏块管理

       对 NAND 进行管理的硬件或软件模块,不仅提供坏块管理,同时也支持对 NAND 的擦写操作进行负载平均。而轻量级的坏块管理只专注于坏块,并不提供擦写负载平均的支持,而且,它也不依赖于任何第三方的库。因此,轻量级的坏块管理方式降低了系统的复杂度,而且免去了加载文件系统或初始化中间件的时间,在嵌入式系统中有着广泛的应用。


       在使用的过程中,往往选择基于nand专用文件系统使用NAND。因此会在spare区存放一些其他有效数据,从而破坏了NAND原有的spare区的数据。因此当拿到一块芯片时,应该先读取spare区的相关字段。然后进行记录,而记录就需要使用BBT。

       在linux系统中,通常使用struct nand_bbt_descr 进行spare区的描述。此结构体的定义如下:

/**

 * struct nand_bbt_descr - bad block table descriptor

 * @options:options for this descriptor

 * @pages:the page(s) where we find the bbt, used with option BBT_ABSPAGE

 *when bbt is searched, then we store the found bbts pages here.

 *Its an array and supports up to 8 chips now

 * @offs:offset of the pattern in the oob area of the page

 * @veroffs:offset of the bbt version counter in the oob are of the page

 * @version:version read from the bbt page during scan

 * @len:length of the pattern, if 0 no pattern check is performed

 * @maxblocks:maximum number of blocks to search for a bbt. This number of

 *blocks is reserved at the end of the device where the tables are

 *written.

 * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than

 *              bad) block in the stored bbt

 * @pattern:pattern to identify bad block table or factory marked good /

 *bad blocks, can be NULL, if len = 0

 *

 * Descriptor for the bad block table marker and the descriptor for the

 * pattern which identifies good and bad blocks. The assumption is made

 * that the pattern and the version count are always located in the oob area

 * of the first block.

 */

struct nand_bbt_descr {

int options;

int pages[NAND_MAX_CHIPS];

int offs;

int veroffs;

uint8_t version[NAND_MAX_CHIPS];

int len;

int maxblocks;

int reserved_block_code;

uint8_t *pattern;

};


       按照此描述,如果我们对这个结构体的变量进行赋值之后。在使用的过程中,就会按照程序设计的要求搜寻BBT。此处需要说明,linux无论如何是需要在内存中建立坏块信息表,不同的是如果我们没有相关的芯片存储数据,那么会在搜寻BBT的过程中,扫描所有的设备块创建内存BBT,设备关闭之后会消失。而存放在芯片上的BBT数据,会在设备关闭之后进行回写操作。

      在NAND的初始化过程中,需要建立坏块表。通过调用chip->scan_bbt(mtd);完成。正是调用了函数nand_default_bbt,此函数中会首先判断是否是AG-AND类型的NAND,如果是则按照规则建立BBT,此处没有深入分析。如果option中定义了NAND_USE_FLASH_BBT,则将在nand_bbt.c中定义的结构体赋值:

                                this->bbt_td = &bbt_main_descr;
this->bbt_md = &bbt_mirror_descr;

并且通过调用

                            if (!this->badblock_pattern)
                         nand_create_default_bbt_descr(this);

                   nand_scan_bbt(mtd, this->badblock_pattern);

完善整个BBT。此函数是整个扫描BBT的重要函数。

       在这个过程中, If no primary table decriptor is given, scan the device to build a memory based bad block table。如果有主描述表和镜像描述表的,则不需要扫描整个设备建立内存BBT。

       如果需要写一个应用程序,让系统启动之后通过应用程序的执行完成对mtd设备的读写操作。则需要注意:

1 首先我们在用户空间能够使用的资源要么是文件系统使用的一套逻辑,要么是使用驱动为我们用户空间提供的ioctl命令。

2当选择使用ioctl命令时,发现内核并没有支持对于数据区的读写操作,因此只能利用linux一切皆文件的概念进行操作。此时就需要注意对于坏块的操作,并没有提供相应的读取机制,因此需要在写之前进行擦除操作以确保坏块的存在和不操作行为。


你可能感兴趣的:(nand的坏块管理机制以及BBT相关知识(持续更新))