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

📄 nandfmd.cpp

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
//  Copyright (C) 2006, Freescale Semiconductor, Inc. All Rights Reserved.
//  THIS SOURCE CODE, AND ITS USE AND DISTRIBUTION, IS SUBJECT TO THE TERMS
//  AND CONDITIONS OF THE APPLICABLE LICENSE AGREEMENT
//
//------------------------------------------------------------------------------
#include <fmd.h>
#include "bsp.h"
#include "nandfmd.h"

//-----------------------------------------------------------------------------
// External Functions
extern "C" void RdPage512Align1(LPBYTE pSectorBuff);
extern "C" void RdPage512Align2(LPBYTE pSectorBuff);
extern "C" void RdPage512Align3(LPBYTE pSectorBuff);
extern "C" void RdPage512Align4(LPBYTE pSectorBuff);
extern "C" void WrPage512Align1(LPBYTE pSectorBuff); 
extern "C" void WrPage512Align2(LPBYTE pSectorBuff); 
extern "C" void WrPage512Align3(LPBYTE pSectorBuff); 
extern "C" void WrPage512Align4(LPBYTE pSectorBuff); 
extern BOOL NFCAlloc(VOID);
extern VOID NFCWait(BOOL bPoll);
extern BOOL NFCSetClock(BOOL bEnabled);
extern BOOL NFCSetPagesize(BOOL bLargePage);


//-----------------------------------------------------------------------------
// External Variables


//-----------------------------------------------------------------------------
// Defines


//-----------------------------------------------------------------------------
// Types


//-----------------------------------------------------------------------------
// Global Variables
extern "C" PCSP_NANDFC_REGS g_pNFC = NULL;


//-----------------------------------------------------------------------------
// Local Variables
static UINT16 g_NandDeviceID;


//-----------------------------------------------------------------------------
// Local Functions


//-----------------------------------------------------------------------------
//
//  Function: NFCReadMain
//
//  This function reads the NAND flash controller main area and provides this
//  sector data to the upper FMD layers.
//
//  Parameters:
//      pSectorBuff 
//          [out] Buffer containing sector data read.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
static VOID NFCReadMain(LPBYTE pSectorBuff)
{        
    if((UINT32)pSectorBuff & 0x1)        
    {
        // Byte-aligned on BYTE[3]
        if((UINT32)pSectorBuff & 0x2)        
        {
            RdPage512Align3(pSectorBuff);
        }

        // Byte-aligned on BYTE[1]
        else
        {
            RdPage512Align1(pSectorBuff);
        }
    }
    else if ((UINT32)pSectorBuff & 0x2)
    {
        // Half-word aligned on BYTE[2]
        RdPage512Align2(pSectorBuff);
    } 
    else
    {
        // Word-aligned
        RdPage512Align4(pSectorBuff);
    }
}


//-----------------------------------------------------------------------------
//
//  Function: NFCWriteMain
//
//  This function writes the sector data provided by the upper FMD layers
//  to the NAND flash controller main area.
//
//  Parameters:
//      pSectorBuff 
//          [in] Buffer containing sector data to be written.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
static VOID NFCWriteMain(LPBYTE pSectorBuff)
{
    if((UINT32)pSectorBuff & 0x1)        
    {
        // Byte-aligned on BYTE[3]
        if((UINT32)pSectorBuff & 0x2)        
        {
            WrPage512Align3(pSectorBuff);
        }

        // Byte-aligned on BYTE[1]
        else
        {
            WrPage512Align1(pSectorBuff);
        }
    }
    else if ((UINT32)pSectorBuff & 0x2)
    {
        // Half-word aligned on BYTE[2]
        WrPage512Align2(pSectorBuff);
    } 
    else
    {
        // Word-aligned
        WrPage512Align4(pSectorBuff);
    }
}


//-----------------------------------------------------------------------------
//
//  Function: NFCReadSpare
//
//  This function reads the NAND flash controller spare area and provides this
//  information to the upper FMD layers.
//
//  Parameters:
//      pSectorInfoBuff 
//          [out] Buffer containing sector information read.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
static VOID NFCReadSpare(PSectorInfo pSectorInfoBuff)
{
    pSectorInfoBuff->dwReserved1 = INREG32((UINT32 *) &g_pNFC->SPARE[0][0]);
    *((UINT16 *) (&pSectorInfoBuff->bOEMReserved)) = INREG16(&g_pNFC->SPARE[0][2]);
    pSectorInfoBuff->wReserved2 = INREG16(&g_pNFC->SPARE[0][7]);
}


