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

📄 flash.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
字号:
#include <windows.h>
#include <halether.h>
#include <blcommon.h>
#include <oalio.h>
#include <alt_def.h>
#include "bootldr.h"
#include "flash1.h"

#include "workitem.h"


#define FLASH_START     (KSEG1_BASE|FLASH_BASE)
#define FLASH_END       0xA6000000
#define FLASH_CACHE     0x80000000

#define FLASH_BLOCK_SIZE    0x40000
#define TOTAL_FLASH_BLOCKS  ((FLASH_END - FLASH_START)/FLASH_BLOCK_SIZE)
#define FLASH_BLOCKS_PER_BANK  64
#define ROMOFFSET       0x00000000


typedef enum {
    eDIRTY,
    ePENDING,
    eERASED,
    eFLASHED
} TEraseStatus;

BOOL CloseFlash(DWORD dwStartAddr, DWORD dwLength);
BOOL FlashWriteBlock(DWORD dwBlkNum, DWORD cbData, DWORD dwFlashAddr, LPDWORD pdwCache);

DWORD gdwStartBlock;
DWORD gdwEndBlock;
int gnBlocks;
int gnErased = 0;
#define MAX_RETRIES     64
int gnRetries = 0;
static TEraseStatus gStatus[TOTAL_FLASH_BLOCKS];

FM_ERROR FM_ErrorCode;

BOOL FlashInit(VOID)
{
    int i;
    UINT uFlashDevCount = 0;
    BOOL bContinueDetect = TRUE;
    DWORD dwFlashAddr = FLASH_START;
    DWORD *dwBlockEndTable;
    DWORD dwSizeOfFlash=0;
    DWORD dwNumberOfBlocks;
    BYTE mID;
    BYTE dID;

    EnableFlash();

    while (bContinueDetect)
    {
        FLASH_WRITE_CMD(dwFlashAddr, INTELLIGENT_IDENTIFIER32);
        mID = LOBYTE(FLASH_READ_CMD(dwFlashAddr));
        dID = LOBYTE(FLASH_READ_CMD(dwFlashAddr+sizeof(DWORD)));

        for (i=0; i< NUMBER_OF_SUPPORTED_DEVICE; i++)
        {
            if ((mID == _fd1[i].ManufactureCode) && (dID == _fd1[i].DeviceCode))
            {
                dwNumberOfBlocks = _fd1[i].NumberOfBlocks;
                dwBlockEndTable = _fd1[i].BlockEnd;
                dwSizeOfFlash += _fd1[i].TotalSize * sizeof(DWORD)/_fd1[i].InterfaceWidth;
                uFlashDevCount++;
                break;
            }
        }

        FLASH_WRITE_CMD(dwFlashAddr, READ_ARRAY32);
        dwFlashAddr+= dwSizeOfFlash;

        // no more than 2 devices on system
        if (uFlashDevCount >= 2)
            bContinueDetect = FALSE;
    }

    DisableFlash();

    {
        if (TOTAL_FLASH_BLOCKS != (FLASH_BLOCKS_PER_BANK *2))
        {
            EdbgOutputDebugString("Flash block setting not correctly\r\n");
            SPIN_FOREVER;
        }

    }
    // initialize status array
    for (i=0; i<TOTAL_FLASH_BLOCKS; i++)
        gStatus[i] = eFLASHED;

    return TRUE;
}



LPBYTE OEMMapMemAddr (DWORD dwImageStart, DWORD dwAddr)
{
    DWORD dwMappedAddr = dwAddr;

    if (OEMIsFlashAddr(dwAddr))
        dwMappedAddr = dwAddr + FLASH_CACHE - dwImageStart;
    else
        dwMappedAddr = dwAddr - ROMOFFSET;

#if 0
    EdbgOutputDebugString("   dwImageStart = %x dwAddr=%x dwMappedAddr=%x\r\n", 
                                                        dwImageStart,
                                                        dwAddr,
                                                        dwMappedAddr);
#endif // 0
    return (LPBYTE)dwMappedAddr;
}



BOOL OEMIsFlashAddr (DWORD dwAddr)
{

    //EdbgOutputDebugString("***OEMIsFlashAddr():dwAddr = %x", dwAddr);

    dwAddr |= 0xA0000000;       // make sure the address are virtual address

    if ( dwAddr>= FLASH_START && dwAddr < FLASH_END)
    {
        //EdbgOutputDebugString("   *** in Flash\r\n");
        return TRUE;
    }
    //EdbgOutputDebugString("   *** not in Flash\r\n");
    return FALSE;
}



BOOL OEMStartEraseFlash (DWORD dwStartAddr, DWORD dwLength)
{
    DWORD i;

    dwStartAddr |= 0xA0000000;      // convert into virtual address

    EdbgOutputDebugString("+OEMStartEraseFlash:dwStartAddr = %x dwLength=%x\r\n", dwStartAddr, dwLength);

    // make sure we are processing flash address
    if (!OEMIsFlashAddr(dwStartAddr))
    {
        EdbgOutputDebugString("The starting address is NOT a flash address(0x%X)\r\n", dwStartAddr);
        return FALSE;
    }

    if ((dwStartAddr & 0x03) || (dwLength & 0x03))
    {
        EdbgOutputDebugString("Flash address or length Not DWORD aligned\r\n");
        return FALSE;
    }

    // enable flash write
    EnableFlash();

    gdwStartBlock = (dwStartAddr - FLASH_START) / FLASH_BLOCK_SIZE;
    gdwEndBlock = (dwStartAddr + dwLength +(FLASH_BLOCK_SIZE-1) -FLASH_START)/ FLASH_BLOCK_SIZE;
    gnBlocks = (int)(gdwEndBlock - gdwStartBlock);

    // initial the status table
    for (i = gdwStartBlock; i < gdwEndBlock; i++)
    {
        gStatus[i] = eDIRTY;
    }

    OEMContinueEraseFlash();

    EdbgOutputDebugString("-OEMStartEraseFlash: StartBlock = 0x%X, EndBlock= 0x%X\r\n", gdwStartBlock, gdwEndBlock);

    return TRUE;

}



void OEMContinueEraseFlash (void)
{
    DWORD i;
    DWORD dwFlashAddr = KSEG1_BASE|FLASH_BASE|(gdwStartBlock * FLASH_BLOCK_SIZE);

    //EdbgOutputDebugString("+OEMContinueEraseFlash()\r\n");

    if (!gnBlocks || (gnBlocks == gnErased))
    {
        // already completed, do nothing
        return;
    }

    if (gnRetries >= MAX_RETRIES)
    {
        EdbgOutputDebugString("   Too many retries\r\n");
        return;
    }

    if (gdwEndBlock > FLASH_BLOCKS_PER_BANK)
    {
        DWORD dwFlashAddr1 = KSEG1_BASE|FLASH_BASE|(FLASH_BLOCKS_PER_BANK * FLASH_BLOCK_SIZE);
        EdbgOutputDebugString("Pass bank boundary(%X)\r\n", dwFlashAddr1);
        FLASH_WRITE_CMD(dwFlashAddr1, READ_ARRAY32);
        FLASH_WRITE_CMD(dwFlashAddr1, READ_ARRAY32);
    }

    for (i = gdwStartBlock; i< gdwEndBlock; i++)
    {
        // initialize reading
        FLASH_WRITE_CMD(dwFlashAddr, READ_STATUS_REGISTER32);

        switch (gStatus[i])
        {
        case eDIRTY:
            // if the block is busy, come back to it later
            if (FLASH_STATUS(dwFlashAddr,FM_WSMS32) != FM_WSMS32)
                break;

            FLASH_WRITE_CMD(dwFlashAddr, READ_ARRAY32);
            FLASH_WRITE_CMD(dwFlashAddr, CLEAR_STATUS_REGISTER32);
            FLASH_WRITE_CMD(dwFlashAddr, ERASE_SETUP32);
            FLASH_WRITE_CMD(dwFlashAddr, ERASE_RESUME32);

            gStatus[i] = ePENDING;
            break;

        case ePENDING:
            // if the block is busy, come back to it later
            if (FLASH_STATUS(dwFlashAddr, FM_WSMS32) != FM_WSMS32)
                break;

            EdbgOutputDebugString("CurBlock=%d status=ePENDING\r\n", i);

            // check for operation errors
            if (FLASH_STATUS(dwFlashAddr, FM_ERROR_MASK32)!= 0)
            {
                EdbgOutputDebugString("ePENDING erase error\r\n");
                gStatus[i]=eDIRTY;
                gnRetries++;
                break;
            }
            gStatus[i] = eERASED;
            gnErased++;
            break;

        case eERASED:
            //EdbgOutputDebugString("eERASED: \r\n");
            break;

        case eFLASHED:
            //EdbgOutputDebugString("eFLASHED: \r\n");
            break;

        default:
            EdbgOutputDebugString("ERROR: \r\n");
            return;
        }

        dwFlashAddr+=FLASH_BLOCK_SIZE;
    }
    //EdbgOutputDebugString("-OEMContinueEraseFlash\r\n");
}



BOOL OEMFinishEraseFlash (void)
{
    EdbgOutputDebugString("+OEMFinishEraseFlash\r\n");
    if (!gnBlocks)
    {
        EdbgOutputDebugString("   no block\r\n");
        return FALSE;
    }

    while ((gnRetries < MAX_RETRIES) && (gnBlocks != gnErased))
    {
        OEMContinueEraseFlash();
    }

    {
        DWORD i;
        for (i = gdwStartBlock; i< gdwEndBlock; i++)
        {
            if (gStatus[i]!= eERASED)
                EdbgOutputDebugString("eStatus[%d]=%X\r\n", i, gStatus[i]);
        }
    }
    return gnBlocks == gnErased;
}



BOOL OEMWriteFlash (DWORD dwStartAddr, DWORD dwLength)
{
    DWORD dwCurSec;
    DWORD dwByteLeft;
    DWORD dwFlashAddr;
    LPBYTE pbCacheAddr;
    DWORD cbData;
    DWORD i;

    if (gnErased != gnBlocks)
    {
        EdbgOutputDebugString("   error Erased(%d)!=Blocks(%d)\r\n", gnErased, gnBlocks);
        return FALSE;
    }

    // wait for 3 secs
    dwCurSec = OEMEthGetSecs();
    while (OEMEthGetSecs() - dwCurSec < 3)
        ;

    EdbgOutputDebugString("OEMWriteFlash():dwStartAddr = %x dwLength=%X\r\n", dwStartAddr, dwLength);

    // start writing to flash
    dwByteLeft = dwLength;
    dwFlashAddr = dwStartAddr;
    pbCacheAddr = OEMMapMemAddr(dwStartAddr, dwFlashAddr);

    cbData = FLASH_BLOCK_SIZE - (dwStartAddr % FLASH_BLOCK_SIZE);

    for (i=gdwStartBlock;i<gdwEndBlock;i++)
    {
        EdbgOutputDebugString("   flashing block[%d], length =%X, dest=%X, src=%X\r\n",
                            i, cbData, dwFlashAddr, pbCacheAddr);
        if (!FlashWriteBlock(i, cbData, dwFlashAddr, (LPDWORD)pbCacheAddr))
        {
            EdbgOutputDebugString("Error flashing block %d, ABORT!\r\n", i);
            return FALSE;
        }

        gStatus[i]=eFLASHED;
        dwByteLeft -= cbData;
        dwFlashAddr += cbData;
        pbCacheAddr = OEMMapMemAddr(dwStartAddr, dwFlashAddr);
        cbData = (dwByteLeft > FLASH_BLOCK_SIZE)? FLASH_BLOCK_SIZE:dwByteLeft;
    }


    // wait for 3 secs
    dwCurSec = OEMEthGetSecs();
    while (OEMEthGetSecs() - dwCurSec < 3)
        ;

    gnErased = 0;
    gnRetries = 0;

    return CloseFlash(dwStartAddr, dwLength);
}



BOOL CloseFlash(DWORD dwStartAddr, DWORD dwLength)
{
    // disable the flash write anyway
    DisableFlash();

    // compare data
    return TRUE;
}



BOOL FlashWriteDWORD(DWORD dwFlashAddr, void *pSrc)
{
    DWORD dwCurSec;
    DWORD * pdwSrc = (DWORD *)pSrc;

    dwFlashAddr |= 0xA0000000;
    //EdbgOutputDebugString("Flashing %X=%X\r\n", dwFlashAddr, *pdwSrc);

    FLASH_WRITE_CMD(dwFlashAddr, READ_ARRAY32);
    FLASH_WRITE_CMD(dwFlashAddr, CLEAR_STATUS_REGISTER32);
    FLASH_WRITE_CMD(dwFlashAddr, PROGRAM_SETUP32);

    *((DWORD *)dwFlashAddr) = *pdwSrc;

    dwCurSec = OEMEthGetSecs();
    do {
        FLASH_WRITE_CMD(dwFlashAddr, READ_STATUS_REGISTER32);
        if ( FLASH_STATUS(dwFlashAddr,FM_WSMS32) == FM_WSMS32)
        {
            if (FLASH_STATUS(dwFlashAddr,FM_ERROR_MASK32)== 0)
                return TRUE;
            else
                EdbgOutputDebugString("FlashWriteDWORD::write error\r\n");
        }
    } while(OEMEthGetSecs()- dwCurSec < PROGRAM_TIMEOUT);

    FM_ErrorCode = Program_Timeout;
    FLASH_WRITE_CMD(dwFlashAddr, READ_ARRAY32);
    FLASH_WRITE_CMD(dwFlashAddr, READ_ARRAY32);
    return FALSE;
}



BOOL FlashWriteBlock(DWORD dwBlkNum, DWORD cbData, DWORD dwFlashAddr, LPDWORD pdwCache)
{
    DWORD dwBlockAddr = KSEG1_BASE|FLASH_BASE|(dwBlkNum * FLASH_BLOCK_SIZE);
    DWORD cdwData = (cbData+sizeof(DWORD)-1)/sizeof(DWORD);

    if (dwBlkNum == FLASH_BLOCKS_PER_BANK)
    {
        FLASH_WRITE_CMD(dwBlockAddr, READ_ARRAY32);
        FLASH_WRITE_CMD(dwBlockAddr, READ_ARRAY32);
    }

    while (cdwData)
    {
        if(!FlashWriteDWORD(dwFlashAddr, pdwCache))
        {
            EdbgOutputDebugString("   Flashing error at %X\r\n",dwFlashAddr);
            return FALSE;
        }
        cdwData--;
        pdwCache++;
        dwFlashAddr+=sizeof(DWORD);
        if ((cdwData % 0x800)==0)
            EdbgOutputDebugString(".");
    }
    EdbgOutputDebugString("\r\n");
    return TRUE;
}

⌨️ 快捷键说明

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