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

📄 nor.c

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// 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) 2004, Motorola Inc. All Rights Reserved
//
//-----------------------------------------------------------------------------
//
// Copyright (C) 2004-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
//
//-----------------------------------------------------------------------------
//
// File:  nor.c
//
// Provides the implementation of the NOR flash library interface layer.
//
// IMPORTANT!
// ==========
//  
// 1. The flash library is not meant to be run XIP in flash. If not already
// residing out of flash, the library user should allocate some buffer 
// (use NORGetRelocateCodeSize() to get max required buffer size) and pass
// address of this buffer in NORLibInit() to relocate the flash functions.
// This may not be needed for flash parts that support simultaneous
// read/write/erase. 
//   
// 2. WinCE linker orders functions randomly, the following line must
// be added in the sources file of the exe or dll using the libraty to force 
// function ordering for relocation. Eg. see eboot/sources 
//
// LDEFINES=$(LDEFINES) /ORDER:@$(_TARGETPLATROOT)\SRC\DRIVERS\BLOCK\NORFMD\NORFLASHLIB\linkorder.txt 
//
// 3. If relocation is required, no msg printout is allowed. ie DEBUG MODE 
// MUST BE OFF! To debug the flash libraries, run it in RAM.
//
// 4. The flash library can make use of OS wait services in order to reduce
// use of polling if USE_OS_SERVICES is defined. However, in this case 
// RELOCATION CANNOT be USED since the flash programming codes will no longer
// be self contained!
//
//-----------------------------------------------------------------------------
#include <windows.h>

#include "nor.h"
#include "amd.h"
#include "strata.h"

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

//------------------------------------------------------------------------------
// Defines
#define MAX_SUPPORTED_FLASH_DRIVERS \
    (sizeof(g_LowLevelDrivers) / sizeof(NOR_FLASH_DRIVER))

#define MAX(a, b)   (((a) > (b)) ? (a) : (b))
#define MIN(a, b)   (((a) < (b)) ? (a) : (b))

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

//------------------------------------------------------------------------------
// Global Variables

//------------------------------------------------------------------------------
// Local Variables
// Table of supported lower level flash drivers.
static const NOR_FLASH_DRIVER g_LowLevelDrivers[] = {
    {
        AMDx16_RelocateBegin,
        AMDx16_IsFlashSupported,
        AMDx16_Program,
        AMDx16_EraseSector,
        AMDx16_EraseChip,
        AMDx16_RelocateEnd,
        AMDx16_LockSector,
        AMDx16_UnlockSector,        
        AMDx16_IsSectorLocked,
        L"AMD/Spansion x16 Flash Driver",
    },
    {
        StrataX16_RelocateBegin,
        StrataX16_IsFlashSupported,
        StrataX16_Program,
        StrataX16_EraseSector,
        NULL,
        StrataX16_RelocateEnd,
        StrataX16_LockSector,
        StrataX16_UnlockSector,        
        NULL,
        L"Intel Strata x16 Flash Driver",
    },
    // Add more low level flash drivers here
};

static NOR_FLASH_DRIVER g_FlashDriver;
static DWORD g_dwFlashDriverID = -1;
static NOR_FLASH_DESC g_FlashDesc;

static BOOL g_bShowProgress = FALSE;
static ULONG g_ulBytePerStep = 0;

//------------------------------------------------------------------------------
// Local Functions
static void PrintCFIData(NOR_FLASH_DESC *pFlashDesc);
static void PrintFlashID(NOR_FLASH_DESC *pFlashDesc);
static BOOL NORFindSector(ULONG *pulFlashAddr, ULONG *pulSectorSize);

//-----------------------------------------------------------------------------
// EXPORTED FUNCTIONS
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// Function: NORLibInit
//
// Function NOR library initialization.
// 
// Parameters:
//      ulFlashBase
//          [in] flash base address
//
//      ulRelocateBase
//          [in] address of buffer to relocate codes. codes will be relocated
//              if this parameter is non zero.
//				NOTE: This must be an address to uncached memory!
//
//      ulRelocSize
//          [in] size of buffer to relocate codes.
//
// Returns:
//      FALSE on failure
//
//-----------------------------------------------------------------------------
BOOL NORLibInit(ULONG ulFlashBase, ULONG ulRelocateBase, ULONG ulRelocSize)
{
    ULONG i;
    ULONG ulRelocLen;
    BOOL bSuccess;
    BOOL (*pIsFlashSupported)(NOR_FLASH_DESC *pFlashDesc);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("NORLibInit+0x%x 0x%x\r\n"), ulFlashBase, ulRelocateBase));

    if (ulRelocateBase != 0 && ulRelocSize < NORGetRelocateCodeSize()) {
        ERRORMSG(ZONE_ERROR, (TEXT("ERROR: Insufficient relocation size! Expected 0x%x\r\n"),
            NORGetRelocateCodeSize()));
        return FALSE;
    } else {
        DEBUGMSG(ZONE_FUNCTION, (TEXT("Init relocate base 0x%x 0x%x\r\n"), ulRelocateBase, ulRelocSize));
        memset((void *)ulRelocateBase, 0, ulRelocSize);
        DEBUGMSG(ZONE_FUNCTION, (TEXT("done relocate base 0x%x 0x%x\r\n"), ulRelocateBase, ulRelocSize));
    }

    memset(&g_FlashDesc, 0, sizeof(NOR_FLASH_DESC));
    g_dwFlashDriverID = -1;
    
    for (i = 0; i < MAX_SUPPORTED_FLASH_DRIVERS; i++) {
        pIsFlashSupported = g_LowLevelDrivers[i].IsFlashSupported;
        if (ulRelocateBase != 0) {
            // Relocate flash detection codes cos flash will not be accessible then.
            ulRelocLen = (ULONG)g_LowLevelDrivers[i].RelocateEnd - (ULONG)g_LowLevelDrivers[i].RelocateBegin;

            DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: Relocate 0x%x to 0x%x.\r\n"), 
                *(ULONG *)&g_LowLevelDrivers[i].RelocateBegin, ulRelocateBase));
            DEBUGMSG(ZONE_FUNCTION, (TEXT("%s detection code size 0x%x\r\n"), 
                g_LowLevelDrivers[i].lpszName, ulRelocLen));

            memcpy((BYTE *)ulRelocateBase, (BYTE *)g_LowLevelDrivers[i].RelocateBegin, ulRelocLen);
            
            *(ULONG *)&pIsFlashSupported = ((ULONG)g_LowLevelDrivers[i].IsFlashSupported - 
                (ULONG)g_LowLevelDrivers[i].RelocateBegin + (ULONG)ulRelocateBase);
            
            DEBUGMSG(ZONE_FUNCTION, (TEXT("pIsFlashSupported 0x%x\r\n"), pIsFlashSupported));
        }
        
        g_FlashDesc.FlashBase = ulFlashBase;
        bSuccess = pIsFlashSupported(&g_FlashDesc);
        DEBUGMSG(ZONE_FUNCTION, (TEXT("pIsFlashSupported %c\r\n"), bSuccess? 'T':'F'));
        if (bSuccess == TRUE) {
            memcpy(&g_FlashDriver, &g_LowLevelDrivers[i], sizeof(NOR_FLASH_DRIVER));
            g_dwFlashDriverID = i;
            break;
        }
    }
    
    if (g_dwFlashDriverID == -1 || g_dwFlashDriverID >= MAX_SUPPORTED_FLASH_DRIVERS || 
        g_FlashDriver.Program == NULL || g_FlashDriver.EraseSector == NULL) {
        ERRORMSG(ZONE_ERROR, (TEXT("ERROR: No supported NOR flash found!\r\n")));
        return FALSE;
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("ll driver index: %d\r\n"), i));
    
    if (ulRelocateBase != 0 && bSuccess == TRUE) {
        ulRelocLen = (ULONG)g_LowLevelDrivers[i].RelocateEnd - (ULONG)g_LowLevelDrivers[i].RelocateBegin;
        memcpy((BYTE *)ulRelocateBase, (BYTE *)g_LowLevelDrivers[i].RelocateBegin, ulRelocLen);

        DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: Relocate 0x%x to 0x%x.\r\n"), *(ULONG *)&g_LowLevelDrivers[i].RelocateBegin, ulRelocateBase));
        DEBUGMSG(ZONE_FUNCTION, (TEXT("%s relocate code size 0x%x\r\n"), g_LowLevelDrivers[i].lpszName, ulRelocLen));

        // Overwrite function pointer to point to relocated codes
        *(ULONG *)&g_FlashDriver.IsFlashSupported = (ulRelocateBase + (ULONG)g_FlashDriver.IsFlashSupported - (ULONG)g_FlashDriver.RelocateBegin);
        *(ULONG *)&g_FlashDriver.Program = (ulRelocateBase + (ULONG)g_FlashDriver.Program - (ULONG)g_FlashDriver.RelocateBegin);
        *(ULONG *)&g_FlashDriver.EraseSector = (ulRelocateBase + (ULONG)g_FlashDriver.EraseSector - (ULONG)g_FlashDriver.RelocateBegin);
        if (g_FlashDriver.EraseChip != NULL)
            *(ULONG *)&g_FlashDriver.EraseChip = (ulRelocateBase + (ULONG)g_FlashDriver.EraseChip - (ULONG)g_FlashDriver.RelocateBegin);

        DEBUGMSG(ZONE_FUNCTION, (TEXT("Relocated IsFlashSupported: 0x%x\r\n"), (ULONG)g_FlashDriver.IsFlashSupported));
        DEBUGMSG(ZONE_FUNCTION, (TEXT("Relocated Program: 0x%x\r\n"), (ULONG)g_FlashDriver.Program));
        DEBUGMSG(ZONE_FUNCTION, (TEXT("Relocated EraseSector: 0x%x\r\n"), (ULONG)g_FlashDriver.EraseSector));
        DEBUGMSG(ZONE_FUNCTION, (TEXT("Relocated EraseChip: 0x%x\r\n"), (ULONG)g_FlashDriver.EraseChip));
    }
    
    PrintCFIData(&g_FlashDesc);
    PrintFlashID(&g_FlashDesc);
    
    DEBUGMSG(ZONE_FUNCTION, (TEXT("NORLibInit-\r\n")));

    return bSuccess;
}

//-----------------------------------------------------------------------------
//
// Function: NORProgram
//
// Program the flash starting from the given address.
//
// Parameters:
//      ulStartAddress
//          [in] address to start writing from
//
//      pData
//          [in] ptr to data buffer to write
//
//      ulSize
//          [in] size of data to program
//
//      bIgnore0to1
//          [in] ignores programming 0 to 1 errors if TRUE
//
// Returns:
//      FALSE on failure
//
//-----------------------------------------------------------------------------
BOOL NORProgram(ULONG ulStartAddress, UCHAR *pData, ULONG ulSize, BOOL bIgnore0to1)
{
    BOOL bSuccess;
    BOOL bIsPaired;
    DWORD dwBusWidth;
    ULONG ulprogSize;


    DEBUGMSG(ZONE_FUNCTION, (TEXT("NORProgram+ 0x%x 0x%x 0x%x\r\n"),
        ulStartAddress, pData, ulSize));

    bIsPaired = g_FlashDesc.PairedFlash;
    dwBusWidth = bIsPaired? g_FlashDesc.DeviceWidth >> 2 : g_FlashDesc.DeviceWidth >> 3;

    // Check address is bus width aligned
    if ((ulStartAddress % dwBusWidth) != 0) {
        DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Unaligned start address for program: 0x%x buswith: %d\r\n"), 
            ulStartAddress, dwBusWidth));
        return FALSE;
    }
    
    // Check data size aligned wrt buswidth
    if ((ulSize % dwBusWidth) != 0) {
        DEBUGMSG(ZONE_ERROR, (TEXT("ERROR: Unaligned data size for program: 0x%x buswith: %d\r\n"), 
            ulSize, dwBusWidth));
        return FALSE;
    }

    if (g_bShowProgress) {
        while (ulSize) {
            ulprogSize = MIN(ulSize, g_ulBytePerStep);
        	DEBUGMSG(ZONE_FUNCTION, (TEXT("ulprogSize 0x%x ulSize 0x%x\r\n"), ulprogSize, ulSize));
            
            bSuccess = g_FlashDriver.Program(&g_FlashDesc, ulStartAddress, pData, ulprogSize, bIgnore0to1);
            if (bSuccess) {
                PROGRESSMSG(g_bShowProgress, (TEXT("P")));
                ulSize -= ulprogSize;
                ulStartAddress += ulprogSize;
                pData += ulprogSize;
            }
            else
                break;
        }
    }
    else
        bSuccess = g_FlashDriver.Program(&g_FlashDesc, ulStartAddress, pData, ulSize, bIgnore0to1);

    PROGRESSMSG(g_bShowProgress, (TEXT("\r\n")));

    DEBUGMSG(ZONE_FUNCTION, (TEXT("NORProgram- %c \r\n"), bSuccess? 'T' : 'F'));
    return bSuccess;
}

//-----------------------------------------------------------------------------
//
// Function: NORErase
//
// Erases the flash starting from the given address. 
//
// Note:
// All sectors overlapping the desired region is erased. 
//
// Parameters:
//      ulStartAddress
//          [in] address to start erase
//
//      ulLen
//          [in] size of region to erase
//
// Returns:
//      actual erase size on success or 0 on failure
//
//-----------------------------------------------------------------------------
ULONG NORErase(ULONG ulStartAddress, ULONG ulLen)
{
    ULONG ulFlashBase;
    BOOL bIsPaired;
    ULONG i;

⌨️ 快捷键说明

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