当前位置:首页 > Windows程序 > 正文

wince系统中对nand坏块的修正

2021-03-27 Windows程序

标签:

  wince系统中对nand坏块的修正 产生坏块的原因是因为NANDFlash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,所以,在NAND
的生产中及使用过程中会产生坏块。
一、坏块的具体表现:  当编程/擦除这个块时,不能将某些位拉高,这会造成Page Program和Block Erase操作时的错误,相应地反映到
Status Register的相应位。
二、坏块的种类:  1.先天性坏块  这种坏块是在生产过程中产生的,一般芯片原厂都会在出厂时都会将坏块第一个page的spare area的第6个byte标记为不等于
0xff的值。
 
2. 后天性坏块  
这种坏块是在NAND Flash使用过程中产生的,如果Block Erase
或者Page Program错误,就可以简单地将这个块作为坏块来处理,这个时候需要把坏块标记起来。为了和先天性坏块信息保持一致,
将新发现的坏块的第一个page的spare area的第6个Byte标记为非0xff的值,这个坏块标记字节的位置不具有通用性,具体以nand的datasheet为准。
 
三、坏块的处理 理解了先天性坏块和后天性坏块后,我们已明白NAND Flash出厂时在spare area中已经反映出了坏块信息,因此,如果在擦除一个块之前,一定要先check一下spare area的第6个byte是否是
0xff,如果是就证明这是一个好块,可以擦除;如果是非0xff,那么就不能擦除。
不过,这样处理可能会错杀伪坏块,因为在芯片操作过程中可能由于电压不稳定等偶然因素会造成NAND操作的错误。但是,为了数据的可靠性及软件设计的简单化,,坏块一个也不能放过。
但是wince为了防止这种伪坏块的浪费,采用了一定的补救措施来进一步验证该坏块为物理坏块还是伪坏块。该部分实现在BOOL WriteFlashReserved(PBYTE  pBuffer, UINT32 dwLength)函数里,具体代码如下:
for (i=0; i < dwSectorSize; i++)
{
// 写入新的Block时, 作一些判断
if (i%g_FlashInfo.wSectorsPerBlock == 0)
{

if (!FMD_ReadSector(dwCurrentWriteBlock*g_FlashInfo.wSectorsPerBlock, NULL, g_pSectorInfoBuf, 1)) 
       {
OALLog(L"Fail read info %d\n", dwCurrentWriteBlock);
       }
RETAILMSG(1, (TEXT("g_pSectorInfoBuf->bBadBlock1 = %d \r\n", g_pSectorInfoBuf->bBadBlock)));//add by zhang , 20150303


//add end


// 算出这个物理block的值
BadBlockCheck:
dwCurrentWriteBlock = dwStartBlock + dwSkipBlock + i/g_FlashInfo.wSectorsPerBlock;
       
// 擦除这个block
    if (!FMD_EraseBlock(dwCurrentWriteBlock)) 
       {
           OALLog(L"Fail erase %d\n", dwCurrentWriteBlock);
           goto BadBlock;         
       }


// 再次读出info
if (!FMD_ReadSector(dwCurrentWriteBlock*g_FlashInfo.wSectorsPerBlock, NULL, g_pSectorInfoBuf, 1)) 
       {
OALLog(L"Fail read info %d\n", dwCurrentWriteBlock);
       goto BadBlock;
       }
            RETAILMSG(1, (TEXT("g_pSectorInfoBuf->bBadBlock2 = %d \r\n", g_pSectorInfoBuf->bBadBlock)));//add by zhang , 20150303
// 擦除后, 再次读出, 却发现bBadBlock不为0xFF, 是物理坏块!
       if ((g_pSectorInfoBuf->bBadBlock != 0xff) || (g_pSectorInfoBuf->bOEMReserved != 0xff))
       {
OALLog(L"Fail oxff %d\n", dwCurrentWriteBlock);
           goto BadBlock;
       }
       
       goto GoodBlock;
       
       BadBlock:
       if (dwCurrentWriteBlock >= LOGO_BLOCK)
       {
           // 在写Logo区时允许坏块
           FMD_SetBlockStatus(dwCurrentWriteBlock, BLOCK_STATUS_BAD);
           
           dwSkipBlock++; //移到下一个Block
           goto BadBlockCheck;
       }
       else
       {
           RETAILMSG(1, (TEXT("WriteFlaseReserved Fail. #%x\n"), dwCurrentWriteBlock));
           return FALSE;
       }
       GoodBlock:
;
}
以上为部分实现代码,红色的部分为我加的串口打印消息,主要是将处理之前和处理之后该块的坏块标记位的值打印出来,以方便观察是否能够将坏块通过处理之后变为好块。
串口打印的消息如下:
CheckSum: eecf
CheckSum Success, USBDownLoadRaw Done
WriteFlashReserved 
g_pSectorInfoBuf->bBadBlock1 = 0 
g_pSectorInfoBuf->bBadBlock2 = 255 
g_pSectorInfoBuf->bBadBlock1 = 0 
g_pSectorInfoBuf->bBadBlock2 = 255 

以上部分是下载EBOOT时候打印的消息,EBOOT占两个block;

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/68329.html