NANDFLASH的学习(三)

文章目录

    • 三、动态坏块处理
      • (四)、动态管理算法设计流程及函数实现
        • 2、建立逻辑块地址-物理块地址映射表

与之相关联的文章:
NANDFLASH的学习(一)
NANDFLASH的学习(二)
NANDFLASH的学习(三)

三、动态坏块处理

(四)、动态管理算法设计流程及函数实现

2、建立逻辑块地址-物理块地址映射表

地址转换是NAND Flash逻辑层驱动需要完成的任务,对上层系统的文件系统诸如FatFs是以逻辑块地址(LBA, Logical Block Address)为单位来对闪存进行寻址的,并且LBA是以扇区(sector)而言的,它的大小根据Flash的容量大小决定,包括块数、块中页数、页的大小。而对底层硬件而言,是以实际的页地址(Page Address)和列地址(Column Address)这些物理块地址(PBA, Physical Block Address)来进行读写操作的。LBA到PBA的映射只需要通过移位操作即可完成,但PBA到LBA的映射则相对来说比较困难,下面主要讲它的实现方式。

动态坏块管理算法最重要的设计思想为:在对以zone为单位进行逻辑—物理块地址空间映射时,将NAND Flash存储空间划分为数据区、交换块区、替换块区和坏块区。动态坏块管理算法中的地址映射与传统的地址映射最大不同就是增加了交换块区与替换块区

该动态坏块管理算法将坏块放到映射表的最后,当发现坏块时,对应地址指针递减的方法实现坏块区的地址映射。由此需要构造数组lookUpTable[512]来映射flash中的一个zone,数组的元素为2个字节,这是因为映射的物理地址占9bit,标识好坏块1bit,块的空闲/使用状态1bit,块是否已映射1bit等。构造指针pLookUpTable指向数组的第一个元素,即映射的第一个PBA。构造指针pBadBlock指向数组的最后一个元素,即将第一个坏块的PBA映射数组lookUpTable的最后,每当发现一个坏块,依次将指针pBadBlock递减,依次完成对整个zone 的坏块映射。它的地址分配如下图所示。

NANDFLASH的学习(三)_第1张图片

从上图可以看到数据区之后紧跟着两个交换块1,2,它们的作用有以下几点:

  1. 对一个已用块进行写操作时,根据物理块的奇偶性进行选择使用哪一块交换块并将该已用块的数据复制到交换块上,再对已用块进行擦写,将其作为新的交换块。当写完一个块时,更新映射表从而达到动态更新映射表的目的。
  2. 在更新映射表时,也是通过交换块进行。首先将旧的映射表读出来并写入到交换块,擦除存放映射表的块,并将更新后的映射表写入其中,最后擦除存放在交换块中的旧映射表。同时也避免了在进行读写和擦除操作时断电导致数据丢失。

交换块的作用图如下:
NANDFLASH的学习(三)_第2张图片

为了实现动态的坏块替换,我们在每个zone预留20个好块用作替换块。在LBA-PBA映射表中,将替换块的的LBA放到交换块的后面,坏块区的前面,替换块用于对写入和擦写失败的块进行替换和数据转存。

使用替换块时,我们从替换块的底部开始用起,地址指针依次递减。替换块的最后一块的地址指针紧接着坏块区第一个坏块的指针地址。每当编程失败或擦除失败,需要进行坏块替换时,都要先判断是否还有空的替换块进行替换;否则,不能进行替换,此时,需要更新地址映射表,从数据区中找新的空块重新分配替换块。

替换块的一般流程图如下:
NANDFLASH的学习(三)_第3张图片

  • spare area字节含义
    另外在逻辑驱动层中,通过NAND Flash的spare area备用区域(每页64字节)中的数据来判断块的好坏和空满情况。它是进行存储空间管理的重要场所,驱动层的地址映射和坏块管理都要经过它提供的信息。当出现坏的编程和擦除失败时会动态更新该区域的信息以实现动态坏块管理。以下是它每个字节代表的含义,值得注意的是不同flash间spare area的每个字节代表的意思大多不同,以下以三星的K9K8G08UOM为例。
字节 0~4 5 6 7 8 9~10 11~15
作用 存放ECC校验码。当写入数据时闪存控制器会产生ECC纠错码,读出时也会产生新的ECC纠错码,控制器通过比对两者ECC纠错码来判断是否产生读出错误。 存放块的好坏状态,0xff代表好块 存放错误状态 表明该块是否用作冗余交换块 表明该块处于第几个zone 该块对应的逻辑地址 保留,用于拓展ECC纠错码纠正位错误,如4-bitECC
  • spare area相关函数

逻辑层驱动中spare array涉及的函数有log_readblockspare()、ReadSpareData()、FillSpareData()等,通过前者读出待操作块的逻辑块地址和块状态等,后两者用来被前者调用,工作在NAND Flash底层驱动中。

函数名 ReadSpareData() FillSpareData() log_readblockspare()
函数作用 填充要写入spare area的数据到sparebuff[16],其中bit0标记好块,bit1和bit2构成块的逻辑地址,bit3和bit4构成逻辑块地址与0xaaaa异或的结果,当作坏块判断信息,其余字节为0xff 使用flash标准的读取页函数,发送spare area地址读取任意sector的16字节数据并存于sparebuff[16] 根据传入参数计算出物理页地址和列地址,接着调用ReadSpareData函数来判断块的状态

接下来详细讲一下log_readblockspare()函数。首先它的传入参数有以下几个:
unsigned char ZoneNo:待操作块所处的zone number
unsigned short BlockNo:待操作块为第几个物理块
unsigned char PageNo:待操作的页号
unsigned char SectorNo:待操作的sector号

接着函数实现步骤如下:根据ZoneNo、BlockNo、PageNo、SectorNo参数算出物理地址的页地址和列地址。接着调用ReadSpareData函数比较sparebuffer[0]即块状态BlockStatus,此时分两种情况。
第一种情况是是若sparebuffer[0]≠0xff,再判断厂商标记位sparebuffer[5],若两者都不等于0xff,表明该块很大可能为坏块。为确保正确性利用ECC进行判断,首先将页数据读到flash控制器的缓存区,获得一组新的ECC纠错码,然后将数据读到databuffer[528],然后判断databuffer[512]和databuffer[517]是否同时不等于0xff,则可肯定判断它是坏块,以0x1000作为坏块标记并返回该数值。
第二种情况是sparebuffer[0]=0xff,表明之前软件判断的该块是好块。为确保正确性,调出所在zone的坏块表关于该块的状态,若为0,则坏块表准确。

上面步骤获取到块的好坏状态后,还要判断它是否为空。通过判断sparebuffer[1]和sparebuffer[2]是否都为0xff,是的话就返回空闲块标记0xffff,否则将两者组合成16字节并返回块标记,表明该块为已用块。

下面为log_readblockspare()函数的流程图:
NANDFLASH的学习(三)_第4张图片* 地址映射函数log_mapzone()函数
在逻辑层中构造一个函数用于实现逻辑-物理块地址映射功能。采用lookuptable映射表来实现逻辑-物理块地址的映射。它的的定义为u16 lookuptable[512],总大小为1024字节的数组。*plookuptable指向数组首地址。每一个元素对应一个物理块,元素顺序号可理解为逻辑块地址。由于需要将flash划分为几部分,分别是数据区、交换块区、替换块区和坏块区。映射表指针的分配如下:
*plookuptable:指向第一个好块。
*pbadblock:指向映射表的末尾,即plookuptable[511]。

通过调用坏块信息表,统计出每个zone的坏块数,用二维数组InvldBlkPerZonelnChip[ChipNo][bZone]来表示。另外使用二维数组urReplacelndex[ChipNo][ZoneNo]来表示当前使用的替换块指数。只有CurReplaceIndex[ChipNo][ZoneNo]不0时,才能发生坏块替换,
否则,要重新进行地址映射,分配替换块。

具体函数的实现如下:
1、调用坏块表计算出该zone的坏块数量

NAND_ReadDataToBufferEnableECC0;
if(!ChipNo)
    MemeryCopyFromBuffer(DataBufferBadBlock,64)else
    MemeryCopyFromBuffer(DataBufferBadBlock2,64)

Flpageaddr为存放坏块表地址,由于坏块表是以位状态来代表块状态,“0”代表坏块,所以统计该zone对应的坏块表中有几个0即可算出该zone的坏块数,即变量InvldBlkPerZoneInChip[ChipNo][bZone]的值。

由于时间问题,其它的请参考给出的论文。抱歉。

参考资料:
百度百科
NAND Flash坏块管理算法及逻辑层驱动设计

你可能感兴趣的:(NANDFlash,NANDFLASH)