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

📄 flash.c

📁 WinCE 5.0的PXA270Bootloader
💻 C
📖 第 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.
//
//------------------------------------------------------------------------------
//
//  File:  flash.c
//
//  Flash routines for the Intel Mainstone II bootloader.
//
#include <windows.h>
#include <mainstoneii.h>
#include <oal_memory.h>
#include <fmd.h>
#include "loader.h"

// Defines.
//
#define FLASH_DEVICE_ID_L18_MIN    0x880C
#define FLASH_DEVICE_ID_L18_MAX    0x880F
#define FLASH_DEVICE_ID_L30_MIN    0x8812
#define FLASH_DEVICE_ID_L30_MAX    0x8815
#define FLASH_DEVICE_ID_K3_MIN     0x8801
#define FLASH_DEVICE_ID_K3_MAX     0x8803
#define FLASH_DEVICE_ID_K18_MIN    0x8805
#define FLASH_DEVICE_ID_K18_MAX    0x8807
#define FLASH_DEVICE_ID_J3_MIN     0x0016
#define FLASH_DEVICE_ID_J3_MAX     0x0018

// Type definitions.
//
typedef enum _FLASH_BLOCK_ARRAY_TYPE_
{
    CONSTANT_SIZE,
    BOTTOM_PARAMETER,
    TOP_PARAMETER
} FLASH_BLOCK_ARRAY_TYPE, *PFLASH_BLOC_ARRAY_TYPE;

typedef enum _FLASH_DEVICE_TYPE_
{
    NONE,
    L18, 
    L30,
    K3,
    K18,
    J3
} FLASH_DEVICE_TYPE, *PFLASH_DEVICE_TYPE;

// Local variables.
//
static FLASH_BLOCK_ARRAY_TYPE g_BlockArrayType  = CONSTANT_SIZE;
static FLASH_DEVICE_TYPE      g_FlashDeviceType = NONE;

static UINT32 FLASH_SIZE    = (16777216 * 2);   // Paired 16MB parts.
static UINT32 ERASE_BLOCKS  = 128;              // Total number of blocks (hiding parameter blocks).
static UINT32 L3_BLOCK_SIZE = 65536;            // 64KB per block on L3 (blocks 0 - 3).

// Global variables.
//
extern IMAGE_TYPE g_ImageType;


//------------------------------------------------------------------------------
//
//  Function:  OEMIsFlashAddr
//
// Checks the address provided and determines if it's a flash address or not.
//
BOOL OEMIsFlashAddr(DWORD dwAddr)
{
    DWORD dwVirtFlashStart = (DWORD) OALPAtoVA(MAINSTONEII_BASE_PA_BOOT_FLASH, FALSE);

    if ((dwAddr >= dwVirtFlashStart) && (dwAddr <= (dwVirtFlashStart + MAINSTONEII_SIZE_BOOT_FLASH)))
    {
        return(TRUE);
    }

    return(FALSE);
}


//------------------------------------------------------------------------------
//
//  Function:  OEMMapMemAddr
//
// Maps a flash address to a RAM address (used when temporarily caching a
// flash-destined download image to RAM).
//
LPBYTE OEMMapMemAddr (DWORD dwImageStart, DWORD dwAddr)
{

    if (OEMIsFlashAddr(dwAddr))
    {
        // The image being downloaded is a flash image - temporarily
        // cache the image in RAM until it's completely downloaded.
        //
        dwAddr -= dwImageStart;
        //TODO - constant.
        dwAddr += 0x80100000;
    }

    return((LPBYTE) (dwAddr));
}


//------------------------------------------------------------------------------
//
//  Function:  OEMStartEraseFlash
//
// Begins the flash erase procedure.
//
BOOL OEMStartEraseFlash (DWORD dwStartAddr, DWORD dwLength)
{
    return(TRUE);
}


//------------------------------------------------------------------------------
//
//  Function:  main
//
// Continues the flash erase procedure (erases are incrementally done during
// download to speed up the overall flash operation from the user's perspective).
//
void OEMContinueEraseFlash(void)
{
}


//------------------------------------------------------------------------------
//
//  Function:  OEMFinishEraseFlash
//
// Finished the flash erase procedure.
//
BOOL OEMFinishEraseFlash(void)
{
    return(TRUE);
}


BOOL OEMWriteFlash(DWORD dwImageStart, DWORD dwImageLength)
{
    BOOL  retVal = FALSE;
    UINT8 *pDataBuffer = (UINT8 *) OEMMapMemAddr(dwImageStart, dwImageStart);

    retVal = FlashWrite(dwImageStart, pDataBuffer, dwImageLength);

    // If we just wrote the bootloader to flash, halt and require the system to be rebooted.
    if (g_ImageType == IMAGE_TYPE_BOOTLOADER)
    {
        EdbgOutputDebugString("INFO: bootloader image stored successfully.\r\n");
        EdbgOutputDebugString("Reboot the system manually.  ");
        SpinForever();
    }

    return(retVal);

}


