📄 fmd.c
字号:
// Read spare data
NAND_SendFullCommand(BSP_NAND_CMD_READ2, sector, 0);
// Read NAND spare area data
NAND_Read((UINT8*)&sa, sizeof(sa));
}
// Select B area
OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_READ2);
// Issue command
NAND_SendFullCommand(BSP_NAND_CMD_WRITE, sector, 0);
// Create spare area info (we already have ECC from above)
sa.oemReserved = pSectorInfo->bOEMReserved;
sa.reserved1 = pSectorInfo->dwReserved1;
sa.reserved2 = pSectorInfo->wReserved2;
sa.badBlock = pSectorInfo->bBadBlock;
sa.unused = 0xFF;
if (sa.badBlock != 0xFF) {
sa.badBlock1 = 0;
sa.badBlock2 = 0;
} else {
sa.badBlock1 = 0xFFFF;
sa.badBlock2 = 0xFFFF;
}
// Write spare info to the media
NAND_Write((UINT8*)&sa, sizeof(sa));
// Finish up the write operation
if (!NAND_FinishCommand(BSP_NAND_CMD_WRITE2)) goto cleanUp;
// Done
rc = TRUE;
cleanUp:
// Restor flash write protection
CLRREG32(&g_fmd.pGPMCRegs->ulGPMC_CONFIG, BIT4);
LeaveCriticalSection(&g_fmd.cs);
ASSERT(rc);
return rc;
}
//------------------------------------------------------------------------------
//
// Function: FMD_GetBlockStatus
//
DWORD FMD_GetBlockStatus(BLOCK_ID blockId)
{
DWORD rc = 0;
SECTOR_ADDR sector;
SectorInfo sectorInfo;
// Check if we know flash geometry
if (g_fmd.pNANDInfo == NULL) goto cleanUp;
// Calculate sector
sector = blockId * g_fmd.pNANDInfo->sectorsPerBlock;
if (!FMD_ReadSector(sector, NULL, §orInfo, 1)) {
rc = BLOCK_STATUS_UNKNOWN;
goto cleanUp;
}
if (sectorInfo.bBadBlock != 0xFF) {
rc |= BLOCK_STATUS_BAD;
}
if ((sectorInfo.bOEMReserved & OEM_BLOCK_READONLY) == 0) {
rc |= BLOCK_STATUS_READONLY;
}
if ((sectorInfo.bOEMReserved & OEM_BLOCK_RESERVED) == 0) {
rc |= BLOCK_STATUS_RESERVED;
}
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: FMD_SetBlockStatus
//
BOOL FMD_SetBlockStatus(BLOCK_ID blockId, DWORD status)
{
BOOL rc = FALSE;
SECTOR_ADDR sector;
SectorInfo sectorInfo;
// Remove flash write protection
SETREG32(&g_fmd.pGPMCRegs->ulGPMC_CONFIG,BIT4);
// Check if we know flash geometry
if (g_fmd.pNANDInfo == NULL) goto cleanUp;
// Calculate sector
sector = blockId * g_fmd.pNANDInfo->sectorsPerBlock;
if ((status & BLOCK_STATUS_BAD) != 0) {
// Read the sector info
if (!FMD_ReadSector(sector, NULL, §orInfo, 1)) goto cleanUp;
// Set the bad block marker
sectorInfo.bBadBlock = 0;
// Complete the write (no erase, we changed 0xFF -> 0x00)
if (!FMD_WriteSector(sector, NULL, §orInfo, 1)) goto cleanUp;
}
if ((status & BLOCK_STATUS_READONLY) != 0) {
// 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 ((FMD_GetBlockStatus(blockId) & BLOCK_STATUS_READONLY) != 0) {
goto cleanUp;
}
}
// Done
rc = TRUE;
cleanUp:
// Restore flash write protection
CLRREG32(&g_fmd.pGPMCRegs->ulGPMC_CONFIG,BIT4);
return rc;
}
//------------------------------------------------------------------------------
//
// Function: FMD_EraseBlock
//
// Erase the given block
//
BOOL FMD_EraseBlock(BLOCK_ID blockId)
{
BOOL rc = FALSE;
UINT32 sector;
// Check if we know flash geometry
if (g_fmd.pNANDInfo == NULL) goto cleanUp;
// Calculate sector
sector = blockId * g_fmd.pNANDInfo->sectorsPerBlock;
// Obtain hardware lock
EnterCriticalSection(&g_fmd.cs);
// Remove flash write protection
SETREG32(&g_fmd.pGPMCRegs->ulGPMC_CONFIG,BIT4);
// Write the command
OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_ERASE);
// Write page address
OUTREG16(&g_fmd.pNANDRegs->ADDRESS, sector & 0xFF);
OUTREG16(&g_fmd.pNANDRegs->ADDRESS, (sector >> 8) & 0xFF);
if (g_fmd.pNANDInfo->extendedAddress) {
OUTREG16(&g_fmd.pNANDRegs->ADDRESS, (sector >> 16) & 0xFF);
}
// Complete erase operation
if (!NAND_FinishCommand(BSP_NAND_CMD_ERASE2)) goto cleanUp;
// Done
rc = TRUE;
cleanUp:
// Restore flash write protection
CLRREG32(&g_fmd.pGPMCRegs->ulGPMC_CONFIG,BIT4);
// Release hardware lock
LeaveCriticalSection(&g_fmd.cs);
return rc;
}
//------------------------------------------------------------------------------
//
// Function: FMD_PowerUp
//
VOID FMD_PowerUp()
{
// Obtain hardware lock
EnterCriticalSection(&g_fmd.cs);
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
// Write the command
OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_RESET);
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
cleanUp:
// Release hardware lock
LeaveCriticalSection(&g_fmd.cs);
}
//------------------------------------------------------------------------------
//
// Function: FMD_PowerDown
//
VOID FMD_PowerDown(VOID)
{
// Obtain hardware lock
EnterCriticalSection(&g_fmd.cs);
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
// Write the command
OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_RESET);
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
cleanUp:
// Release hardware lock
LeaveCriticalSection(&g_fmd.cs);
}
//------------------------------------------------------------------------------
//
// Function: FMD_OEMIoControl
//
BOOL FMD_OEMIoControl(
DWORD code, UCHAR *pInBuffer, DWORD inSize, UCHAR *pOutBuffer,
DWORD outSize, DWORD *pOutSize
) {
return FALSE;
}
//------------------------------------------------------------------------------
static BOOL NAND_SendFullCommand(UINT8 cmd, SECTOR_ADDR sector, UINT32 offset)
{
BOOL rc = FALSE;
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
// Write the command
OUTREG16(&g_fmd.pNANDRegs->CMD, cmd);
// Write the address
OUTREG16(&g_fmd.pNANDRegs->ADDRESS, offset);
OUTREG16(&g_fmd.pNANDRegs->ADDRESS, sector & 0xFF);
OUTREG16(&g_fmd.pNANDRegs->ADDRESS, (sector >> 8) & 0xFF);
if (g_fmd.pNANDInfo->extendedAddress) {
OUTREG16(&g_fmd.pNANDRegs->ADDRESS, (sector >> 16) & 0xFF);
}
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
// Done
rc = TRUE;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
static BOOL NAND_FinishCommand(UINT8 cmd)
{
BOOL rc = FALSE;
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
// Write the command
OUTREG16(&g_fmd.pNANDRegs->CMD, cmd);
// Wait for NAND
if (!NAND_WaitForReady()) goto cleanUp;
// Write STATUS command
OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_STATUS);
// Read status
rc = (INREG16(&g_fmd.pNANDRegs->DATA) & BSP_NAND_STATUS_ERROR) == 0;
cleanUp:
return rc;
}
//------------------------------------------------------------------------------
static VOID NAND_Read(UINT8 *pBuffer, UINT32 bytes)
{
UINT16 data;
while (bytes > 1) {
data = INREG16(&g_fmd.pNANDRegs->DATA);
*pBuffer++ = (UINT8)data;
*pBuffer++ = (UINT8)(data >> 8);
bytes -= 2;
}
if (bytes > 0) {
data = INREG16(&g_fmd.pNANDRegs->DATA);
*pBuffer++ = (UINT8)data;
bytes--;
}
}
//------------------------------------------------------------------------------
static VOID NAND_Write(UINT8 *pBuffer, UINT32 bytes)
{
UINT16 data;
while (bytes > 1) {
data = *pBuffer++;
data |= *pBuffer++ << 8;
OUTREG16(&g_fmd.pNANDRegs->DATA, data);
bytes -= 2;
}
if (bytes > 0) {
data = *pBuffer++ | 0xFF00;
OUTREG16(&g_fmd.pNANDRegs->DATA, data);
bytes--;
}
}
//------------------------------------------------------------------------------
_inline static BOOL NAND_WaitForReady()
{
// Internal Wait monitoring implmented in GPMC, So no need to
// check the status of the NAND Flash ready bit.
// In case if the status bit is to be monitored then uncomment the
// code below.
//while ((INREG32(&g_fmd.pGPMCRegs->ulGPMC_STATUS) & BIT8 ) == 0);
return TRUE;
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -