📄 nand.c
字号:
* block block no
* Return
* error code
*/
BOOL Nand_EraseBlock(BLOCK_ID block)
{
BYTE status;
DWORD page;
page = BLOCK_TO_PAGE(block);
NF_nFCE_L();
NF_CMD(CMD_BlockErase_1st);
NF_ADDR_ROW(page);
NF_CMD(CMD_BlockErase_2nd);
NF_WAIT_RnB();
NF_READ_STATUS(status);
NF_nFCE_H();
return NF_STATUS_FAILED(status) ? FALSE : TRUE;
}
//
// Nand_GetBlockStatus
//
// Returns the status of a block. The status information is stored in the spare area of the first sector for
// the respective block.
//
// A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
//
DWORD Nand_GetBlockStatus(BLOCK_ID blockID)
{
SECTOR_ADDR sectorAddr = BLOCK_TO_PAGE(blockID);
SectorInfo SI;
DWORD dwResult = 0;
if(!Nand_ReadPageSpare(sectorAddr, &SI, sizeof(SI)))
{
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;
}
//
// Nand_SetBlockStatus
//
// Sets the status of a block. Only implement for bad blocks for now.
// Returns TRUE if no errors in setting.
//
BOOL Nand_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED | BLOCK_STATUS_BAD))
{
SECTOR_ADDR Sector = BLOCK_TO_PAGE(blockID);
SectorInfo SI;
if (!Nand_ReadPageSpare(Sector, &SI, sizeof(SectorInfo)))
{
return FALSE;
}
if (dwStatus & BLOCK_STATUS_READONLY)
{
SI.bOEMReserved &= ~OEM_BLOCK_READONLY;
}
if (dwStatus & BLOCK_STATUS_RESERVED)
{
SI.bOEMReserved &= ~OEM_BLOCK_RESERVED;
}
if(dwStatus & BLOCK_STATUS_BAD)
{
SI.bBadBlock = 0x00; //0xFF good block, 0x00 bad block
}
if (!Nand_WritePageSpare (Sector, &SI, sizeof(SectorInfo)))
{
return FALSE;
}
return TRUE;
}
return FALSE;
}
/*
* Write a page
*
* Parameter
* block block no
* page page no
* pdata data buffer pointer
* len data buffer length
* Return
* status byte
*/
BOOL Nand_WritePageEx(BLOCK_ID block, SECTOR_ADDR offset_pages, const void *pdata, DWORD len)
{
DWORD pages;
if(len > Nand_PageSize())
{
len = Nand_PageSize();
}
pages = BLOCK_TO_PAGE(block) + offset_pages;
return (AdvFlash == NAND_Advance) ? NF_WriteAdv(pages, 0, pdata, len) : NF_Write(pages, 0, pdata, len);
}
BOOL Nand_WritePage(SECTOR_ADDR absolute_pages, const void *pdata, DWORD len)
{
return (AdvFlash == NAND_Advance) ? NF_WriteAdv(absolute_pages, 0, pdata, len) : NF_Write(absolute_pages, 0, pdata, len);
}
BOOL Nand_WritePageSpare(SECTOR_ADDR absolute_pages, const void *pdata, DWORD len)
{
return (AdvFlash == NAND_Advance) ? NF_WriteSpareAdv(absolute_pages, pdata, len) : NF_WriteSpare(absolute_pages, pdata, len);
}
/*
* Read a page
* block block no
* page page no
* pdata data buffer pointer
* len data buffer length
* Return
* status byte
*/
BOOL Nand_ReadPageEx(BLOCK_ID block, SECTOR_ADDR offset_pages, void *pdata, DWORD len)
{
DWORD pages;
if(len > Nand_PageSize())
{
len = Nand_PageSize();
}
pages = BLOCK_TO_PAGE(block) + offset_pages;
return (AdvFlash == NAND_Advance) ? NF_ReadAdv(pages, 0, pdata, len) : NF_Read(pages, 0, pdata, len);
}
BOOL Nand_ReadPage(SECTOR_ADDR absolute_pages, void *pdata, DWORD len)
{
return (AdvFlash == NAND_Advance) ? NF_ReadAdv(absolute_pages, 0, pdata, len) : NF_Read(absolute_pages, 0, pdata, len);
}
BOOL Nand_ReadPageSpare(SECTOR_ADDR absolute_pages, void *pdata, DWORD len)
{
return (AdvFlash == NAND_Advance) ? NF_ReadSpareAdv(absolute_pages, pdata, len) : NF_ReadSpare(absolute_pages, pdata, len);
}
//----------------------------------------------------------------------------------------
// Nand private methods
//----------------------------------------------------------------------------------------
// Normal mode (512)
static BOOL NF_Write(SECTOR_ADDR pages, DWORD offset_bytes, const void* pdata, DWORD len)
{
return TRUE;
}
static BOOL NF_Read(SECTOR_ADDR pages, DWORD offset_bytes, void* pdata, DWORD len)
{
return TRUE;
}
static BOOL NF_WriteSpare(SECTOR_ADDR pages, const void* pdata, DWORD len)
{
return TRUE;
}
static BOOL NF_ReadSpare(SECTOR_ADDR pages, void* pdata, DWORD len)
{
return TRUE;
}
// Advanced mode (2048)
static BOOL NF_WriteAdv(SECTOR_ADDR pages, DWORD offset_bytes, const void* pdata, DWORD len)
{
BOOL error = FALSE;
BYTE status;
DebugPrintf(("::NF_WriteAdv(pages=%d, offset_bytes=%d, pdata=%p, len=%d)\n", pages, offset_bytes, pdata, len));
if(offset_bytes >= Nand_PageSize())
{
return FALSE;
}
//data len can be write
if(len + offset_bytes > Nand_PageSize())
{
len = Nand_PageSize() - offset_bytes;
}
NF_nFCE_L();
//output command : Program 1st & address & Program 2nd
NF_CMD(CMD_PageProgram_1st);
NF_ADDR_COL(offset_bytes);
NF_ADDR_ROW(pages);
__WrPageBytes(pdata, len);
// for(i=0; i<len; i++)
// {
// NF_WDATA8(*pdata++);
// }
NF_CMD(CMD_PageProgram_2nd);
NF_WAIT_RnB();
NF_READ_STATUS(status);
error = (NF_STATUS_FAILED(status)) ? FALSE : TRUE;
NF_nFCE_H();
return error;
}
static BOOL NF_ReadAdv(SECTOR_ADDR pages, DWORD offset_bytes, void* pdata, DWORD len)
{
BOOL error = FALSE;
DebugPrintf(("::NF_ReadAdv(pages=%d, offset_bytes=%d, pdata=%p, len=%d)\n", pages, offset_bytes, pdata, len));
if(offset_bytes >= Nand_PageSize())
{
return FALSE;
}
//data len can be write
if(len + offset_bytes > Nand_PageSize())
{
len = Nand_PageSize() - offset_bytes;
}
NF_nFCE_L();
//output command : Read 1st & address & Read 2nd
NF_CMD(CMD_Read_1st);
NF_ADDR_COL(offset_bytes);
NF_ADDR_ROW(pages);
NF_CMD(CMD_Read_2nd);
NF_WAIT_RnB();
__RdPageBytes(pdata, len);
// for(i=0; i<len; i++)
// {
// *pdata++ = NF_RDATA8();
// }
//MainECC check
NF_nFCE_H();
error = TRUE;
return error;
}
static BOOL NF_WriteSpareAdv(SECTOR_ADDR pages, const void* pdata, DWORD len)
{
BOOL error = FALSE;
BYTE status;
DebugPrintf(("::NF_WriteSpareAdv(pages=%d, pdata=%p, len=%d)\n", pages, pdata, len));
//data len can be write
if(len > SpareSize)
{
len = SpareSize;
}
NF_nFCE_L();
//output command : Program 1st & address & Program 2nd
NF_CMD(CMD_PageProgram_1st);
NF_ADDR_COL(Nand_PageSize());
NF_ADDR_ROW(pages);
__WrPageBytes(pdata, len);
// for(i=0; i<len; i++)
// {
// NF_WDATA8(*pdata++);
// }
NF_CMD(CMD_PageProgram_2nd);
NF_WAIT_RnB();
NF_READ_STATUS(status);
error = (NF_STATUS_FAILED(status)) ? FALSE : TRUE;
NF_nFCE_H();
return error;
}
static BOOL NF_ReadSpareAdv(SECTOR_ADDR pages, void* pdata, DWORD len)
{
BOOL error = FALSE;
DebugPrintf(("::NF_ReadSpareAdv(pages=%d, pdata=%p, len=%d)\n", pages, pdata, len));
//data len can be write
if(len > SpareSize)
{
len = SpareSize;
}
NF_nFCE_L();
//output command : Read 1st & address & Read 2nd
NF_CMD(CMD_Read_1st);
NF_ADDR_COL(Nand_PageSize());
NF_ADDR_ROW(pages);
NF_CMD(CMD_Read_2nd);
NF_WAIT_RnB();
__RdPageBytes(pdata, len);
// for(i=0; i<len; i++)
// {
// *pdata++ = NF_RDATA8();
// }
//SpareECC check
NF_nFCE_H();
error = TRUE;
return error;
}
BOOL NF_ReadChipInfo(FlashInfo *pFlashInfo)
{
WORD wChipID = Nand_ReadID();
int i;
for(i=0; i< sizeof(ChipID2NumBlocks)/sizeof(ChipID2NumBlocks[0]); i++)
{
if(wChipID == ChipID2NumBlocks[i][0])
{
pFlashInfo->dwNumBlocks = ChipID2NumBlocks[i][1];
return TRUE;
}
}
return FALSE;
}
#ifdef __cplusplus
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -