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

📄 fmd.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//------------------------------------------------------------------------------
//
//  File: fmd.cpp
//
//  This file implements NAND flash media PDD. It doesn't use OMAP2420
//  NAND controller to access memory.
//
#include <windows.h>
#include <fmd.h>
#include <oal.h>
#include <omap2420.h>
#include <bsp_nand_cfg.h>
#include <bsp_base_regs.h>
//------------------------------------------------------------------------------
//  External functions

#ifdef FMD_ECC
BOOL ECC_ComputeECC(UCHAR *pData, DWORD size, UCHAR *pECC, DWORD eccSize);
BOOL ECC_IsDataValid(UCHAR *pData, DWORD size, UCHAR *pECC, DWORD eccSize);
BOOL ECC_CorrectData(UCHAR *pData, DWORD size, UCHAR *pECC, DWORD eccSize);
#endif

//------------------------------------------------------------------------------
//  Spare area on NAND used for OMAP2420

/*

//  MSFT's ECC spare area layout

#define ECC_SIZE        6

#pragma pack( push, 1 )
typedef struct {
    DWORD reserved1;            // Reserved - used by FAL
    BYTE  oemReserved;          // For use by OEM
    BYTE  badBlock;             // Indicates if block is BAD
    WORD  reserved2;            // Reserved - used by FAL
    BYTE  ecc[ECC_SIZE];        // ECC checksum
    WORD  unused;               // Unused...
} NAND_SPARE_AREA;
#pragma pack( pop )

*/

//  TI's ECC spare area layout

#define ECC_SIZE    3

#pragma pack( push, 1 )
typedef struct {
    WORD  badBlock1;            // Indicates if block is BAD
    BYTE  ecc[ECC_SIZE];        // ECC values
    BYTE  badBlock;             // Indicates if block is BAD
    BYTE  unused;               // Unused byte
    BYTE  oemReserved;          // For use by OEM
    WORD  reserved2;            // Reserved - used by FAL
    WORD  badBlock2;            // Indicates if block is BAD
    DWORD reserved1;            // Reserved - used by FAL
} NAND_SPARE_AREA;
#pragma pack( pop )


//------------------------------------------------------------------------------
//  Geometry info structure

typedef struct {
    UINT8  manufacturerId;
    UINT8  deviceId;
    UINT32 blocks;
    UINT32 sectorsPerBlock;
    UINT32 sectorSize;
    BOOL   extendedAddress;
} NAND_INFO;

//------------------------------------------------------------------------------
//  Hardware NAND registers structure

typedef volatile struct {
    UINT32 CMD;
    UINT32 ADDRESS;
    UINT32 DATA;
} NAND_REGS;

//------------------------------------------------------------------------------
//  Local Variable
static struct{
    OMAP2420_GPMC_REGS *pGPMCRegs;
    NAND_REGS *pNANDRegs;
    const NAND_INFO *pNANDInfo;
}g_fmd;// = {(OMAP2420_GPMC_REGS*)OMAP2420_GPMC_REGS_PA, (NAND_REGS*)BSP_NAND_REGS_PA, 0};

//------------------------------------------------------------------------------
//  NAND geometry info

static const NAND_INFO g_nandInfo[] = { BSP_NAND_INFO };

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

_inline static BOOL NAND_WaitForReady();
static BOOL NAND_SendFullCommand(UINT8 cmd, SECTOR_ADDR sector, UINT32 offset);
static BOOL NAND_FinishCommand(UINT8 cmd);
static VOID NAND_Read(UINT8 *pBuffer, UINT32 bytes);
static VOID NAND_Write(UINT8 *pBuffer, UINT32 bytes);

//------------------------------------------------------------------------------
//
//  Function:  FMD_Init
//
//  This function is called to initialize flash subsystem.
//
PVOID FMD_Init(LPCTSTR pActive, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
    HANDLE hFMD = NULL;
    UINT8 manufacturer, device;
    UINT32 ix;

//	OALLog(L"FMD_Init+\r\n");
//	OALLog(L"FMD_Init+ [0x%x]\r\n", 0xFF);

    // Map NAND registers
    g_fmd.pGPMCRegs = (OMAP2420_GPMC_REGS*)OMAP2420_GPMC_REGS_PA;
    g_fmd.pNANDRegs = (NAND_REGS*)BSP_NAND_REGS_PA;
     
    // Wait for NAND
    if (!NAND_WaitForReady()) goto cleanUp;

    // Send Read ID Command
    OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_READID);

    // Wait for NAND
    if (!NAND_WaitForReady()) goto cleanUp;

    // Send Address 00h
    OUTREG16(&g_fmd.pNANDRegs->ADDRESS, 0);
    if (!NAND_WaitForReady()) goto cleanUp;

    // Read the manufacturer ID & device code
    manufacturer = (UINT8)INREG16(&g_fmd.pNANDRegs->DATA);
    device = (UINT8)INREG16(&g_fmd.pNANDRegs->DATA);

    // Find if we support chip
    g_fmd.pNANDInfo = NULL;
    for (ix = 0; ix < sizeof(g_nandInfo)/sizeof(g_nandInfo[0]); ix++) {
        if (
            manufacturer == g_nandInfo[ix].manufacturerId &&
            device == g_nandInfo[ix].deviceId
        ) {
          g_fmd.pNANDInfo = &g_nandInfo[ix];
          break;
        }
    }

    // If we don't support NAND, fail...
    if (g_fmd.pNANDInfo == NULL) goto cleanUp;

    // We are done
    hFMD = &g_fmd;

cleanUp:
    return hFMD;
}

//------------------------------------------------------------------------------
//
//  Function:  FMD_Deinit
//
BOOL FMD_Deinit(VOID *pContext)
{
    return TRUE;
}

//------------------------------------------------------------------------------
//
//  Function:  FMD_GetInfo
//
//  This function is call to get flash information
//
BOOL FMD_GetInfo(FlashInfo *pFlashInfo)
{
    BOOL rc = FALSE;

    // If we don't support NAND, fail...
    if (g_fmd.pNANDInfo == NULL) goto cleanUp;

    // Memory type is NAND
    pFlashInfo->flashType = NAND;
    pFlashInfo->dwNumBlocks = g_fmd.pNANDInfo->blocks;
    pFlashInfo->wSectorsPerBlock = g_fmd.pNANDInfo->sectorsPerBlock;
    pFlashInfo->wDataBytesPerSector = g_fmd.pNANDInfo->sectorSize;
    pFlashInfo->dwBytesPerBlock =
        g_fmd.pNANDInfo->sectorSize * g_fmd.pNANDInfo->sectorsPerBlock;

    // Done
    rc = TRUE;

cleanUp:
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  FMD_ReadSector
//
//  Read the content of the sector.
//
//	OALLog(L"FMD_Init+\r\n");
//	OALLog(L"FMD_Init+ [0x%x]\r\n", 0xFF);

BOOL FMD_ReadSector(
    SECTOR_ADDR sector, UCHAR *pBuffer, SectorInfo *pSectorInfo, DWORD sectors
) {
    BOOL rc = FALSE;
    NAND_SPARE_AREA sa;

    // There isn't clear semantic how to read more than one sector
    if (sectors > 1 || g_fmd.pNANDInfo == NULL) goto cleanUp;

    // Read sector from A
    if (pBuffer != NULL) {
        NAND_SendFullCommand(BSP_NAND_CMD_READ, sector, 0);
        NAND_Read(pBuffer, g_fmd.pNANDInfo->sectorSize);
    }

    // Write the command
    NAND_SendFullCommand(BSP_NAND_CMD_READ2, sector, 0);
    // Read NAND spare area data
    NAND_Read((UINT8*)&sa, sizeof(sa));

    // Copy sector info
    if (pSectorInfo != NULL) {
        pSectorInfo->bBadBlock = sa.badBlock;
        pSectorInfo->bOEMReserved = sa.oemReserved;
        pSectorInfo->dwReserved1 = sa.reserved1;
        pSectorInfo->wReserved2 = sa.reserved2;
    }

#ifdef FMD_ECC
    // Verify ECC
    if (pBuffer != NULL) {
        UINT32 i;

        // Check if we get same ECC from data
        if (!ECC_IsDataValid(
            pBuffer, g_fmd.pNANDInfo->sectorSize, sa.ecc, ECC_SIZE
        )) {
            //  Now try to correct them
            if (!ECC_CorrectData(
                pBuffer, g_fmd.pNANDInfo->sectorSize, sa.ecc, ECC_SIZE
            )) {
                // Check if spare and data are all 0xFF - erased sector
                for (i = 0; i < sizeof(sa); i++) {
                    if (((UINT8*)&sa)[i] != 0xFF) goto cleanUp;
                }                    
                for (i = 0; i < g_fmd.pNANDInfo->sectorSize; i++) {
                    if (pBuffer[i] != 0xFF) goto cleanUp;
                }                    
            }                
        }
    }
#endif

    // Done
    rc = TRUE;

cleanUp:
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  FMD_WriteSector
//
BOOL FMD_WriteSector(
    SECTOR_ADDR sector, UCHAR *pBuffer, SectorInfo *pSectorInfo, DWORD sectors
) {
    BOOL rc = FALSE;
    NAND_SPARE_AREA sa;

    
    // Remove flash write protection
    SETREG32(&g_fmd.pGPMCRegs->ulGPMC_CONFIG,BIT4);

    // There isn't clear semantic how to read more than one sector
    if (sectors > 1 || g_fmd.pNANDInfo == NULL) goto cleanUp;

    // When there is buffer write data
    if (pBuffer != NULL) {

        // Select A area
        OUTREG16(&g_fmd.pNANDRegs->CMD, BSP_NAND_CMD_READ);
        // Issue command
        NAND_SendFullCommand(BSP_NAND_CMD_WRITE, sector, 0);
        // Write the data
        NAND_Write(pBuffer, g_fmd.pNANDInfo->sectorSize);
#ifdef FMD_ECC
        // Calculate the ECC
        ECC_ComputeECC(
            pBuffer, g_fmd.pNANDInfo->sectorSize, sa.ecc, ECC_SIZE
        );
#else
        memset(sa.ecc, 0xFF, ECC_SIZE);
#endif
        // Finish up the write operation

⌨️ 快捷键说明

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