Nandflash 驱动移植 (六)
Nandflash驱动移植系列文章导航: Nandflash 驱动移植 (一) Nandflash 驱动移植 (二) Nandflash 驱动移植 (三) Nandflash 驱动移植 (四) Nandflash 驱动移植 (五) Nandflash 驱动移植 (六) 一共六篇 ? ? ? 近段时间比较忙,接着上一篇,这篇主要介绍到写的部分 ? 1、FMD_LB_WriteSector()? MLC写sector BOOL FMD_LB_WriteSector(SECTOR_ADDR startSectorAddr,LPBYTE pSectorBuff,PSectorInfo pSectorInfoBuff,DWORD dwNumSectors) { DWORD i; BOOL bRet = TRUE; volatile DWORD wrdata; DWORD MECCBuf[16]; // 16 gjl UINT16 nSectorLoop; int NewSpareAddr = 4096; // 2048 gjl int NewDataAddr = 0; int NewSectorAddr = startSectorAddr; #if CHECK_SPAREECC DWORD SECCBuf[4]; // 2 gjl #endif #if (NAND_DEBUG) RETAILMSG(1,(TEXT("FMD::FMD_LB_WriteSector 0x%x n"),startSectorAddr)); #endif if (!pSectorBuff && !pSectorInfoBuff) return(FALSE); if ( dwNumSectors > 1 ) { RETAILMSG(1,(TEXT("######## FATAL ERROR => FMD::FMD_WriteSector->dwNumsectors is bigger than 1. n"))); return FALSE; } if (!pSectorBuff) { NAND_LB_WriteSectorInfo(startSectorAddr,pSectorInfoBuff); return TRUE; } // Enable Chip NF_nFCE_L(); NF_CLEAR_RB(); // Issue command NF_CMD(CMD_WRITE); // Setup address NF_ADDR((NewDataAddr)&0xff); NF_ADDR((NewDataAddr>>8)&0xff); NF_ADDR((NewSectorAddr)&0xff); NF_ADDR((NewSectorAddr>>8)&0xff); #if LB_NEED_EXT_ADDR NF_ADDR((NewSectorAddr>>16)&0xff); #endif for (nSectorLoop = 0; nSectorLoop < SECTORS_PER_PAGE; nSectorLoop++) { // Initialize ECC register NF_MSGLENGTH_512(); NF_ECCTYPE_4BIT(); NF_RSTECC(); NF_MECC_UnLock(); // Special case to handle un-aligned buffer pointer. // if( ((DWORD) (pSectorBuff+nSectorLoop*SECTOR_SIZE)) & 0x3) { // Write the data for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++) { wrdata = (pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+0]; wrdata |= (pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+1]<<8; wrdata |= (pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+2]<<16; wrdata |= (pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+3]<<24; NF_WRDATA_WORD(wrdata); } } else { WrPage512(pSectorBuff+nSectorLoop*SECTOR_SIZE); } // Read out the ECC value generated by HW NF_MECC_Lock(); //encode done while (!(NF_RDSTAT & (1<<7))); MECCBuf[2*nSectorLoop] = NF_RDMECC0(); MECCBuf[2*nSectorLoop+1] = NF_RDMECC1(); #if DEBUG_WRITE_READ_EQUAL g_MECCBuf[2*nSectorLoop] = MECCBuf[2*nSectorLoop]; g_MECCBuf[2*nSectorLoop+1] = MECCBuf[2*nSectorLoop+1]; #endif } NF_CMD(CMD_RDI); NF_ADDR((NewSpareAddr)&0xff); NF_ADDR((NewSpareAddr>>8)&0xff); // Write the SectorInfo data to the media // NOTE: This hardware is odd: only a byte can be written at a time and it must reside in the // upper byte of a USHORT. if(pSectorInfoBuff) { // Write the first reserved field (DWORD) NF_WRDATA_BYTE(pSectorInfoBuff->bBadBlock); NF_WRDATA_WORD(pSectorInfoBuff->dwReserved1); NF_WRDATA_BYTE(pSectorInfoBuff->bOEMReserved); NF_WRDATA_BYTE(pSectorInfoBuff->wReserved2&0xff); NF_WRDATA_BYTE((pSectorInfoBuff->wReserved2>>8)&0xff); } else { // Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data) for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++) { NF_WRDATA_WORD(0xffffffff); } } // Write the ECC value to the flash for (nSectorLoop = 0; nSectorLoop < SECTORS_PER_PAGE*2; nSectorLoop++) NF_WRDATA_WORD(MECCBuf[nSectorLoop]); // Finish up the write operation NF_CMD(CMD_WRITE2); // Wait for RB NF_DETECT_RB(); // Wait tR(max 12us) if ( NF_RDSTAT & STATUS_ILLACC ) { RETAILMSG(1,(TEXT("FMD_WriteSector() ######## Error Programming page (Illigar Access) %d!n"),startSectorAddr)); g_pNFConReg->NFSTAT = STATUS_ILLACC; // Write 1 to clear. bRet = FALSE; } else { // Check the status NF_CMD(CMD_STATUS); if(NF_RDDATA_BYTE() & STATUS_ERROR) { RETAILMSG(1,(TEXT("FMD_WriteSector() ######## Error Programming page %d!n"),startSectorAddr)); bRet = FALSE; } } // Disable the chip NF_nFCE_H(); return bRet; } 这个是飞凌的源码,这里需要修改成8bit的ECC。 变量定义这里需要把 DWORD MECCBuf[16]; 修改成: DWORD MECCBuf[32];
操作之前,添加使能中断的操作: g_pNFConReg->NFCONT |= (1<<10); // Enable illegal access interrupt control g_pNFConReg->NFCONT |= (1<<9); // Enable RnB interrupt
把 ??????? NF_MSGLENGTH_512(); 中的 NF_ECCTYPE_4BIT(); 修改成: NF_ECCTYPE_8BIT(); NF_ECC_8BIT_STOP(); NF_ECC_DIRECTION_OUT();
//encode done 处理的后面,把 ??????? MECCBuf[2*nSectorLoop] = NF_RDMECC0(); 修改成: MECCBuf[4*nSectorLoop] = NF_RDM8ECC0(); MECCBuf[4*nSectorLoop+1] = NF_RDM8ECC1(); MECCBuf[4*nSectorLoop+2] = NF_RDM8ECC2(); MECCBuf[4*nSectorLoop+3] = NF_RDM8ECC3() & 0xff;
NF_CMD(CMD_RDI); 操作之前,添加: NF_ECCTYPE_8BIT(); NF_ECC_8BIT_STOP();
??? //? Write the ECC value to the flash 这里需要把for修改成: for (nSectorLoop = 0; nSectorLoop < SECTORS_PER_PAGE*4; nSectorLoop++)
?? //? Disable the chip 之前添加: g_pNFConReg->NFCONT &= ~(1<<10); // Disable illegal access interrupt control g_pNFConReg->NFCONT &= ~(1<<9); // Disable RnB interrupt
? ? ? 2、NAND_LB_WriteSectorInfo()?? 写sector信息 BOOL NAND_LB_WriteSectorInfo(SECTOR_ADDR sectorAddr,PSectorInfo pInfo) { BOOL bRet = TRUE; int NewSpareAddr = 4096; // gjl 2048 int NewSectorAddr = sectorAddr; #if CHECK_SPAREECC DWORD SECCBuf[4]; // gjl 2 #endif // Chip enable NF_nFCE_L(); NF_CLEAR_RB(); // Write the command // First,let's point to the spare area NF_CMD(CMD_WRITE); // Write the address NF_ADDR((NewSpareAddr)&0xff); NF_ADDR((NewSpareAddr>>8)&0xff); NF_ADDR((NewSectorAddr)&0xff); NF_ADDR((NewSectorAddr>>8)&0xff); #if LB_NEED_EXT_ADDR NF_ADDR((NewSectorAddr>>16)&0xff); #endif NF_MSGLENGTH_512(); NF_ECCTYPE_4BIT(); // Now let's write the SectorInfo data // // Write the first reserved field (DWORD) NF_WRDATA_BYTE(pInfo->bBadBlock); NF_WRDATA_WORD(pInfo->dwReserved1); NF_WRDATA_BYTE(pInfo->bOEMReserved); NF_WRDATA_BYTE(pInfo->wReserved2&0xff); NF_WRDATA_BYTE((pInfo->wReserved2>>8)&0xff); NF_WRDATA_WORD(0xffffffff); // Mecc[0] NF_WRDATA_WORD(0xffffffff); // Mecc[1] NF_WRDATA_WORD(0xffffffff); // Mecc[2] NF_WRDATA_WORD(0xffffffff); // Mecc[3] NF_WRDATA_WORD(0xffffffff); // Mecc[4] NF_WRDATA_WORD(0xffffffff); // Mecc[5] NF_WRDATA_WORD(0xffffffff); // Mecc[6] NF_WRDATA_WORD(0xffffffff); // Mecc[7] // Issue the write complete command NF_CMD(CMD_WRITE2); // Check ready bit NF_DETECT_RB(); // Wait tR(max 12us) if ( NF_RDSTAT & STATUS_ILLACC ) { RETAILMSG(1,(TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page (Illigar Access) %d!n"),sectorAddr)); g_pNFConReg->NFSTAT = STATUS_ILLACC; // Write 1 to clear. bRet = FALSE; } else { // Check the status of program NF_CMD(CMD_STATUS); if( NF_RDDATA_BYTE() & STATUS_ERROR) { RETAILMSG(1,(TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page %d!n"),sectorAddr)); bRet = FALSE; } } NF_nFCE_H(); return bRet; } 这个是飞凌给的源码,从上面可以看出也是只用到了4bit的ECC。下面我们将其改成8bit的ECC: 看到 这两个处理,我们把其中的 NF_ECCTYPE_4BIT(); 修改成 NF_ECCTYPE_8BIT(); // use 8bit ECC type NF_ECC_8BIT_STOP(); // init 8bit ECC decoding
这里需要修改成: // 16 byte Sector0 ECC data NF_WRDATA_WORD(0xffffffff); // Mecc[0] NF_WRDATA_WORD(0xffffffff); // Mecc[1] NF_WRDATA_WORD(0xffffffff); // Mecc[2] NF_WRDATA_WORD(0xffffffff); // Mecc[3] // 16 byte Sector1 ECC data NF_WRDATA_WORD(0xffffffff); // Mecc[4] NF_WRDATA_WORD(0xffffffff); // Mecc[5] NF_WRDATA_WORD(0xffffffff); // Mecc[6] NF_WRDATA_WORD(0xffffffff); // Mecc[7] // 16 byte Sector2 ECC data NF_WRDATA_WORD(0xffffffff); // Mecc[8] NF_WRDATA_WORD(0xffffffff); // Mecc[9] NF_WRDATA_WORD(0xffffffff); // Mecc[10] NF_WRDATA_WORD(0xffffffff); // Mecc[11] // 16 byte Sector3 ECC data NF_WRDATA_WORD(0xffffffff); // Mecc[12] NF_WRDATA_WORD(0xffffffff); // Mecc[13] NF_WRDATA_WORD(0xffffffff); // Mecc[14] NF_WRDATA_WORD(0xffffffff); // Mecc[15] // 16 byte Sector4 ECC data NF_WRDATA_WORD(0xffffffff); // Mecc[16] NF_WRDATA_WORD(0xffffffff); // Mecc[17] NF_WRDATA_WORD(0xffffffff); // Mecc[18] NF_WRDATA_WORD(0xffffffff); // Mecc[19] // 16 byte Sector5 ECC data NF_WRDATA_WORD(0xffffffff); // Mecc[20] NF_WRDATA_WORD(0xffffffff); // Mecc[21] NF_WRDATA_WORD(0xffffffff); // Mecc[22] NF_WRDATA_WORD(0xffffffff); // Mecc[23] // 16 byte Sector6 ECC data NF_WRDATA_WORD(0xffffffff); // Mecc[24] NF_WRDATA_WORD(0xffffffff); // Mecc[25] NF_WRDATA_WORD(0xffffffff); // Mecc[26] NF_WRDATA_WORD(0xffffffff); // Mecc[27] // 16 byte Sector7 ECC data NF_WRDATA_WORD(0xffffffff); // Mecc[28] NF_WRDATA_WORD(0xffffffff); // Mecc[29] NF_WRDATA_WORD(0xffffffff); // Mecc[30] NF_WRDATA_WORD(0xffffffff); // Mecc[31]
这里之所以这样修改,是因为每512字节的主数据就产生4*4字节的ECC,而我们这里每个block有4096字节,即8个512字节,也就是8 * 16个字节的ECC数据。 ? ? ? 3、FMD_SB_WriteSector() BOOL FMD_SB_WriteSector(SECTOR_ADDR startSectorAddr,DWORD dwNumSectors) { BYTE Status; ULONG SectorAddr = (ULONG)startSectorAddr; ULONG MECC; if (!pSectorBuff && !pSectorInfoBuff) return(FALSE); #if (NAND_DEBUG) RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_sbwrite n"))); #endif NF_nFCE_L(); // Select the flash chip. while (dwNumSectors--) { if (!pSectorBuff) // Only spare area { // If we are asked just to write the SectorInfo,we will do that separately NF_CMD(CMD_READ2); // Send read command. NF_CMD(CMD_WRITE); // Send write command. NF_ADDR(0); // Column = 0. NF_ADDR(SectorAddr & 0xff); // Page address. NF_ADDR((SectorAddr >> 8) & 0xff); #if SB_NEED_EXT_ADDR NF_ADDR((SectorAddr >> 16) & 0xff); #endif // Write the SectorInfo data to the media. // Spare area[7:0] WrPageInfo((PBYTE)pSectorInfoBuff); NF_CLEAR_RB(); NF_CMD(CMD_WRITE2); // Send write confirm command. NF_DETECT_RB(); NF_CMD(CMD_STATUS); Status = NF_RDDATA_BYTE(); // Read command status. if (Status & STATUS_ERROR) { NF_nFCE_H(); // Deselect the flash chip. //SetKMode (bLastMode); return(FALSE); } pSectorInfoBuff++; } else // Main area+Spare area. { NF_CMD(CMD_READ); // Send read command. NF_CMD(CMD_WRITE); // Send write command. NF_ADDR(0); // Column = 0. NF_ADDR(SectorAddr & 0xff); // Page address. NF_ADDR((SectorAddr >> 8) & 0xff); #if SB_NEED_EXT_ADDR NF_ADDR((SectorAddr >> 16) & 0xff); #endif // Special case to handle un-aligned buffer pointer. NF_RSTECC(); NF_MECC_UnLock(); if( ((DWORD) pSectorBuff) & 0x3) { WrPage512Unalign (pSectorBuff); } else { WrPage512(pSectorBuff); // Write page/sector data. } NF_MECC_Lock(); // Write the SectorInfo data to the media. // Spare area[7:0] if(pSectorInfoBuff) { WrPageInfo((PBYTE)pSectorInfoBuff); pSectorInfoBuff++; } else // Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data) { BYTE TempInfo[] = {0xFF,0xFF,0xFF}; WrPageInfo(TempInfo); } // Write the SectorInfo data to the media. // Spare area[11:8] // Get the ECC data from status register. MECC = NF_RDMECC0(); // Now,Write the ECC data to Spare area[11:8] NF_WRDATA_BYTE((UCHAR)((MECC ) & 0xff)); // Spare area offset 8 NF_WRDATA_BYTE((UCHAR)((MECC >> 8) & 0xff)); // Spare area offset 9 NF_WRDATA_BYTE((UCHAR)((MECC >> 16) & 0xff)); // Spare area offset 10 NF_WRDATA_BYTE((UCHAR)((MECC >> 24) & 0xff)); // Spare area offset 11 NF_CLEAR_RB(); NF_CMD(CMD_WRITE2); // Send write confirm command. NF_DETECT_RB(); do { NF_CMD(CMD_STATUS); Status = NF_RDDATA_BYTE(); // Read command status. }while(!(Status & STATUS_READY)); if (Status & STATUS_ERROR) { NF_nFCE_H(); // Deselect the flash chip. return(FALSE); } pSectorBuff += NAND_SECTOR_SIZE; } ++SectorAddr; } NF_nFCE_H(); // Deselect the flash chip. return(TRUE); }
? ? ? 4、FMD_LB_EraseBlock()?? 擦出块 BOOL FMD_LB_EraseBlock(BLOCK_ID blockID) { BOOL bRet = TRUE; DWORD dwPageID = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK; #if (NAND_DEBUG) RETAILMSG(1,(TEXT("FMD_LB_EraseBlock 0x%x n"),blockID)); #endif // Enable the chip NF_nFCE_L(); // Select the flash chip. NF_CLEAR_RB(); NF_MSGLENGTH_512(); // Issue command NF_CMD(CMD_ERASE); // Set up address NF_ADDR((dwPageID) & 0xff); NF_ADDR((dwPageID >> 8) & 0xff); #if LB_NEED_EXT_ADDR NF_ADDR((dwPageID >> 16) & 0xff); #endif // Complete erase operation NF_CMD(CMD_ERASE2); // Wait for ready bit NF_DETECT_RB(); // Wait tR(max 12us) if ( NF_RDSTAT & STATUS_ILLACC ) { RETAILMSG(1,(TEXT("LB######## Error Erasing block (Illigar Access) %d!n"),blockID)); g_pNFConReg->NFSTAT = STATUS_ILLACC; // Write 1 to clear. bRet = FALSE; } else { // Check the status NF_CMD(CMD_STATUS); if( NF_RDDATA_BYTE() & STATUS_ERROR) { RETAILMSG(1,(TEXT("LB######## Error Erasing block %d!n"),blockID)); bRet = FALSE; } } NF_nFCE_H(); // Select the flash chip. return bRet; } 上述是飞凌的源码,这里我们需要稍作修改。 在使能片选?NF_nFCE_L();? 之前,我们需要使能一些中断: g_pNFConReg->NFCONT |= (1<<10); // Enable illegal access interrupt control g_pNFConReg->NFCONT |= (1<<9); // Enable RnB interrupt
g_pNFConReg->NFCONT &= ~(1<<10); // Disable illegal access interrupt control g_pNFConReg->NFCONT &= ~(1<<9); // Disable RnB interrupt ? ? ? 5、FMD_SB_EraseBlock() BOOL FMD_SB_EraseBlock(BLOCK_ID blockID) { BOOL bRet = TRUE; DWORD dwPageID = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK; // Enable the chip NF_nFCE_L(); // Select the flash chip. // Issue command NF_CMD(CMD_ERASE); // Set up address NF_ADDR((dwPageID) & 0xff); NF_ADDR((dwPageID >> 8) & 0xff); #if SB_NEED_EXT_ADDR NF_ADDR((dwPageID >> 16) & 0xff); #endif NF_CLEAR_RB(); // Complete erase operation NF_CMD(CMD_ERASE2); // Wait for ready bit NF_DETECT_RB(); // Wait tR(max 12us) if ( NF_RDSTAT & STATUS_ILLACC ) { RETAILMSG(1,(TEXT("SB######## Error Erasing block (Illigar Access) %d!n"),(TEXT("SB######## Error Erasing block %d!n"),blockID)); bRet = FALSE; } } NF_nFCE_H(); // Select the flash chip. return bRet; }
? ? ? 6、FMD_LB_GetBlockStatus()? MLC获取块的状态 DWORD FMD_LB_GetBlockStatus(BLOCK_ID blockID) { BLOCK_ID blockID_bad = blockID + 1; SECTOR_ADDR sectorAddr = (blockID_bad << LB_NAND_LOG_2_PAGES_PER_BLOCK) - 1; SectorInfo SI; DWORD dwResult = 0; //RETAILMSG(1,(TEXT("FMD_LB_GetBlockStatus (0x%x)0x%x n"),blockID,sectorAddr)); if(!FMD_LB_ReadSector(sectorAddr,NULL,&SI,1)) { return BLOCK_STATUS_UNKNOWN; } if(!(SI.bOEMReserved & OEM_BLOCK_READONLY)) { dwResult |= BLOCK_STATUS_READONLY; } if (!(SI.bOEMReserved & OEM_BLOCK_RESERVED)) { dwResult |= BLOCK_STATUS_RESERVED; } if(SI.bBadBlock != 0xFF) { dwResult |= BLOCK_STATUS_BAD; } return dwResult; }
? ? 7、FMD_SB_GetBlockStatus()? SLC读取块状态 DWORD FMD_SB_GetBlockStatus(BLOCK_ID blockID) { SECTOR_ADDR sectorAddr = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK; SectorInfo SI; DWORD dwResult = 0; //RETAILMSG(1,(TEXT("FMD_SB_GetBlockStatus (0x%x)0x%x n"),sectorAddr)); if(!FMD_SB_ReadSector(sectorAddr,1)) { return BLOCK_STATUS_UNKNOWN; } if(!(SI.bOEMReserved & OEM_BLOCK_READONLY)) { dwResult |= BLOCK_STATUS_READONLY; } if(SI.bBadBlock != 0xFF) { dwResult |= BLOCK_STATUS_BAD; } return dwResult; }
? ? 8、FMD_LB_SetBlockStatus()、FMD_SB_SetBlockStatus()? 设置块的状态 BOOL FMD_LB_SetBlockStatus(BLOCK_ID blockID,DWORD dwStatus) { BYTE bStatus = 0; if(dwStatus & BLOCK_STATUS_BAD) { if(!LB_MarkBlockBad (blockID)) { return FALSE; } } // We don't currently support setting a block to read-only,so fail if request is // for read-only and block is not currently read-only. if(dwStatus & BLOCK_STATUS_READONLY) { if(!(FMD_LB_GetBlockStatus(blockID) & BLOCK_STATUS_READONLY)) { return FALSE; } } return TRUE; } BOOL FMD_SB_SetBlockStatus(BLOCK_ID blockID,DWORD dwStatus) { SECTOR_ADDR sectorAddr = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK; BYTE bStatus = 0; //RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_sbsetblock n"))); if(dwStatus & BLOCK_STATUS_BAD) { if(!SB_MarkBlockBad (blockID)) { return FALSE; } } // We don't currently support setting a block to read-only,so fail if request is // for read-only and block is not currently read-only. if(dwStatus & BLOCK_STATUS_READONLY) { if(!(FMD_SB_GetBlockStatus(blockID) & BLOCK_STATUS_READONLY)) { return FALSE; } } return TRUE; }
? ? 9、LB_MarkBlockBad()、SB_MarkBlockBad()?? 标记坏块 BOOL LB_MarkBlockBad(BLOCK_ID blockID) { BLOCK_ID blockID_bad = blockID + 1; DWORD dwStartPage = (blockID_bad << LB_NAND_LOG_2_PAGES_PER_BLOCK) - 1; BOOL bRet = TRUE; // RETAILMSG(1,(TEXT("LB_MarkBlockBad 0x%x n"),dwStartPage)); // Enable chip NF_nFCE_L(); NF_CLEAR_RB(); NF_MSGLENGTH_512(); // Issue command // We are dealing with spare area NF_CMD(CMD_WRITE); // Set up address NF_ADDR((4096+LB_POS_BADBLOCK)&0xff); // gjl 2048 NF_ADDR(((4096+LB_POS_BADBLOCK)>>8)&0xff); // gjl 2048 NF_ADDR((dwStartPage) & 0xff); NF_ADDR((dwStartPage >> 8) & 0xff); #if LB_NEED_EXT_ADDR NF_ADDR((dwStartPage >> 16) & 0xff); #endif NF_WRDATA_BYTE(BADBLOCKMARK); // Copmlete the write NF_CMD(CMD_WRITE2); // Wait for RB NF_DETECT_RB(); // Wait tR(max 12us) if ( NF_RDSTAT & STATUS_ILLACC ) { RETAILMSG(1,(TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page (Illigar Access) %d!n"))); g_pNFConReg->NFSTAT = STATUS_ILLACC; // Write 1 to clear. bRet = FALSE; } else { // Check the status of program NF_CMD(CMD_STATUS); if( NF_RDDATA_BYTE() & STATUS_ERROR) { RETAILMSG(1,(TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page %d!n"))); bRet = FALSE; } } // Disable chip select NF_nFCE_H(); return bRet; } BOOL SB_MarkBlockBad(BLOCK_ID blockID) { DWORD dwStartPage = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK; BOOL bRet = TRUE; //RETAILMSG(1,(TEXT("SB_MarkBlockBad 0x%x n"),dwStartPage)); // Enable chip NF_nFCE_L(); NF_CLEAR_RB(); // Issue command // We are dealing with spare area NF_CMD(CMD_READ2); NF_CMD(CMD_WRITE); // Set up address NF_ADDR(SB_POS_BADBLOCK); NF_ADDR((dwStartPage) & 0xff); NF_ADDR((dwStartPage >> 8) & 0xff); #if SB_NEED_EXT_ADDR NF_ADDR((dwStartPage >> 16) & 0xff); #endif NF_WRDATA_BYTE(BADBLOCKMARK); // Copmlete the write NF_CMD(CMD_WRITE2); // Wait for RB NF_DETECT_RB(); // Wait tR(max 12us) if ( NF_RDSTAT & STATUS_ILLACC ) { RETAILMSG(1,(TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page %d!n"))); bRet = FALSE; } } // Disable chip select NF_nFCE_H(); return bRet; }
? ? 10、LB_IsBlockBad()、SB_IsBlockBad()? 判断是否为坏块 BOOL LB_IsBlockBad(BLOCK_ID blockID) { BLOCK_ID blockID_bad = blockID + 1; DWORD dwPageID = (blockID_bad << LB_NAND_LOG_2_PAGES_PER_BLOCK) - 1; BOOL bRet = FALSE; BYTE wFlag; // Enable the chip NF_nFCE_L(); NF_CLEAR_RB(); NF_MSGLENGTH_512(); // Issue the command NF_CMD(CMD_READ); // Set up address NF_ADDR((4096+LB_POS_BADBLOCK)&0xff); //gjl 2048 NF_ADDR(((4096+LB_POS_BADBLOCK)>>8)&0xff); // gjl 2048 NF_ADDR((dwPageID) & 0xff); NF_ADDR((dwPageID >> 8) & 0xff); #if LB_NEED_EXT_ADDR NF_ADDR((dwPageID >> 16) & 0xff); #endif NF_CMD(CMD_READ3); // Wait for Ready bit NF_DETECT_RB(); // Wait tR(max 12us) // Now get the byte we want wFlag = (BYTE)(NF_RDDATA_BYTE()&0xff); if(wFlag != 0xff) { RETAILMSG(1,(TEXT("FMDLB: IsBlockBad - Page #: 0x%x n"),dwPageID)); bRet = TRUE; } // Disable the chip NF_nFCE_H(); return bRet; } BOOL SB_IsBlockBad(BLOCK_ID blockID) { DWORD dwPageID = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK; BOOL bRet = FALSE; BYTE wFlag; //RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_sbisblockbad n"))); // Enable the chip NF_nFCE_L(); NF_CLEAR_RB(); // Issue the command NF_CMD(CMD_READ2); // Set up address NF_ADDR(SB_POS_BADBLOCK); NF_ADDR((dwPageID) & 0xff); NF_ADDR((dwPageID >> 8) & 0xff); #if SB_NEED_EXT_ADDR NF_ADDR((dwPageID >> 16) & 0xff); #endif // Wait for Ready bit NF_DETECT_RB(); // Wait tR(max 12us) // Now get the byte we want wFlag = (BYTE) NF_RDDATA_BYTE(); if(wFlag != 0xff) { RETAILMSG(1,(TEXT("FMDSB: IsBlockBad - Page #: 0x%x n"),dwPageID)); bRet = TRUE; } // Disable the chip NF_nFCE_H(); return bRet; }
时间比较仓促,这个Nandflash移植系列的就到这里结束了。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |