📄 fmd.cpp
字号:
}
VOID FMD_PowerUp(VOID)
{
// Enable the clock to NAND controller
s2440CLKPWR->CLKCON |= (1<<4);
// Reinit the NAND controller
s2440NAND->NFCONF = (TACLS << 12) | /* CLE & ALE = HCLK * (TACLS + 1) */
(TWRPH0 << 8) | /* TWRPH0 = HCLK * (TWRPH0 + 1) */
(TWRPH1 << 4) | /* TWRPH1 = HCLK * (TWRPH1 + 1) */
(g_pNandFlashChip->is16BitSize);
s2440NAND->NFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);
s2440NAND->NFSTAT = 0;
NF_Reset();
}
VOID FMD_PowerDown(VOID)
{
// Disable the clock to NAND controller
s2440CLKPWR->CLKCON &= ~(1<<4);
}
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
return(TRUE);
}
BOOL FMD_Deinit(PVOID hFMD)
{
return(TRUE);
}
/*
@func BOOL | FMD_GetInfo | Provides information on the NAND flash.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
if (!pFlashInfo)
return(FALSE);
pFlashInfo->flashType = NAND;
pFlashInfo->wDataBytesPerSector = NAND_PAGE_SIZE;
pFlashInfo->dwNumBlocks = NAND_BLOCK_CNT;
pFlashInfo->wSectorsPerBlock = NAND_PAGE_CNT;
pFlashInfo->dwBytesPerBlock = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
return(TRUE);
}
BOOL IsBlockBad(BLOCK_ID blockID)
{
if(g_pNandFlashChip)
return g_pNandFlashChip->pIsBlockBad(blockID);
return FALSE;
}
/*
@func DWORD | FMD_GetBlockStatus | Returns the status of the specified block.
@rdesc Block status (see fmd.h).
@comm
@xref
*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
SECTOR_ADDR Sector = (blockID * NAND_PAGE_CNT);
SectorInfo SI;
DWORD dwResult = 0;
if (IsBlockBad(blockID))
return BLOCK_STATUS_BAD;
if (!FMD_ReadSector(Sector, 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;
return(dwResult);
}
/*
@func BOOL | MarkBlockBad | Marks the specified block as bad.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
static BOOL MarkBlockBad(BLOCK_ID blockID)
{
if(g_pNandFlashChip)
return g_pNandFlashChip->pMarkBlockBad(blockID);
return FALSE;
}
/*
@func BOOL | FMD_SetBlockStatus | Marks the block with the specified block status.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
#ifdef BOOT_LOADER
EdbgOutputDebugString("FMD_SetBlockStatus:block:%d,status:%d \r\n",blockID,dwStatus);
#else
RETAILMSG(1,(TEXT("FMD_SetBlockStatus:block:%d,status:%d \r\n"),blockID,dwStatus));
#endif
if (dwStatus & BLOCK_STATUS_BAD)
{
if (!MarkBlockBad(blockID))
return(FALSE);
}
if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
SECTOR_ADDR Sector = blockID * NAND_PAGE_CNT;
SectorInfo SI;
if (!FMD_ReadSector(Sector, NULL, &SI, 1)) {
return FALSE;
}
if (dwStatus & BLOCK_STATUS_READONLY) {
SI.bOEMReserved &= ~OEM_BLOCK_READONLY;
}
if (dwStatus & BLOCK_STATUS_RESERVED) {
SI.bOEMReserved &= ~OEM_BLOCK_RESERVED;
}
if (!FMD_WriteSector (Sector, NULL, &SI, 1)) {
return FALSE;
}
}
return(TRUE);
}
BOOL FMD_ReadSector1208(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
ULONG SectorAddr = (ULONG)startSectorAddr;
int i;
BOOL bLastMode = SetKMode(TRUE);
NF_RSTECC(); // Initialize ECC.
NF_nFCE_L(); // Select the flash chip.
NF_CLEAR_RB();
NF_CMD(CMD_RESET); // Send reset command.
for(i=0;i<10;i++);
NF_DETECT_RB();
while (dwNumSectors--)
{
ULONG blockPage = SectorAddr;//(((SectorAddr / NAND_PAGE_CNT) * NAND_PAGE_CNT) | (SectorAddr % NAND_PAGE_CNT));
if (pSectorBuff)
{
NF_CLEAR_RB();
NF_CMD(CMD_READ); // Send read command.
NF_ADDR(0); // Column = 0.
NF_ADDR(blockPage & 0xff); // Page address.
NF_ADDR((blockPage >> 8) & 0xff);
NF_ADDR((blockPage >> 16) & 0xff);
NF_DETECT_RB(); // Wait tR(max 12us)
// Handle unaligned buffer pointer
if( ((DWORD) pSectorBuff) & 0x3)
{
RdPage512Unalign (pSectorBuff,(PULONG)&s2440NAND->NFDATA);
}
else
{
RdPage512(pSectorBuff,(PULONG)&s2440NAND->NFDATA); // Read page/sector data.
}
}
if (pSectorInfoBuff)
{
if(!pSectorBuff)
{
NF_CLEAR_RB();
NF_CMD(CMD_READ2); // Send read confirm command.
NF_ADDR(0); // Column = 0.
NF_ADDR(blockPage & 0xff); // Page address.
NF_ADDR((blockPage >> 8) & 0xff);
NF_ADDR((blockPage >> 16) & 0xff);
NF_DETECT_RB(); // Wait tR(max 12us)
}
// RdPageInfo((PBYTE)pSectorInfoBuff,(PULONG)&s2440NAND->NFDATA); // Read page/sector information.
pSectorInfoBuff->dwReserved1 = NF_DATA_R4();
// OEM byte
pSectorInfoBuff->bOEMReserved = (BYTE) NF_RDDATA();
// Read the bad block mark
pSectorInfoBuff->bBadBlock = (BYTE) NF_RDDATA();
// Second reserved field (WORD)
pSectorInfoBuff->wReserved2 = ((BYTE) NF_RDDATA() << 8);
pSectorInfoBuff->wReserved2 |= ((BYTE) NF_RDDATA());
pSectorInfoBuff++;
}
// NF_nFCE_H(); // Deselect the flash chip.
++SectorAddr;
pSectorBuff += NAND_PAGE_SIZE;
}
NF_nFCE_H(); // Deselect the flash chip.
SetKMode (bLastMode);
return(TRUE);
}
/*
@func BOOL | FMD_EraseBlock | Erases the specified flash block.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_EraseBlock1208(BLOCK_ID blockID)
{
BYTE Status;
ULONG blockPage = (blockID * NAND_PAGE_CNT); // Convert block address to page address.
BOOL bLastMode = SetKMode(TRUE);
NF_nFCE_L(); // Select the flash chip.
NF_CLEAR_RB();
NF_CMD(CMD_ERASE); // Send block erase command.
NF_ADDR(blockPage & 0xff); /* The mark of bad block is in 0 page */
NF_ADDR((blockPage >> 8) & 0xff); /* For block number A[24:17] */
NF_ADDR((blockPage >> 16) & 0xff); /* For block number A[25] */
NF_CMD(CMD_ERASE2); // Send block erase confirm command.
//NF_WAITRB(); // Wait for flash to complete command.
NF_DETECT_RB();
// Check the status
NF_CMD(CMD_STATUS);
Status = NF_RDDATA(); // Read command status.
NF_nFCE_H(); // Deselect the flash chip.
SetKMode (bLastMode);
return((Status & 1) ? FALSE : TRUE);
}
/*
@func BOOL | FMD_WriteSector | Writes the specified data to the specified NAND flash sector/page.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_WriteSector1208(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
BYTE Status;
ULONG SectorAddr = (ULONG)startSectorAddr;
DWORD i;
BOOL bLastMode = SetKMode(TRUE);
// DWORD Mecc;
if (!pSectorBuff && !pSectorInfoBuff)
return(FALSE);
NF_RSTECC(); // Initialize ECC.
NF_nFCE_L(); // Select the flash chip.
NF_CLEAR_RB();
NF_CMD(CMD_RESET); // Send reset command.
for(i=0;i<10;i++);
NF_DETECT_RB();
while (dwNumSectors--)
{
ULONG blockPage = SectorAddr;//(((SectorAddr / NAND_PAGE_CNT) * NAND_PAGE_CNT) | (SectorAddr % NAND_PAGE_CNT));
if (!pSectorBuff)
{
// 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(blockPage & 0xff); // Page address.
NF_ADDR((blockPage >> 8) & 0xff);
NF_ADDR((blockPage >> 16) & 0xff);
// WrPageInfo((PBYTE)pSectorInfoBuff,(PULONG)&s2440NAND->NFDATA);
// Write the first reserved field (DWORD)
NF_DATA_W4( pSectorInfoBuff->dwReserved1 );
// Write OEM reserved flag
NF_WRDATA( (pSectorInfoBuff->bOEMReserved) );
// Write the bad block flag
NF_WRDATA( (pSectorInfoBuff->bBadBlock) );
// Write the second reserved field
NF_WRDATA( (pSectorInfoBuff->wReserved2 >> 8) & 0xff );
NF_WRDATA( (pSectorInfoBuff->wReserved2)&0xff );
pSectorInfoBuff++;
}
else
{
NF_CMD(CMD_READ); // Send read command.
NF_CMD(CMD_WRITE); // Send write command.
NF_ADDR(0); // Column = 0.
NF_ADDR(blockPage & 0xff); // Page address.
NF_ADDR((blockPage >> 8) & 0xff);
NF_ADDR((blockPage >> 16) & 0xff);
// Special case to handle un-aligned buffer pointer.
if( ((DWORD) pSectorBuff) & 0x3)
{
WrPage512Unalign (pSectorBuff,(PULONG)&s2440NAND->NFDATA);
}
else
{
WrPage512(pSectorBuff,(PULONG)&s2440NAND->NFDATA); // Write page/sector data.
}
// Write the SectorInfo data to the media.
//
if(pSectorInfoBuff)
{
// Write the first reserved field (DWORD)
NF_DATA_W4(pSectorInfoBuff->dwReserved1);
// Write OEM reserved flag
NF_WRDATA( (pSectorInfoBuff->bOEMReserved) );
// Write the bad block flag
NF_WRDATA( (pSectorInfoBuff->bBadBlock) );
// Write the second reserved field
NF_WRDATA( (pSectorInfoBuff->wReserved2 >> 8) & 0xff );
NF_WRDATA( (pSectorInfoBuff->wReserved2) & 0xff );
}else
{
int i;
// Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data)
for(i=0; i<sizeof(SectorInfo); i++)
{
NF_WRDATA(0xff);
}
}
pSectorBuff += NAND_PAGE_SIZE;
}
NF_CLEAR_RB();
NF_CMD(CMD_WRITE2); // Send write confirm command.
// Wait for RB
NF_DETECT_RB(); // Wait tR(max 12us)
// Check the status
NF_CMD(CMD_STATUS);
Status = NF_RDDATA();
if (Status & 1)
{
NF_nFCE_H(); // Deselect the flash chip.
SetKMode (bLastMode);
#ifdef BOOT_LOADER
EdbgOutputDebugString("ERROR: FMD_WriteSector: failed sector write.\r\n");
#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -