📄 nandfmd.c
字号:
NF_ADDR_COL(ColumnAddr); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
#else
NF_CMD(CMD_READ); // Send read command
NF_ADDR_COL(ColumnAddr + NAND_SECTOR_SIZE); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
NF_CMD(CMD_READ_2CYCLE); // Send 2nd cycle read command
#endif
// Read page data into NFC buffer
NF_RD_SPARE();
NFCReadSpare(pSectorInfoBuff);
pSectorInfoBuff++;
}
++SectorAddr;
bSeqRead = NF_READ_SEQ(SectorAddr);
}
rc = TRUE;
cleanUp:
NFCSetClock(FALSE);
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_EraseBlock
//
// This function erases the specified flash block.
//
// Parameters:
// blockID
// [in] The block number to erase.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_EraseBlock(u32 blockID)
{
u16 Status;
u32 RowAddr = blockID * (NAND_SECTOR_CNT / NAND_SECTORS_PERPAGE);
// RETAILMSG(TRUE, (_T("FMD_EraseBlock(block = %d, addr = 0x%x)\r\n"), blockID, addr));
NFCSetClock(TRUE);
#ifndef NAND_LARGE_PAGE
NF_CMD(CMD_READ); // Set address pointer to main area
#endif
NF_CMD(CMD_ERASE); // Send block erase setup command
NF_ADDR_PAGE(RowAddr); // Send page address
NF_CMD(CMD_ERASE2); // Send block erase command
NF_CMD(CMD_STATUS) // Send status command
NF_RD_STATUS(); // Read status into NFC buffer
Status = INREG16(&g_pNFC->MAIN[0][0]); // Read status from NFC buffer
NFCSetClock(FALSE);
if (Status & NAND_STATUS_MASK_ERROR)
{
// ERRORMSG(TRUE, (_T("NAND erase failed (blockID = 0x%x)\r\n"), blockID));
return FALSE;
}
return TRUE;
}
static void FMD_WriteMain(u16_ptr pBuffer,/* u8_ptr pMain,*/ u16 pSize)
{
u16 i;
u16_ptr pMain ;
pMain = (u16 *)(0xD8000000);
for(i = 0; i < pSize; i++)
{
*pMain = *pBuffer ;
pBuffer++ ;
pMain++ ;
}
return;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_WriteSector
//
// This function writes the requested sector data and metadata to the
// flash media.
//
// Parameters:
// startSectorAddr
// [in] The starting physical sector address to write to.
//
// pSectorBuff
// [in] Pointer to the buffer that contains the sector data to write.
// Set to NULL if no data is to be written.
//
// pSectorInfoBuff
// [in] Buffer for an array of sector information structures. There
// must be one sector information entry for each sector that is to be
// written. Set to NULL if this data is not written.
//
// dwNumSectors
// [in] Number of sectors to write.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_WriteSector(u32 startSectorAddr, u16_ptr pSectorBuff,
PSectorInfo pSectorInfoBuff, u32 dwNumSectors)
{
u16 Status;
u32 SectorAddr = startSectorAddr;
u32 ColumnAddr, RowAddr;
BOOL rc = FALSE;
NFCSetClock(TRUE);
if (!pSectorBuff && !pSectorInfoBuff)
{
goto cleanUp;
}
while (dwNumSectors--)
{
RowAddr = (u32)SectorAddr/NAND_SECTORS_PERPAGE;
ColumnAddr = ((u32)SectorAddr%NAND_SECTORS_PERPAGE) * (NAND_SECTOR_SIZE + NAND_SPARE_SIZE);
if (pSectorBuff)
{
if (pSectorInfoBuff)
{
// Update spare area with sector information provided
NFCWriteSpare(pSectorInfoBuff);
pSectorInfoBuff++;
}
else
{
// Clear out the spare area
NFCClearSpare();
}
// Move page data from sector buffer to NFC buffer
// NFCWriteMain(pSectorBuff);
FMD_WriteMain(pSectorBuff,256);
#ifndef NAND_LARGE_PAGE
NF_CMD(CMD_READ); // Set address pointer to main area
#endif
NF_CMD(CMD_WRITE); // Send sequential data input command
NF_ADDR_COL(ColumnAddr); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
NF_WR_PAGE(); // Write out the page data
//pSectorBuff += NAND_SECTOR_SIZE; // Next sector
pSectorBuff += NAND_SECTOR_SIZE/2; // Next sector
}
else
{
// Update spare area with sector information provided
NFCWriteSpare(pSectorInfoBuff);
#ifndef NAND_LARGE_PAGE
NF_CMD(CMD_READ2); // Set address pointer to spare area
NF_CMD(CMD_WRITE); // Send sequential data input command
NF_ADDR_COL(ColumnAddr); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
#else
NF_CMD(CMD_WRITE); // Send sequential data input command
NF_ADDR_COL(ColumnAddr + NAND_SECTOR_SIZE); // Send column address
NF_ADDR_PAGE(RowAddr); // Send page address
#endif
NF_WR_SPARE(); // Write out the spare data
pSectorInfoBuff++;
}
NF_CMD(CMD_WRITE2) // Send program command
NF_CMD(CMD_STATUS) // Send status command
NF_RD_STATUS(); // Read status into NFC buffer
Status = INREG16(&g_pNFC->MAIN[0][0]); // Read status from NFC buffer
if (Status & NAND_STATUS_MASK_ERROR)
{
goto cleanUp;
}
++SectorAddr;
}
rc = TRUE;
cleanUp:
NFCSetClock(FALSE);
return rc;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_PowerUp
//
// This function restores power to the flash memory device, if applicable.
//
// Parameters:
// None
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
void FMD_PowerUp(void)
{
}
//-----------------------------------------------------------------------------
//
// Function: FMD_PowerDown
//
// This function suspends power to the flash memory device, if applicable.
//
// Parameters:
// None
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
void FMD_PowerDown(void)
{
}
//-----------------------------------------------------------------------------
//
// Function: FMD_OEMIoControl
//
// This function implements user-defined commands for the flash memory device.
//
// Parameters:
// dwIoControlCode
// [in] The control code specifying the command to execute.
//
// pInBuf
// [in] Long pointer to a buffer that contains the data required to
// perform the operation. Set to NULL if the dwIoControlCode parameter
// specifies an operation that does not require input data.
//
// nInBufSize
// [in] Size, in bytes, of the buffer pointed to by pInBuf.
//
// pOutBuf
// [out] Long pointer to a buffer that receives the output data for
// the operation. Set to NULL if the dwIoControlCode parameter
// specifies an operation that does not produce output data.
//
// nOutBufSize
// [in] Size, in bytes, of the buffer pointed to by pOutBuf.
//
// pBytesReturned
// [out] Long pointer to a variable that receives the size, in bytes,
// of the data stored into the buffer pointed to by pOutBuf. Even
// when an operation produces no output data and pOutBuf is set to
// NULL, the DeviceIoControl function uses the variable pointed to
// by pBytesReturned. After such an operation, the value of the
// variable has no meaning.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_OEMIoControl(u32 dwIoControlCode, u8_ptr pInBuf, u32 nInBufSize,
u8_ptr pOutBuf, u32 nOutBufSize, u32_ptr pBytesReturned)
{
BOOL rc = FALSE;
return(rc);
}
//-----------------------------------------------------------------------------
//
// Function: FMD_GetBlockStatus
//
// This function returns the status of a block.
//
// Parameters:
// blockID
// [in] The block number used to check status.
//
// Returns:
// Flags to describe the status of the block.
//
//-----------------------------------------------------------------------------
u32 FMD_GetBlockStatus(u32 blockID)
{
u32 Sector = (blockID * NAND_SECTOR_CNT);
SectorInfo SI[2];
u32 dwResult = 0;
// Samsung makes sure that either the 1st or 2nd page of every initial
// invalid block has non-FFh data at the column address of 517. Read
// first two page spare areas and to determine block status.
if (!FMD_ReadSector(Sector, NULL, SI, 2))
{
dwResult = BLOCK_STATUS_UNKNOWN;
goto cleanUp;
}
if ((SI[0].bBadBlock != 0xFF) || (SI[1].bBadBlock != 0xFF))
{
dwResult = BLOCK_STATUS_BAD;
goto cleanUp;
}
if (!(SI[0].bOEMReserved & OEM_BLOCK_READONLY))
dwResult |= BLOCK_STATUS_READONLY;
if (!(SI[0].bOEMReserved & OEM_BLOCK_RESERVED))
dwResult |= BLOCK_STATUS_RESERVED;
cleanUp:
return(dwResult);
}
//-----------------------------------------------------------------------------
//
// Function: FMD_SetBlockStatus
//
// This function sets the status of a block.
//
// Parameters:
// blockID
// [in] The block number used to set status.
//
// dwStatus
// [in] The status value to set.
//
// Returns:
// Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_SetBlockStatus(u32 blockID, u32 dwStatus)
{
u32 Sector = (blockID * NAND_SECTOR_CNT);
SectorInfo SI;
if (dwStatus & (BLOCK_STATUS_BAD | BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
if (!FMD_ReadSector(Sector, NULL, &SI, 1)) {
return FALSE;
}
if (dwStatus & BLOCK_STATUS_BAD)
{
SI.bBadBlock = 0x00;
}
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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -