一.操作注意点:坏块一旦确定,就不允许在对其进行擦除或写操作
坏块一般由系统文件或软件管理程序在spare去进行标记
二.坏块管理的基本作用:标记nandflash中的所有坏块并建立坏块表,避免对坏块进行操作,在对nandflash进行操作时如遇到坏块则将其标记,跳过并找一好块替代该坏块,同时更新逻辑地址与物理地址的映射关系和坏块表,使得nandflash对上层文件(系统)仍是连续的。
三.nandflash中坏块出现的四种情况:
1.出厂时的坏块
2.操作过程中由擦除失败造成的
3.擦除过程中写入操作失败引起的
4.出现超出ECC校验算法纠正能力的错误时,也认为出现了坏块
四.出现坏块时,坏块管理机制通过分配一个好块来存储当前坏块的数据并进行地址重映射,寻找新块的方法有下面两种:
1.skip block method:出现坏块,跳过,寻找下一个最近的好块,将数据存储在该好块上。这时该好块对应的坏块的信息也得存储在nandflash中
2.reserved bolock method:遇到坏块,不跳转,通过修改逻辑地址与物理地址的映射关系,将逻辑地址映射到一个已知的好块,达到替换的目的。
此时坏块管理软件将nandflash分为可寻址块区和保留区(一般保留区为nandflash的2%)。
五.当上层文件(系统)写一个逻辑sector时,计算出要写的块的物理地址(该物理地址也可以由坏块管理软件得出)。坏块管理软件检测该块是否为坏块,如果是,重新将该sector的逻辑地址映射到一个好块上,并返回该好块的地址。对使用中出现的坏块,坏块管理软件对其重映射,并将原来的数据搬到好块上。坏块管理软件对文件系统是透明的,对文件系统而言,就如同将数据写到相同的地址上一样。
六.动态坏块管理设计思想:对nandflash进行操作时,出现坏块,采用动态坏块算法,标记坏块,将坏块放进坏块映射表的坏块区,从系统预留的坏块区中选择一个好块替代坏块进行操作;同时更新逻辑物理地址映射表。
(一)将nandflash存储地址映射空间划分为:
1.数据区:用于存储数据,系统应用程序,均为好块。
2.交换块:所有已用块的写入操作均改为对交换块的写入,交换块同时起着更新映射表时,防止掉电发生,保存原始映射表,在更新nandflash中的映射表完成后,再将旧表擦除的作用,可以有效应对掉电状态,不至于掉电时发生信息丢失的情况,交换个数一般为一两个,或更多。
3.替换块:替换坏块。
4.坏块区:用于存放初次上电扫描发现的坏块及使用过程中出现的坏块。
(二)动态坏块管理算法流程及实现
动态坏块管理算法由建立坏块表、建立逻辑物理块映射表、更新逻辑物理块映射表三部分组成。
第一步,建立坏块表
check_block();
scan_block();
markblockbad();
第二步,建立逻辑物理地址映射表
映射表地址空间分布:文件系统以LBA为单位对nandflash存储空间进行寻址;nandflash底层硬件而言,所有读写操作均以实际的页地址和类地址来进行。因而需要将LBA转换为逻辑地址,再将逻辑地址转换为物理地址。因为LBA是对sector而言的,LBA转换为逻辑地址的转化。
根据nandflash的页的大小,块容量的不同,进行移位操作即可。对nandflash管理的真正难点在于逻辑——物理地址的映射。
将坏块放在映射表的最后,采用发现一个坏块对应地址指针递减的方法实现坏块区的地址映射。为此构造数组lookuptable[512]来映射 nandflash的一个ZONE空间,数组元素由两个字节组成(映射的物理块地址要占9个bit;还要标识好坏块、块的空闲/已使用情况、块是否已映射等情况)。构造指针plookuptabel指向数组第一个元素,即映射的第一个物理块;初始化指针pbadblock指向映射表的最后一个元素,即将 第一个坏块的物理地址映射到lookuptable最后,每当发现一个坏块就依次将指针pbadblock递减依次完成整个zone的坏块映射。
当对一个zone的512个块进行映射时,我们将紧跟在数据区之后的两个块设定为交换块。当系统要对一个已用块进行写入操作时,根据该块物理地址的奇偶性选择一个交换替代该已用块进行写入操作,同时将该已用块的数据发知道交换块上,最后擦除该已用块,将其作为新的交 换块。最后当写完一个块时,更新RAM中的映射表,达到动态的映射地址的更新,在更新nandflash的映射表时,也是通过交换块,先将旧的 映射表存进交换块后,再将更新后的映射表写进nandflash,最后擦除旧的映射表,达到防止掉电映射表被破坏后丢失的情况。
将交换块的逻辑地址,即其在映射表中的逻辑地址放在替换块前。
在逻辑——物理地址映射表中,将替换块的逻辑地址放在交换块之后,坏块区之前。替换块用于当对发生写入或擦除失败的坏块进行替换,以及坏块数据的转存。
使用替换块时,我们从替换块的底部开始使用,地址依次递减。替换块的最后一块的地址指针紧接着坏块区第一个坏块的指针地址.每当操作中遇到坏块需要替换时,先要判断是否有空的替换块,如有才能进行替换;否则不能替换,此时需更新地址映射表,从数据中找新的空块,重新 分配替换块。
在建立映射表时,需要对整个nandflash存储空间的状态进行判断,即块的空满、好坏状态等。
spare 区个字节相关定义,对2K/page 来说,就有64个字节的spare区。
0——4:存放读写构成中的ECC code,
5:存放块状态,表明该地块是好块用0xff,还是坏块0x00
6——7:保留
8:表明该块所处鱼第几个块,逻辑层驱动每512个块划分为一个zone
9——10:该块对应的逻辑块地址
11——15:保留
spare区相关函数:
log_readblockspare(); 用于读出待操作块的逻辑块地址和块状态,并调用后两个函数。
log_readblockspare();参数定义如下:unsigned char ZoneNo;待操作块处于的Zone Number
unsigned short BlockNo;待操作块为第几个物理块
unsigned char PageNo;待操作块的页号
unsigned char SectorNo;待操作的sector号
ReadSpareData();
FillSpareData();
地址映射函数log_mapzone()实现逻辑物理块地址映射功能。
lookuptable[512],即映射表实现逻辑与物理地址的映射,lookuptable其实是一个有1024个字节、512元素的数组,plooluptable为数组首地址,每一个数组元素对应一个物理块,元素顺序号即可认为是逻辑块地址。由于要将nandflash存储空间划分为数据区、替换区和坏块区,所 以将映射表地址指针分配如下:
*plookuptable;指向第一个好块
*pbadblock;指向映射表末尾,逻辑块地址为zone的最后一个块,即plookuptable[512]
通过调用坏块信息表,统计出该zone的坏块数,用变量InvldBlkPerZoneInChip[bZone],同时用CurReplaceIndex[ChipNo][ZoneNo]来表示替换块指数。只有CurReplaceIndex[ChipNo][ZoneNo不为0时,才能发生坏块替换,否则,要重新进行地址映射,分配替换块。
具体函数实现流程:
1.调用坏块表,计算该Zone坏块数量
if(!ChipNo)
{
MemeryCopyFromBuffer(DataBuffer_BadBlock,64);
}
else
{
MemeryCopyFromBuffer(DataBuffer_BadBlock2,64);
}
Flpageaddr存放坏块表地址,坏块表以位代表块状态
2.初始化逻辑——物理块地址映射表,将其全部标记为物理块地址为空,块空闲,未映射状态,即将lookuptable[512]的全部元素初始化为 0x4000;
3.判断zone内每个块的好块、空闲等状态,并以变量woutputvalue返回给函数使用
首先通过readblockspare()函数读出检测块的首页第一个sector对应的spare区和最后一页对应的spare区中的块逻辑地址,分别用 wfirstsectorflag和wlastsectorflag表示,用0x1000代表坏块
MLC与SLC在ECC校验上不同,对SLC,用wfirstsectorflag代表woutputvalue;对MLC,若wfirstsectorflag显示其为坏块,则用 wlastsectorflag代表woutputvalue
4.根据坏块状态情况,将坏块扔到坏块区,pbadblock地址指针递减,同时将坏块的物理地址写入映射表。
动态管理将已在映射表中已映射的已用块擦除,标记为为映射的空状态,未映射的已用块则只需将其标记为已映射即可。
5.经过上面四步,nandflash存储空间的数据区此时分为:未映射的空块和已映射的已用块。接下来,只需将未映射的空块进行映射即可,以变量wRecord_plook代表要映射的物理块地址,逐一对空块,未映射的块进行映射,同时将其状态标记为已映射块。pScanBuf为本次操作块 在映射表中的逻辑地址
6.将最后一个和倒数第二个映射的空块作为交换块,将其逻辑地址分别定义为
plookuptable[ZONE_SIZE-1-Replace-InvldBlkPerZoneInChip[ChipNo][bZone]];
plookuptable[ZONE_SIZE-2-Replace-InvldBlkPerZoneInChip[ChipNo][bZone]];
7.算出替换块指数CurReplaceIndex[ChipNo][ZoneNo]=(InvldBlkPerZoneInChip[ChipNo][bZone]+ReplaceBlock-1-wBadblockNum)
wBadblockNum为映射过程中发现坏块数
至此,建立逻辑物理映射表结束。
映射表生成后,将其烧写到替换块的第一个物理块上,并将这个物理地址保存到nandflash的启动初始信息page的第二个sector上。
第三步.更新逻辑——物理映射表
分两步:(1)首先更新RAM中的地址映射表:
写完一个块后,更新相应的逻辑、物理地址。若操作中发现坏块,替换区有空闲块,发生替换,将坏块的逻辑地址赋给来替代坏块的替换块,并将坏块标记,将坏块的物理地址对应到逻辑地址映射表的坏块区,将替换块的空闲标志位改为已用块;若无替换块,原来的块是个已 用块,则将其擦除,将其物理块地址对应到交换块逻辑位置上,将ram中映射表更新iaozhiwei置一,即完成ram中的逻辑——物理块地址映射
(2)然后更新nandflash芯片中保存的地址映射表
统一将替换块中逻辑地址最靠前的一块作为保存该zone地址映射表的默认地址块,即地址映射表中逻辑地址为(ZONE_SIZE-1-Replace-InvldBlkPerZoneInChip[bChip_Old][bZone_Old])对应的物理块。为防止掉电产生的丢失映射表,先将旧映射表调出,保存在交换块中,然后擦除原来保存旧映射表的块,即(ZONE_SIZE-1-Replace-InvldBlkPerZoneInChip[bChip_Old][bZone_Old])对应的物理块,将ram中更新过 的逻辑——物理块地址映射表写进该块,最后擦除交换块中的旧表。如果nandflash芯片中并没有旧的地址映射表,则将上述逻辑地址对应的物理块擦除,将ram中的地址映射表写进该块即可。nandflash所有zone的地址映射块的物理地址0页都同意保存在nandflash鉴权page的第二个sector的前126个字节域