// START: these routines will be replaced by the FMD when it's done.
// TODO - clean these routines up.
static FLASH_DEVICE_TYPE DetectFlashDevice(UINT32 FlashBaseAddress)
{
    UINT32 nDeviceID = 0;
    volatile UINT32 *pFlash = (volatile UINT32 *)(FlashBaseAddress);

    // Get the flash part ID.
    //
    *pFlash   = 0x00900090;
    nDeviceID = (*(pFlash + 1) & 0xFFFF);

    // Put the flash part in read array mode.
    //
    *pFlash   = 0x00FF00FF;

    if ((nDeviceID >= FLASH_DEVICE_ID_L18_MIN) && (nDeviceID <= FLASH_DEVICE_ID_L18_MAX))
    {
        //EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is L18.\r\n");
        return(L18);
    }
    if ((nDeviceID >= FLASH_DEVICE_ID_L30_MIN) && (nDeviceID <= FLASH_DEVICE_ID_L30_MAX))
    {
        //EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is L30.\r\n");
        return(L30);
    }
    if ((nDeviceID >= FLASH_DEVICE_ID_K3_MIN) && (nDeviceID <= FLASH_DEVICE_ID_K3_MAX))
    {
        //EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is K3.\r\n");
        return(K3);
    }
    if ((nDeviceID >= FLASH_DEVICE_ID_K18_MIN) && (nDeviceID <= FLASH_DEVICE_ID_K18_MAX))
    {
        //EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is K18.\r\n");
        return(K18);
    }
    if ((nDeviceID >= FLASH_DEVICE_ID_J3_MIN) && (nDeviceID <= FLASH_DEVICE_ID_J3_MAX))
    {
        //EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is J3.\r\n");
        return(J3);
    }

    EdbgOutputDebugString("INFO: DetectFlashDevice: flash type is undetermined.\r\n");
    return(NONE);
}


static BOOL FlashErase(UINT32 FlashStart, UINT32 FlashLength)
{
    UINT32 i,j;
    UINT32 num_blocks;
    UINT32 num_blocks_to_erase;
    UINT32 num_l3_blocks_to_erase = 0;
    UINT32 num_l3_blocks_erased;
    UINT32 flash_start_address = (UINT32) OALPAtoVA(MAINSTONEII_BASE_PA_BOOT_FLASH, FALSE);
    volatile UINT32 *pFlash;
    UINT32 status;
    UINT32 BLOCK_SIZE = (FLASH_SIZE / ERASE_BLOCKS);

    // Make sure we know what kind of flash part we have.
    //
    if (g_FlashDeviceType == NONE)
    {
        EdbgOutputDebugString("ERROR: FlashErase: unrecognized flash part.\r\n");
        return(FALSE);
    }

    // Determine the number of blocks to erase.
    num_blocks = (FlashLength / (BLOCK_SIZE));
    if (FlashLength % (BLOCK_SIZE))
    {
        num_blocks++;
    }

    if (num_blocks < 1)
    {
        num_blocks = 1;
        EdbgOutputDebugString("WARNING: FlashErase: calculation error.  Erase blocks = %d\n\r", num_blocks);
    }

    else if (num_blocks > 128)
    {
        num_blocks = 128;
        EdbgOutputDebugString("WARNING: FlashErase: calculation error.  Erase blocks = %d\n\r", num_blocks);
    }

    // If Tyax flash, need to change block count based on if we're in the first 4 blocks
    // as the first 4 blocks are 16KWords (vs. 64KWords/block)
    if ((g_FlashDeviceType == L18) || (g_FlashDeviceType == L30))
    {
        // Is start address within the first 4 blocks.  As there are 2 devices in parallel,
        // are we within the first 128KWords (2 x 64KWords)?  If so, we need to account for
        // increased number of blocks - which is the first 256K of addy range
        if ((FlashStart >= flash_start_address) && (FlashStart < (flash_start_address + 0x40000)))
        {
            // If we're within the first 128K words (256K), we need to treat the block as a special case
            num_l3_blocks_to_erase = 4;
            num_blocks--; // Decrease the num_blocks count, as it assumes the first block is 64K

            // Now add the # of L3 blocks to the # blocks calc.'ed at the beginning to get total
            // # of blocks to erase on a given L3 device INCLUDING the first 4 16kWord blocks
            num_blocks = num_blocks + num_l3_blocks_to_erase;
        }
    }

    pFlash = (volatile UINT32 *)(FlashStart);

    // Issue the clear lock bits and confirm command.
    if (g_FlashDeviceType == J3)
    {
        // For J3 FLASH, unlock all blocks at once with one command
        num_blocks_to_erase = 1;
    }
    else if ((g_FlashDeviceType == K3) || (g_FlashDeviceType == K18)|| (g_FlashDeviceType == L18) || (g_FlashDeviceType == L30))
    {
        // For K3/K18 FLASH, unlock individual blocks one at a time
        num_blocks_to_erase = num_blocks;
    }

    // For L3, need to set for use within the FOR loop
    num_l3_blocks_erased = num_l3_blocks_to_erase;

    for (j = 0; j < num_blocks_to_erase; j++)
    {
        *pFlash = 0x00600060;
        *pFlash = 0x00d000d0;

        i = 0;
        while ((i & 0x00800080) != 0x00800080)
        {
            i = *pFlash;
        }

⌨️ 快捷键说明

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