⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc32xx_fmd.cpp

📁 NXP LPC3000系列 wince BSP包
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    
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 + -