📄 lpc32xx_fmd.cpp
字号:
cleanup:
if (ret == NULL)
{
FMD_Deinit(&nandDrvDat);
}
return ret;
}
//------------------------------------------------------------------------------
//
// FMD_Deinit
//
// De-initialize NAND interface
//
extern "C"
BOOL FMD_Deinit(PVOID hFMD)
{
// Close event handle
if (nandDrvDat.dwEvent != NULL)
{
CloseHandle(nandDrvDat.dwEvent);
nandDrvDat.dwEvent = NULL;
}
// Return sysIntr value
if (nandDrvDat.dwSysIntr != SYSINTR_UNDEFINED)
{
InterruptDisable(nandDrvDat.dwSysIntr);
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &nandDrvDat.dwSysIntr,
sizeof(nandDrvDat.dwSysIntr), NULL, 0, NULL);
nandDrvDat.dwSysIntr = SYSINTR_UNDEFINED;
}
// Diable SLC clock and unmap registers
if (nandDrvDat.pCLKPWRRegs != NULL)
{
nandDrvDat.pCLKPWRRegs->clkpwr_nand_clk_ctrl &= ~CLKPWR_NANDCLK_SLCCLK_EN;
MmUnmapIoSpace((PVOID) nandDrvDat.pCLKPWRRegs, sizeof (CLKPWR_REGS_T));
nandDrvDat.pCLKPWRRegs = NULL;
}
if (nandDrvDat.pSLCRegs != NULL)
{
MmUnmapIoSpace((PVOID) nandDrvDat.pSLCRegs, sizeof (SLCNAND_REGS_T));
nandDrvDat.pSLCRegs = NULL;
}
// Enable write protect and unmap GPIO registers
if (nandDrvDat.pGPIORegs != NULL)
{
nandWpEnable(TRUE);
MmUnmapIoSpace((PVOID) nandDrvDat.pGPIORegs, sizeof (GPIO_REGS_T));
nandDrvDat.pGPIORegs = NULL;
}
#ifdef FMDACCESSLOCKS
// Close lock mutex
if (nandDrvDat.Lockmutex != NULL)
{
CloseHandle(nandDrvDat.Lockmutex);
nandDrvDat.Lockmutex = NULL;
}
#endif
return TRUE;
}
//------------------------------------------------------------------------------
//
// FMD_EraseBlock
//
// Erase a FLASH block
//
extern "C"
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
unsigned char addrbytes[3];
BYTE Status;
#if BYPASSBLOCKS>0
blockID += BYPASSBLOCKS;
#endif
// Lock access and chip select
nandMutexLock();
nandCSLock(TRUE);
// Issue erase command with block address and wait
nandWriteCommand(LPCNAND_CMD_ERASE1);
// Generate block address
addrbytes[0] = (unsigned char) ((blockID << 5) & 0x00E0);
addrbytes[1] = (unsigned char) ((blockID >> 3) & 0x00FF);
if (nandDrvDat.addressCycles == 4)
{
addrbytes[2] = (unsigned char) ((blockID >> 11) & 0x0003);
}
nandWriteAddress(addrbytes, (nandDrvDat.addressCycles - 1));
nandWriteCommand(LPCNAND_CMD_ERASE2);
nandWaitReady(MAXERASETIMEINMS);
// Get NAND operation status
nandWriteCommand(LPCNAND_CMD_STATUS);
nandReadData(&Status, 1);
// Unlock access and chip select
nandCSLock(FALSE);
nandMutexUnlock();
if ((Status & 0x1) == 0)
{
// Passed
return TRUE;
}
// Failed
RETAILMSG(1,
(TEXT("FMD: Failed block erase (status = 0x%x)\r\n"), Status));
return FALSE;
}
//------------------------------------------------------------------------------
//
// FMD_GetBlockStatus
//
// Return the status of the specified block
//
extern "C"
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
SectorInfo SI;
DWORD dwResult = 0;
SECTOR_ADDR Sector;
// Compute sector address
Sector = blockID * nandDrvDat.dwSectorsPerBlock;
/* Get SectorInfo data from the sector */
if (FMD_ReadSector(Sector, NULL, &SI, 1) == FALSE) {
RETAILMSG(1, (TEXT("FMD: Cannot read block\r\n")));
return BLOCK_STATUS_UNKNOWN;
}
// Add in statuses
if (SI.bBadBlock != 0xFF)
{
dwResult |= BLOCK_STATUS_BAD;
}
if ((SI.bOEMReserved & OEM_BLOCK_READONLY) == 0)
{
dwResult |= BLOCK_STATUS_READONLY;
}
if ((SI.bOEMReserved & OEM_BLOCK_RESERVED) == 0)
{
dwResult |= BLOCK_STATUS_RESERVED;
}
return dwResult;
}
//------------------------------------------------------------------------------
//
// FMD_GetInfo
//
// Return FLASH geometry
//
extern "C"
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
if (pFlashInfo == NULL) {
return FALSE;
}
pFlashInfo->flashType = NAND;
pFlashInfo->wDataBytesPerSector = nandDrvDat.dwDataBytesPerSector;
pFlashInfo->dwNumBlocks = nandDrvDat.dwNumBlocks;
pFlashInfo->wSectorsPerBlock = nandDrvDat.dwSectorsPerBlock;
pFlashInfo->dwBytesPerBlock = nandDrvDat.dwBytesPerBlock;
return TRUE;
}
//------------------------------------------------------------------------------
//
// FMD_OEMIoControl
//
// FLASH IO control block
//
extern "C"
BOOL FMD_OEMIoControl(DWORD dwIoControlCode,
PBYTE pInBuf,
DWORD nInBufSize,
PBYTE pOutBuf,
DWORD nOutBufSize,
PDWORD pBytesReturned)
{
return FALSE;
}
//------------------------------------------------------------------------------
//
// FMD_PowerUp
//
// Power up
//
extern "C"
VOID FMD_PowerUp(VOID)
{
}
//------------------------------------------------------------------------------
//
// FMD_PowerDown
//
// Power down
//
extern "C"
VOID FMD_PowerDown(VOID)
{
}
//------------------------------------------------------------------------------
//
// FMD_SetBlockStatus
//
// Set the block status
//
extern "C"
BOOL FMD_SetBlockStatus(BLOCK_ID blockID,
DWORD dwStatus)
{
SectorInfo SI;
SECTOR_ADDR Sector;
// Compute sector address
Sector = blockID * nandDrvDat.dwSectorsPerBlock;
/* Get SectorInfo data from the sector */
if (FMD_ReadSector(Sector, NULL, &SI, 1) == FALSE)
{
RETAILMSG(1, (TEXT("FMD: Cannot read block\r\n")));
return FALSE;
}
// Should block be marked as bad?
if ((dwStatus & BLOCK_STATUS_BAD) != 0)
{
SI.bBadBlock = 0;
}
// Other statuses
if ((dwStatus & BLOCK_STATUS_READONLY) != 0)
{
SI.bOEMReserved &= ~OEM_BLOCK_READONLY;
}
if ((dwStatus & BLOCK_STATUS_RESERVED) != 0)
{
SI.bOEMReserved &= ~OEM_BLOCK_RESERVED;
}
// Write back sector info
if (FMD_WriteSector (Sector, NULL, &SI, 1) == FALSE)
{
RETAILMSG(1, (TEXT("FMD: Write sector failure\r\n")));
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// FMD_ReadSector
//
// Read a number of sectors
//
extern "C"
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr,
LPBYTE pSectorBuff,
PSectorInfo pSectorInfoBuff,
DWORD dwNumSectors)
{
unsigned char addrbytes[5];
unsigned short eccin[2], ecccomp[2];
ULONG SectorAddr;
SectorInfo tSec;
#if BYPASSBLOCKS>0
startSectorAddr += (BYPASSBLOCKS * nandDrvDat.dwSectorsPerBlock);
#endif
SectorAddr = startSectorAddr;
// Lock
nandMutexLock();
// Read all sectors
while (dwNumSectors > 0)
{
// Wait until device is ready
if (nandWaitReady(MAXEREADTIMEINMS) == FALSE)
{
// Device not ready
RETAILMSG(1, (TEXT("FMD: Timeout reading sector\r\n")));
return FALSE;
}
// Lock chip select
nandCSLock(TRUE);
// Is this a sector read with or without sector info?
if (pSectorBuff != NULL) {
nandGetPageIndex(SectorAddr, 0, addrbytes);
nandWriteCommand(LPCNAND_CMD_PAGE_READA);
nandWriteAddress(addrbytes, nandDrvDat.addressCycles);
nandWaitReady(MAXEREADTIMEINMS);
// Copy buffer from NAND
nandReadData(pSectorBuff, 512);
eccGenerate512(ecccomp, pSectorBuff);
if (pSectorInfoBuff != NULL)
{
// Seek to sector info structure and read it
nandReadData(pSectorInfoBuff, sizeof(SectorInfo));
pSectorInfoBuff++;
}
else
{
// Just read garbage to place NAND pointer in right location
// for the ECC fetch
nandReadData(&tSec, sizeof(tSec));
}
// Get the saved ECC data from the FLASH
nandReadData(eccin, sizeof(eccin));
// Check and correct data
if (eccCheckAndCorrect(eccin, ecccomp,
pSectorBuff) == ECC_NOTCORRECTABLE)
{
// Uncorrectable error, report it to FAL
nandCSLock(FALSE);
RETAILMSG(1, (TEXT("FMD: ECC failure (sector %d)\r\n"),
SectorAddr));
nandMutexUnlock();
return FALSE;
}
pSectorBuff = pSectorBuff + 512;
}
else if (pSectorInfoBuff != NULL)
{
nandGetPageIndex(SectorAddr, 0, addrbytes);
/* Read sectorinfo structure from FLASH */
nandWriteCommand(LPCNAND_CMD_PAGE_READC);
nandWriteAddress(addrbytes, nandDrvDat.addressCycles);
nandWaitReady(MAXEREADTIMEINMS);
nandReadData(pSectorInfoBuff, sizeof(SectorInfo));
pSectorInfoBuff++;
}
++SectorAddr;
dwNumSectors--;
/* Unlock access and chip select */
nandCSLock(FALSE);
nandMutexUnlock();
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// FMD_WriteSector
//
// Write a number of sectors
//
extern "C"
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr,
LPBYTE pSectorBuff,
PSectorInfo pSectorInfoBuff,
DWORD dwNumSectors)
{
unsigned char addrbytes[5];
BYTE Status;
unsigned short ecccomp[2];
ULONG SectorAddr;
#if BYPASSBLOCKS>0
startSectorAddr += (BYPASSBLOCKS * nandDrvDat.dwSectorsPerBlock);
#endif
SectorAddr = startSectorAddr;
if ((pSectorBuff == NULL) && (pSectorInfoBuff == NULL)) {
return FALSE;
}
/* Lock access and chip select */
nandMutexLock();
nandCSLock(TRUE);
while (dwNumSectors > 0) {
if (pSectorBuff != NULL) {
/* Setup write */
nandGetPageIndex(SectorAddr, 0, addrbytes);
nandWriteCommand(LPCNAND_CMD_PAGE_READA);
nandWriteCommand(LPCNAND_CMD_PAGE_WRITE1);
nandWriteAddress(addrbytes, nandDrvDat.addressCycles);
/* Copy buffer to NAND */
nandWriteData(pSectorBuff, 512);
/* Copy buffer to NAND and generate ECC */
eccGenerate512(ecccomp, pSectorBuff);
pSectorBuff = pSectorBuff + 512;
/* Write sectorinfo structure */
if (pSectorInfoBuff != NULL) {
/* Seek to sectorinfo offset */
nandWriteData(pSectorInfoBuff, sizeof(SectorInfo));
pSectorInfoBuff++;
}
else
{
// For the ECC to be written in the correct location,
// the page needs to be written now and a new write
// session needs to be opened at the correct FLASH
// page data index
nandWriteCommand(LPCNAND_CMD_PAGE_WRITE2);
nandWaitReady(MAXEWRITETIMEINMS);
nandGetPageIndex(SectorAddr, 8, addrbytes);
nandWriteCommand(LPCNAND_CMD_PAGE_READC);
nandWriteCommand(LPCNAND_CMD_PAGE_WRITE1);
nandWriteAddress(addrbytes, nandDrvDat.addressCycles);
}
/* Write ECC data */
nandWriteData(&ecccomp, sizeof(ecccomp));
nandWriteCommand(LPCNAND_CMD_PAGE_WRITE2);
nandWaitReady(MAXEWRITETIMEINMS);
}
else if (pSectorInfoBuff != NULL) {
/* Update jsut sectorinfo data */
nandGetPageIndex(SectorAddr, 0, addrbytes);
nandWriteCommand(LPCNAND_CMD_PAGE_READC);
nandWriteCommand(LPCNAND_CMD_PAGE_WRITE1);
nandWriteAddress(addrbytes, nandDrvDat.addressCycles);
nandWriteData(pSectorInfoBuff, sizeof(SectorInfo));
pSectorInfoBuff++;
nandWriteCommand(LPCNAND_CMD_PAGE_WRITE2);
nandWaitReady(MAXEWRITETIMEINMS);
}
nandWriteCommand(LPCNAND_CMD_STATUS);
nandReadData(&Status, 1);
if ((Status & 0x1) != 0) {
nandCSLock(FALSE);
RETAILMSG(1,
(TEXT("FMD: Write status failure, status = 0x%02x\r\n"), Status));
nandMutexUnlock();
return FALSE;
}
++SectorAddr;
dwNumSectors--;
}
/* Unlock access and chip select */
nandCSLock(FALSE);
nandMutexUnlock();
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -