微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > MCU和DSP > 基于NAND Flash的转译层的设计

基于NAND Flash的转译层的设计

时间:03-11 来源:电子技术应用 点击:

3 NFTL坏块管理设计

3.1 构建BBI表

用一数组FlashBadBlockTable[2][FLASH_BAD_BLOCKS_REMAP]存放BBI表。第一维为坏块(数据区)的块地址,第二维为映射块地址(重映块)。

BBI表的构建可在Flash首次上电时,通过读取厂商设置在Flash备用区中的坏块标记识别坏块,建立坏块映射表,此法初始化时间与Flash的容量成正比;或通过读NAND Flash所有块内容并和0xFF作比较[3],如果不相同,则表示坏块。这种方法只针对新闪存,并且构建BBI表的时间长,主控芯片的占用率高;另一种方法是在Flash初次上电时先不建立坏块表,认为当前所有的块都是好块,在随后操作中发现坏块,并更新BBI表。本文选择后一种方法。

3.2 坏块映射表区的设计

将BBI表通过特殊的方式保存,以后通过此种方式的逆向来识别BBI表。坏块映射表区的3个块的设计方法如下:

(1)在每块最后一页的首字节处做特殊标记,用于标识该块有没有准备被擦除:0xFF表示没有准备被擦除;0x00表示该块已经准备被擦除[4]。
(2)在每块的倒数第二页的首字节处写0x00,表示该块存放BBI表数据;并在第2、3、4、5个字节处以大端模式存放校验和,用于校验该块中存放的所有数据的正确性。该页的剩余字节写0xFF。
(3)在第一页起依次写:表头特殊标记(0x0055AAFF)、坏块总数(FlashBadBlockCount)、BBI表(FlashBadBlockTable)、重映块状态(FlashRemapBlockStatus),其结构如图3所示。

3.3 逻辑地址映射

在与主机批量数据传输时,首先对主机发送的CBW命令解析,从而固件获得主机请求数据传输的LBA,再对LBA地址映射以此获得相应的PBA,然后再执行主机命令。具体方法:首先读取当前总的坏块数FlashBadBlocksCount,如果为0,表示无坏块,LBA就不用映射,直接返回;如果最后一次访问地址与LBA同属于一个块,那么也不用地址映射;如果当前坏块的数量为1,判断LBA块地址与BBI表中坏块地址是否相同,从而决定是否采取地址映射;如果当前坏块的数量不为1,就需要查找BBI表判断是不是含有LBA的块地址,如果存在,则要地址重新映射,如果不存在,就不用重新映射。可以采用二分法查表实现两地址快速比较[4]。

3.4 坏块处理

对映射后的地址进行写或擦除过程中发现当前块变坏的处理方法:首先查找映射区中的块状态FlashRemapBlockStatus[FLASH_BAD_BLOCKS_REMAP],寻找可用的映射块。如果50个重映块都被标记为坏或已使用,则程序进入死循环;如果找到可用的映射块,则固件对可能出现坏块的三种情况进行散转:(1)擦除当前块时出错:将当前块地址与可用的重映块地址写入BBI表中,按地址大小排列有利于二分法查表,并返回重映块地址。(2)复制某页从交换区到操作地址时失败:首先获得当前使用的交换块的块地址,然后判断操作地址是在数据存储区还是在重映区。如果在重映区,说明当前操作地址所对应的在数据存储区中的块已经是坏块,并且在这次操作中重映块也变坏,此时就应该标记当前映射块状态为坏,并在重映区中寻找下一个可用重映块,将原来在数据存储区中的块地址与更新后的映射块地址写入BBI表中,并返回新的映射后的地址;如果在数据存储区,就进行第一次重映射,更新坏块表,并且将映射地址返回。然后再完成复制工作。(3)向操作地址写一页数据时出错:将当前地址所在块中的前面页从交换块中相应地址复制到重映块,然后将操作地址所在当前页中的没有写到的数据从交换块中复制,并将缓冲区中的数据重新写到重映射的地址中,并返回重映射地址。函数实现如下:

DWORD FlashDealBadBlock(DWORD Addr,DWORD Type)
{
DWORD i;
DWORD RemapBlockAddr;
DWORD SwapBlockAddr;
while(1)
{
RemapBlockAddr=FlashGetNewRemapBlock();
if(RemapBlockAddr==-1)
return Addr;
switch(Type)
{ case 1:
goto Exit;
break;
case 2:
SwapBlockAddr=FlashGetCurrentSwapBlock();
for(i=0;i<(Addr&(FLASH_BLOCK_SIZE-1))/
FLASH_PAGE_SIZE+1;i++)
{
if(0x00==(FlashCopyPage(SwapBlockAddr+
i*FLASH_PAGE_SIZE,RemapBlockAddr+
i*FLASH_PAGE_SIZE)))
goto BadRemapBlock;
}
goto Exit;
break;
case 3:
SwapBlockAddr=FlashGetCurrentSwapBlock();
for(i=0;i<(Addr&(FLASH_BLOCK_SIZE-1))/
FLASH_PAGE_SIZE;i++)
{
if(0x00==(FlashCopyPage(SwapBlockAddr+
i*FLASH_PAGE_SIZE,RemapBlockAddr+
i*FLASH_PAGE_SIZE)))
goto BadRemapBlock;
}
if(0x00==(FlashCopyPage(Addr,RemapBlockAddr+
i*FLASH_PAGE_SIZE)))
goto BadRemapBlock;
goto Exit;
break;
default:
break;
}
BadRemapBlock: FlashMarkRemapBlockBad
(RemapBlockAddr);
}
Exit:FlashUpdateBadBlockTable(Addr,RemapBlockAddr);
return RemapBlockAddr+(Addr&(FLASH_BLOCK_SIZE-1));
}

3.5 连续读写操作

当主机与设备建立批量传输数据连接时,固件通过解析CBW封包获得起始LBA。对该地址进行映射和坏块管理从而获得PBA。设置一个变量,当此变量有效时,表示主机对Flash仍需要读或写数据,直到此变量失效为止。同时将主机上一次读写扇区的地址存入另一个变量,此变量在连续读中作用不大,但在连续写时,通过与上一次写操作地址所在块做比较,判断是否同属一个块,以此决定是不是需要进行地址跨块处理。

本文设计了一种针对NAND型的闪存转译层,使NFTL完成地址映射和坏块管理以及连续读写数据的操作。对NAND Flash的分区设计,使块管理结构清晰,有利于固件的开发。本文没有对Flash的ECC校验进行过多的设计,这是因为在实际应用中NAND Flash主要用于存储多媒体数据(图片、语音文件)等,并不会对它进行频繁的写入或擦除操作,而且多媒体文件数据对数据的完整性不敏感[5],所以不需要对存储在其中的每一位数据进行严格的ECC校验,可以通过另外设计简单的校验方法来代替ECC校验。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top