//-----------------------------------------------------------------------------
//
//  Function: NFCWriteSpare
//
//  This function writes the spare data provided by the upper FMD layers
//  to the NAND flash controller spare area.
//
//  Parameters:
//      pSectorInfoBuff 
//          [in] Buffer containing sector information to be written.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
static VOID NFCWriteSpare(PSectorInfo pSectorInfoBuff)
{
    OUTREG32((UINT32 *) &g_pNFC->SPARE[0][0], pSectorInfoBuff->dwReserved1);
    OUTREG16(&g_pNFC->SPARE[0][2], *((UINT16 *) (&pSectorInfoBuff->bOEMReserved)));
    OUTREG16(&g_pNFC->SPARE[0][3], 0xFFFF);
    OUTREG32((UINT32 *) &g_pNFC->SPARE[0][4], 0xFFFFFFFF);
    OUTREG16(&g_pNFC->SPARE[0][6], 0xFFFF);
    OUTREG16(&g_pNFC->SPARE[0][7], pSectorInfoBuff->wReserved2);
}


//-----------------------------------------------------------------------------
//
//  Function: NFCClearSpare
//
//  This function clears the NAND flash controller spare area (all
//  ones written to the spare area will prevent the spare area of
//  the NAND memory device from being updated since only zeros are
//  written during a NAND program cycle).
//
//  Parameters:
//      None.
//
//  Returns:
//      None.
//
//-----------------------------------------------------------------------------
static VOID NFCClearSpare(VOID)
{
    UINT32 *dest = (UINT32 *) &g_pNFC->SPARE[0];

    OUTREG32(&dest[0], 0xFFFFFFFF);
    OUTREG32(&dest[1], 0xFFFFFFFF);
    OUTREG32(&dest[2], 0xFFFFFFFF);
    OUTREG32(&dest[3], 0xFFFFFFFF);
}


//-----------------------------------------------------------------------------
//
//  Function: FMD_Init
//
//  This function initializes the flash memory of a device.
//
//  Parameters:
//      lpActiveReg
//          [in] Pointer to the active registry string used to find device 
//          information from the registry. Set to NULL if not needed. 
//
//      pRegIn
//          [in] Pointer to a PCI_REG_INFO structure. Used to find flash 
//          hardware on PCI hardware. Set to NULL if not needed.
//
//      pRegOut
//          [in/out] Pointer to a PCI_REG_INFO structure. Used to return 
//          flash information. Set to NULL if not needed.
//
//  Returns:
//      A handle that can be used in a call to FMD_Deinit. It is the 
//      responsibility of the specific flash media driver (FMD) implementation 
//      to determine what this value represents. A value of zero (0) 
//      represents failure.
//
//-----------------------------------------------------------------------------
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
    PVOID rc = NULL;
    
    NFCSetClock(TRUE);
    
    // Perform NFC allocations, mappings, and initializations
    if (!NFCAlloc())
    {
        ERRORMSG(TRUE, (_T("FMD_Init: failed memory allocation/mapping\r\n")));
        goto cleanUp;
    }
    
#ifdef NAND_LARGE_PAGE
    // For large page size nand flash, the NFMS bit in register RCSR(CCM module) 
    // must be set
    if(!NFCSetPagesize(TRUE))
    {
        ERRORMSG(TRUE, (_T("FMD_Init: failed setting page size\r\n")));
        goto cleanUp;
    }
#endif
    
    // Unlock buffer pages
    INSREG16BF(&g_pNFC->NFC_CONFIGURATION, NANDFC_NFC_CONFIGURATION_BLS,
        NANDFC_NFC_CONFIGURATION_BLS_UNLOCKED);

    // Use NFC buffer #0 for all operations
    OUTREG16(&g_pNFC->RAM_BUFF_ADDRESS, 0);
    
    // Configure the NFC
    //  - Enable hardware ECC
    //  - Mask NFC interrupt
    //  - Little endian mode
    //  - Reset NFC state machine
    //  - CE signal operates normally
    OUTREG16(&g_pNFC->NAND_FLASH_CONFIG1, 
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_ECC_EN, NANDFC_NAND_FLASH_CONFIG1_ECC_EN_ENABLE) |
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_INT_MSK, NANDFC_NAND_FLASH_CONFIG1_INT_MSK_MASK) |
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_NF_BIG, NANDFC_NAND_FLASH_CONFIG1_NF_BIG_LITTLE) |
        CSP_BITFVAL(NANDFC_NAND_FLASH_CONFIG1_NF_CE, NANDFC_NAND_FLASH_CONFIG1_NF_CE_UNFORCE));    

    NF_CMD(CMD_RESET);     // Send flash reset command

    // Get manufacturer and device codes.
    NF_CMD(CMD_READID);     // Read ID command
    NF_ADDR(0);             // Required address cycle
    NF_RD_ID();             // Read ID into NFC buffer

    g_NandDeviceID = INREG16(&g_pNFC->MAIN[0]);
    
    if (g_NandDeviceID != NAND_ID_CODE)
    {
        ERRORMSG(TRUE, (_T("FMD_Init: invalid device ID (%x)\r\n"), g_NandDeviceID));
        goto cleanUp;
    }

    // Unlock all blocks
    OUTREG16(&g_pNFC->UNLOCK_START_BLK_ADD, 0);
    OUTREG16(&g_pNFC->UNLOCK_END_BLK_ADD, NAND_BLOCK_CNT-1);
    OUTREG16(&g_pNFC->NF_WR_PROT, NANDFC_NF_WR_PROT_WPC_UNLOCK);

    rc = g_pNFC;

cleanUp:
    NFCSetClock(FALSE);
    return rc;
}


//-----------------------------------------------------------------------------
//
//  Function: FMD_Deinit
//
//  This function de-initializes the flash chip.
//
//  Parameters:
//      hFMD 
//          [in] The handle returned from FMD_Init. 
//
//  Returns:  
//      Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_Deinit(PVOID hFMD)
{
    return(TRUE);
}


//-----------------------------------------------------------------------------
//
//  Function: FMD_ReadSector
//
//  This function reads the requested sector data and metadata from the 
//  flash media.
//
//  Parameters:
//      startSectorAddr 
//          [in] The starting physical sector address to read.
//
//      pSectorBuff 
//          [out] Pointer to the buffer that contains the sector data read 
//          from flash memory. Set to NULL if this data is not needed.
//
//      pSectorInfoBuff 
//          [out] Buffer for an array of sector information structures. There 
//          is one sector information entry for every sector that is to be read. 
//          Set to NULL if this data is not needed. 
//
//      dwNumSectors 
//          [in] Number of sectors to read.
//
//  Returns:  
//      Returns TRUE on success. Returns FALSE on failure.
//
//-----------------------------------------------------------------------------
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, 
    PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
    SECTOR_ADDR SectorAddr = startSectorAddr;
    UINT32 ColumnAddr, RowAddr;
    BOOL bSeqRead = FALSE;
    BOOL rc = FALSE;
            
    NFCSetClock(TRUE);
    
    while (dwNumSectors--)
    {
        RowAddr = (UINT32)SectorAddr/NAND_SECTORS_PERPAGE;
        ColumnAddr = ((UINT32)SectorAddr%NAND_SECTORS_PERPAGE)
                         * (NAND_SECTOR_SIZE + NAND_SPARE_SIZE); 
    
        // RETAILMSG(TRUE, (_T("FMD_ReadSector(0x%x)\r\n"), addr));
    
        if (pSectorBuff != NULL)
        {
            // If read access requires command and address to be sent
            if (!bSeqRead)
            {
                NF_CMD(CMD_READ);             // Send page read command.
                NF_ADDR_COL(ColumnAddr);      // Send column address
                NF_ADDR_PAGE(RowAddr);        // Send page address
                
#ifdef NAND_LARGE_PAGE
                NF_CMD(CMD_READ_2CYCLE);      // Send 2nd cycle read command
#endif
            }
            
            // Read page data into NFC buffer
            NF_RD_PAGE();
            
            // Move page data from NFC buffer sector buffer
            NFCReadMain(pSectorBuff);

            if (pSectorInfoBuff != NULL)
            {
                NFCReadSpare(pSectorInfoBuff);

                pSectorInfoBuff++;
            }

            pSectorBuff += NAND_SECTOR_SIZE;

            // Check for uncorrectable ECC errors in main and spare areas
            if (EXTREG16BF(&g_pNFC->ECC_STATUS_RESULT, NANDFC_ECC_STATUS_RESULT_ERM) == 
                NANDFC_ECC_STATUS_RESULT_ERM_2BIT_ERR)
            {
                ERRORMSG(TRUE, (_T("Uncorrectable ECC error\r\n")));
                goto cleanUp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -