用CFlashAmd对些DBAU1200开发板的BOOT FLASH

//========================================================================
//TITLE:
//    DBAU1200开发板的BOOT FLASH读写
//AUTHOR:
//    norains
//DATE:
//    Saturday  31-May-2008
//Environment:
//    VS2005 + DBAU1200 BOARD + MIPSII SDK
//========================================================================

    WinCE的一个好处就是,能够在应用程序中访问物理内存。也正是在这个基础之上,才使我们在应用程序中能够更新boot flash。
    
    为了使用上方便,已经将flash的读写操作封装为Class,在此先看代码:    
    
//////////////////////////////////////////////////////////////////////
// Flash.h
//
//////////////////////////////////////////////////////////////////////
namespace Flash
{
    //Flash information
    struct FlashInfo
    {    
        int Bank;
        int Width;
        unsigned long Size;    //The size of the flash    
        unsigned long SectorSize; //The sector size, in bytes.
        unsigned long BootSectorCount;
        unsigned long BootSectorSize;
        unsigned long WriteBufferSize;
    };

    //The information of the specified flash
    const FlashInfo    FLASH_INFO_AM29LV256M = {2,16,0x04000000,0x10000,0,0,(16 * (16 / 8))};
};

//////////////////////////////////////////////////////////////////////
// FlashAmd.h: interface for the CFlashAmd class.
//
//Version:
//    1.1.0
//
//Date:
//    2008.05.29
//
//Description:
//    
//
//////////////////////////////////////////////////////////////////////


#pragma once

#include "Flash.h"


class CFlashAmd
{

public:
    //Interface

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Erase the flash
    //
    //Parameters:
    //    ulAddressOffset : [in] The offset address to erase
    //    ulSize : [in] The number of byte
    //    bCompletion : If true, the function would return after finish erasing,or it would return immediately.
    //
    //-------------------------------------------------------------------------------------------------------
    virtual bool EraseFlash(unsigned long ulAddressOffset,unsigned long ulSize,bool bCompletion );


    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Lock the flash
    //
    //Parameters:
    //    ulAddressOffset : [in] The offset address to lock
    //    ulSize : [in] The number of byte to lock
    //-------------------------------------------------------------------------------------------------------
    virtual void LockFlash(unsigned long ulAddressOffset,unsigned long ulSize);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Unlock the flash
    //
    //Parameters:
    //    ulAddressOffset : [in] The offset address to unlock
    //    ulSize : [in] The number of byte to unlock
    //-------------------------------------------------------------------------------------------------------
    virtual void UnlockFlash(unsigned long ulAddressOffset,unsigned long ulSize);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Read the flash
    //
    //Parameters:
    //    ulAddressOffset : [in] The offset address to read
    //    pDataStore : [out] The buffer for storing the data.
    //    ulSize : [in] The size of the buffer
    //-------------------------------------------------------------------------------------------------------
    virtual bool ReadFlash(unsigned long ulAddressOffset,void *pDataStore,unsigned long ulSize);    

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Wait for finishing erasing
    //
    //Parameters:
    //    ulAddressOffset : [in] The offset address to wait
    //-------------------------------------------------------------------------------------------------------
    virtual bool WaitForEraseComplete(unsigned long ulAddressOffset);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Write the data to the flash    
    //
    //Parameters:
    //    ulAddressOffset : [in] The offset address to write.
    //    pDataWrite : [in] The data buffer to write
    //    ulSize : [in] The source buffer length in bytes,must be multiple of 4
    //    bErase : [in] If true, it would erase the block before writing.
    //-------------------------------------------------------------------------------------------------------
    virtual bool WriteFlash(unsigned long ulAddressOffset,const void * pDataWrite,unsigned long ulSize,bool bErase);

    
    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Set the flash base address
    //
    //Parameters:
    //    dwAddress : [in] The base address to set
    //-------------------------------------------------------------------------------------------------------
    bool SetFlashAddressBase(unsigned long ulAddress);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Set the flash base address
    //-------------------------------------------------------------------------------------------------------
    unsigned long GetFlashAddressBase(void);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Set the flash information
    //-------------------------------------------------------------------------------------------------------
    bool SetFlashInfo(const Flash::FlashInfo & flashInfo);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Get the flash information
    //-------------------------------------------------------------------------------------------------------
    const  Flash::FlashInfo& GetFlashInfo();


public:
    CFlashAmd(void);
    ~CFlashAmd(void);


private:
    
    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Return the base address of a FLASH bank
    //
    //Parameters:
    //    iBank : [in] Bank number (zero based)
    //
    //Return Values:
    //    Base address of the FLASH bank
    //
    //-------------------------------------------------------------------------------------------------------
    unsigned long GetBankBaseAddress(int iBank);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Returns the index of the FLASH bank containing the specified address
    //
    //Parameters:
    //    ulAddr : [in] FLASH Address
    //
    //Return Values:
    //    Index of the FLASH bank containing Address
    //
    //-------------------------------------------------------------------------------------------------------
    int GetBankIndex(unsigned long ulAddr);

        
    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    IssueFlashCommand RESET/UNLOCK/ERASE/.....
    //
    //Parameters:
    //    ulCommand : [in] command id
    //    ulParam1, ulParam2 : [in] Command Dependent:
    //        CMDRESET:            ulParam1 - FLASH Bank
    //                            ulParam2 - Ignore
    //        CMDUNLOCK:            ulParam1 - FLASH Bank
    //                            ulParam2 - Ignore
    //        CMDERASESET:        ulParam1 - FLASH Bank
    //                            ulParam2 - Ignore
    //        CMDERASESECTOR:        ulParam1 - FLASH Bank
    //                            ulParam2 - Sector
    //        CMDPROGRAM:            ulParam1 - FLASH Bank
    //                            ulParam2 - Ignore
    //        CMDWRITEBUFFER:        ulParam1 - Program Location
    //                            ulParam2 - Word Count - 1. Present twice in 32bit word
    //        CMDCOMMITBUFFER:    ulParam1 - Program Location
    //                            ulParam2 - Ignore
    //
    //Return Values:
    //    NONE
    //
    //-------------------------------------------------------------------------------------------------------
    void IssueFlashCommand(unsigned long ulCommand, unsigned long ulParam1, unsigned long ulParam2);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Get the address of the specified sector
    //
    //Parameters:
    //    iBank : [in] Bank number (zero based)
    //    ulSector : [in] Sector number
    //
    //Return Values:
    //    Address of the sector
    //
    //-------------------------------------------------------------------------------------------------------
    unsigned long GetSectorAddress(int iBank, unsigned long ulSector);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Return the size of sector, uses GetFlashInfo().Width to handle the case of two 16bit FLASH parts in parallel to form up a 32bit word.
    //
    //Parameters:
    //    ulSector - Sector number
    //
    //Return Values:
    //    Size in bytes of the sector including both parts
    //
    //-------------------------------------------------------------------------------------------------------
    unsigned long GetSectorSize(unsigned long ulSector);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Returns the index of the FLASH bank and sector containing the specified address
    //
    //Parameters:
    //    ulAddress : [in] FLASH Address
    //    iBank : [out] The variable to receive the Bank containing Address
    //    ulSector : [out] The variable to receive the Sector containing Address
    //
    //Return Values:
    //    NONE
    //
    //-------------------------------------------------------------------------------------------------------
    void GetBankAndSectorIndex(unsigned long ulAddress, int & iBank, unsigned long & ulSector);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Erases the specified sector and waits until sector is completely erased.
    //    Typical sector erase time varies from 0.7 seconds to 15 seconds.. See data sheet
    //
    //Parameters:
    //    BYTE bSector. Sector number to be erased .. 0 denotes SA0 and 70 denotes SA70
    //
    //Return Values:
    //    True to indicate that sector has been successfully erased and flash is ready for other operation
    //
    //-------------------------------------------------------------------------------------------------------
    bool EraseSectorWithCompletion(int iBank, unsigned long ulSector, bool bCompletion);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Erases the specified sector
    //
    //Parameters:
    //    iBank : [in] Bank being worked on
    //    ulSector : [in] Sector number to be erased

    //
    //Return Values:
    //    True to indicate that erase command has been successfully erased
    //
    //-------------------------------------------------------------------------------------------------------
    bool EraseSector(int iBank, unsigned long ulSector);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Get the status of operations(write/erase) on the flash
    //
    //Parameters:
    //    ulAddress : [in] Address of the flash to check status
    //
    //Return Values:
    //    STATUSREADY flash has completed an operation and is ready for new operation0
    //    STATUSERASESUSPEND .. flash erase has been suspended
    //    STATUSTIMEOUT Time out
    //    STATUSBUSY  Busy
    //    STATUSERROR Error
    //
    //-------------------------------------------------------------------------------------------------------
    unsigned long GetFlashStatus(unsigned long ulAddress);


    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Program an entire write buffers worth of data
    //
    //Parameters:
    //    
    //
    //Return Values:
    //    
    //
    //-------------------------------------------------------------------------------------------------------
    bool WriteFlashBuffer(unsigned long ulAddress,const void * pSrcData, unsigned long ulByteCount);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Write the data to the flash address base on the flash width.
    //-------------------------------------------------------------------------------------------------------
    bool WriteFlash(unsigned long ulAddr, unsigned long ulValue);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Read the flash data from the address base on the flash width.
    //-------------------------------------------------------------------------------------------------------
    unsigned long ReadFlash(unsigned long ulAddr);


    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Write the flash which the width is 32bit
    //-------------------------------------------------------------------------------------------------------
    bool WriteFlash32(unsigned long ulAddr, unsigned long ulValue);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Read the flash which the width is 32bit
    //-------------------------------------------------------------------------------------------------------
    unsigned long ReadFlash32(unsigned long ulAddr);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Write the flash which the width is 16bit
    //-------------------------------------------------------------------------------------------------------
    bool WriteFlash16(unsigned long ulAddr, unsigned long ulValue);

    //-------------------------------------------------------------------------------------------------------
    //Description:
    //    Read the flash which the width is 16bit
    //-------------------------------------------------------------------------------------------------------
    unsigned short ReadFlash16(unsigned long ulAddr);

private:
    unsigned long m_ulAddressBase;
    Flash::FlashInfo m_FlashInfo;
};


//////////////////////////////////////////////////////////////////////
// FlashAmd.cpp
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "FlashAmd.h"

//------------------------------------------------------------------------------------------------------
//Macro define


// AMD Specifics
#define LATCH_OFFSET1            (0x555 * (GetFlashInfo().Width / 8))
#define LATCH_OFFSET2            (0x2AA * (GetFlashInfo().Width / 8))
#define LATCH_UNLOCKBYPASS        (0xBA * (GetFlashInfo().Width / 8))
#define AMD_UNLOCK1                0x00AA00AA
#define AMD_UNLOCK2                0x00550055

#define AMD_AUTOSELECT32        0x00900090
#define AMD_RESET32             0x00F000F0
#define AMD_ERASESET            0x00800080
#define AMD_ERASESECTOR         0x00300030
#define AMD_SUSPENDERASE        0x00B000B0
#define AMD_RESUMEERASE         0x00300030
#define AMD_PROGRAM             0x00A000A0
#define AMD_PROGRAMBUFFER       0x00250025
#define AMD_UNLOCKBYPASS        0x00200020
#define AMD_UNLOCKBYPASSPROGRAM 0x00A000A0
#define AMD_UNLOCKBYPASSRESET1  0x00900090
#define AMD_UNLOCKBYPASSRESET2  0x00000000
#define AMD_CHIPERASE           0x00100010
#define AMD_COMMITBUFFER        0x00290029


// defines for GetFlashStatus() function
#define STATUS_READY            0x00000000
#define STATUS_ERASESUSPEND     0x00040004 // DQ2
#define STATUS_TIMEOUTVALUE     0x00200020 // DQ5
#define STATUS_TOGGLEVALUE      0x00400040 // DQ6 - toggle bit one


//Flash status
enum FlashStatus
{
    STATUSREADY         = 100,
    STATUSERASESUSPEND  = 101,
    STATUSTIMEOUT       = 102,
    STATUSBUSY          = 103,
    STATUSERROR         = 104
};

    // Flash Commands
enum FlashCommand
{
    CMDRESET               = 0x1000,
    CMDUNLOCK              = 0x1001,
    CMDAUTOSELECT          = 0x1002,
    CMDERASESET            = 0x1003,
    CMDERASESECTOR         = 0x1004,
    CMDSUSPENDERASE        = 0x1005,
    CMDRESUMEERASE         = 0x1006,
    CMDPROGRAM             = 0x1007,
    CMDUNLOCKBYPASSSET     = 0x1008,
    CMDUNLOCKBYPASSRESET   = 0x1009,
    CMDCHIPERASE           = 0x1010,
    CMDREADIDCODES         = 0x1011,
    CMDCLEARSTATUS         = 0x1012,
    CMDREADSTATUS          = 0x1013,
    CMDWRITEWORD           = 0x1014,
    CMDWRITEBUFFER         = 0x1015,
    CMDCOMMITBUFFER        = 0x1016
};
//------------------------------------------------------------------------------------------------------

CFlashAmd::CFlashAmd(void):
m_ulAddressBase(0)
{
}

CFlashAmd::~CFlashAmd(void)
{
}

bool CFlashAmd::EraseFlash(unsigned long ulAddressOffset,unsigned long ulSize,bool bCompletion )
{
    unsigned long ulBeginAddr = GetFlashAddressBase() + ulAddressOffset;
    if(ulBeginAddr + ulSize - 1 > GetFlashAddressBase() + GetFlashInfo().Size)
    {
        return false;
    }

    unsigned long ulEndAddr = ulBeginAddr + ulSize - 1;
    unsigned long ulCurAddr = ulBeginAddr;
    
    //
    // erase the sectors in this range
    //
 
    for (int i = 0; i < GetFlashInfo().Bank; i ++)
    {
        IssueFlashCommand(CMDRESET, i, 0);
    }


    int iBank = 0;
    unsigned long ulSector = 0;
    do{
        GetBankAndSectorIndex(ulCurAddr, iBank, ulSector);

        EraseSectorWithCompletion(iBank, ulSector, bCompletion);

        ulCurAddr += GetSectorSize(ulSector);

    }
    while (ulCurAddr < ulEndAddr);


    
    // Verify Erase
    for (unsigned i = 0;i < ulSize; i += 4)
    {
        unsigned long ulTemp = ReadFlash32(ulBeginAddr + i);
        if (0xFFFFFFFF != ulTemp)
        {            
            return false;
        }
    }
    
   
    return true;

}

void CFlashAmd::LockFlash(unsigned long ulAddressOffset,unsigned long ulSize)
{
    return ;
}

void CFlashAmd::UnlockFlash(unsigned long ulAddressOffset,unsigned long ulSize)
{
    return ;
}

bool CFlashAmd::ReadFlash(unsigned long ulAddressOffset,void *pDataStore,unsigned long ulSize)
{
    unsigned long ulAddrRead = ulAddressOffset + GetFlashAddressBase();;

    int iBank = GetBankIndex(ulAddrRead);    
    IssueFlashCommand(CMDRESET, iBank, 0);
    
    while (ulSize --)
    {
        (reinterpret_cast<unsigned char *> (pDataStore))[ulSize] = *(reinterpret_cast<unsigned char *>(ulAddrRead + ulSize));
    }

    return true;
}

bool CFlashAmd::WaitForEraseComplete(unsigned long ulAddressOffset)
{
    unsigned long ulAddr = GetFlashAddressBase() + ulAddressOffset;

    return (GetFlashStatus(ulAddr) != 0 );
}


bool CFlashAmd::WriteFlash(unsigned long ulAddressOffset,const void * pDataWrite,unsigned long ulSize,bool bErase)
{
    unsigned long ulAddr = ulAddressOffset + GetFlashAddressBase();

    bool bResult = true;

    // Check parameters...
    if (ulAddressOffset + ulSize - 1 > GetFlashInfo().Size)
    {
        return false;
    }

    
    // Round up to whole word    
    if (ulSize & 0x3)
    {
        ulSize += ulSize % 4;
    }

    int iBank = GetBankIndex(ulAddr);
    IssueFlashCommand(CMDRESET, iBank, 0);

    
    // Firstly check that is is erased
    if (!bErase)
    {
        for (unsigned long i = 0; i < ulSize; i ++)
        {
            if (0xff != *(reinterpret_cast<unsigned char *>(ulAddr + i)))
            {            
                bResult = FALSE;

                goto EXIT;            
            }
        }
    }

    if (bErase)
    {
        // Erase the area before write

        EraseFlash(ulAddressOffset,ulSize,true);  
    }

    

    
    // Get to next buffer boundary
    const unsigned long * pulData = reinterpret_cast<const unsigned long *>(pDataWrite);
    while (ulSize && (ulAddr & (GetFlashInfo().WriteBufferSize - 1)) && bResult)
    {

        bResult = WriteFlash32(ulAddr, *pulData);

        ulSize -= 4;
        ulAddr += 4;
        pulData ++;
    }

    IssueFlashCommand(CMDRESET, iBank, 0);

    // Round Size up to multiple of 4 bytes
    ulSize = (ulSize+3) & ~0x3;

    while (ulSize && bResult)
    {
        unsigned long ulCopySize;


        // GetFlashInfo().WriteBufferSize specifies the number of bytes of write buffer
        ulCopySize = min(ulSize, GetFlashInfo().WriteBufferSize);

        bResult = WriteFlashBuffer(ulAddr, pulData, ulCopySize);

        //Sleep(5);//norains.Maybe don't finish writing.

        ulSize -= ulCopySize;
        ulAddr += ulCopySize;
        pulData = &pulData[ulCopySize / 4];
    }


EXIT:
    
    return bResult;
}

unsigned long CFlashAmd::GetBankBaseAddress(int iBank)
{
    return  GetFlashAddressBase() + ( ( GetFlashInfo().Size / GetFlashInfo().Bank) * iBank);

}



int CFlashAmd::GetBankIndex(unsigned long ulAddr)
{
    int iBank;

    for(iBank = GetFlashInfo().Bank - 1; iBank >= 0; iBank--)
    {
        if(ulAddr >= GetBankBaseAddress(iBank))
        {
            break;
        }
    }

    return iBank;
}


void CFlashAmd::IssueFlashCommand(unsigned long ulCommand, unsigned long ulParam1, unsigned long ulParam2)
{
    unsigned long ulAddr; // will hold address of the flash


    switch (ulCommand)
    {
        case CMDRESET:
            ulAddr = GetBankBaseAddress(ulParam1);
            WriteFlash(ulAddr, AMD_RESET32);  // Set the Device to Read Mode
            break;

        case CMDUNLOCK:
            ulAddr = GetBankBaseAddress(ulParam1);
            WriteFlash(ulAddr + LATCH_OFFSET1, AMD_UNLOCK1);
            WriteFlash(ulAddr + LATCH_OFFSET2, AMD_UNLOCK2);
            break;
            
        case CMDERASESET:
            ulAddr = GetBankBaseAddress(ulParam1);
            WriteFlash(ulAddr + LATCH_OFFSET1, AMD_ERASESET);
            break;
        
        case CMDERASESECTOR:
            ulAddr = GetSectorAddress(ulParam1,ulParam2);
            WriteFlash(ulAddr, AMD_ERASESECTOR); // issue erase sector command
            break;
        
        case CMDPROGRAM:
            ulAddr = GetBankBaseAddress(ulParam1);
            WriteFlash(ulAddr + LATCH_OFFSET1, AMD_PROGRAM);
            break;

        case CMDWRITEBUFFER:                
            WriteFlash(ulParam1, AMD_PROGRAMBUFFER);
            WriteFlash(ulParam1, ulParam2);      // word count - 1
            break;
                
        case CMDCOMMITBUFFER:
            WriteFlash(ulParam1, AMD_COMMITBUFFER);
            break;

        default:
            break;
     }
}



unsigned long CFlashAmd::GetSectorAddress(int iBank, unsigned long ulSector)
{
    unsigned long ulSectorAddr;

    ulSectorAddr = GetBankBaseAddress(iBank);

    for (unsigned long i=0; i < ulSector; i ++)
    {
        ulSectorAddr += GetSectorSize(ulSector);
    }

    return ulSectorAddr;
}



unsigned long CFlashAmd::GetSectorSize(unsigned long ulSector)
{
    unsigned long ulSectorSize;

    if (ulSector < GetFlashInfo().BootSectorCount)
    {
        ulSectorSize = GetFlashInfo().BootSectorSize;
    }
    else
    {
        ulSectorSize = GetFlashInfo().SectorSize;
    }

    return ulSectorSize * (GetFlashInfo().Width / 16);
}



void CFlashAmd::GetBankAndSectorIndex(unsigned long ulAddress, int & iBank, unsigned long & ulSector)
{    
    //Reset
    iBank = 0;
    ulSector = 0;
    
    // Find the Bank number first
    for (iBank = GetFlashInfo().Bank - 1; iBank >= 0; iBank --)
    {
        if (ulAddress >= GetBankBaseAddress(iBank))
        {
            break;
        }
    }

    // Now work out the sector number
    while (ulAddress >= GetSectorAddress(iBank,ulSector))
    {
        ulSector ++;
    }
    ulSector --;


}



bool CFlashAmd::EraseSectorWithCompletion(int iBank, unsigned long ulSector, bool bCompletion)
{
    unsigned long ulAddr = GetSectorAddress(iBank, ulSector);
    EraseSector(iBank, ulSector);

    unsigned long ulStatus;    

    if (bCompletion)
    {   
        
        // wait until flash state machine is ready for other operation        
        ulStatus = GetFlashStatus(ulAddr);
    }
    else
    {
        ulStatus = STATUSREADY;
    }

    return (ulStatus == STATUSREADY);
}



bool CFlashAmd::EraseSector(int iBank, unsigned long ulSector)
{
    IssueFlashCommand(CMDUNLOCK, iBank, 0); // issue unlock command // no data to write
    IssueFlashCommand(CMDERASESET, iBank, 0); //  // erase setup command
    IssueFlashCommand(CMDUNLOCK, iBank, 0);
    IssueFlashCommand(CMDERASESECTOR, iBank, ulSector); // issue erase sector command

    return true;
}

unsigned long CFlashAmd::GetFlashStatus(unsigned long ulAddress)
{
    unsigned long ulStatus;

    int iBank = GetBankIndex(ulAddress);
   
    // Two consecutive reads to check if bits are toggling
    unsigned long ulOldRead = ReadFlash(ulAddress);
    unsigned long ulNewRead = ReadFlash(ulAddress);   

    //The timeout value
    unsigned long ulStatusTimeoutValue = STATUS_TIMEOUTVALUE;
    if(GetFlashInfo().Width == 16)
    {
        ulStatusTimeoutValue &= 0xFFFF;
    }

    do {    
        // XOR to see if bits toggled

        ulStatus = ulOldRead ^ ulNewRead;
        if (0 == (ulStatus & STATUS_TOGGLEVALUE))
        {
            ulStatus = STATUSREADY;
            break;
        }


        if ((ulNewRead & ulStatusTimeoutValue) == ulStatusTimeoutValue)
        {

            ulNewRead = ReadFlash(ulAddress);
            ulOldRead = ReadFlash(ulAddress);

            ulStatus = ulOldRead ^ ulNewRead;

            if (0 == (ulStatus & STATUS_TOGGLEVALUE))
            {
                ulStatus = STATUSREADY;
                break;
            }    

              
            ulStatus = STATUSTIMEOUT;

            IssueFlashCommand(CMDRESET,iBank,0);

            break;
        }

        ulOldRead = ulNewRead;
        ulNewRead = ReadFlash(ulAddress);


    } while(true);

    return ulStatus;
}



bool CFlashAmd::WriteFlashBuffer(unsigned long ulAddress,const void * pSrcData, unsigned long ulByteCount)
{
    if ((ulByteCount & 3) || (0 == ulByteCount))
    {
        //Flash Write buffer requires a whole multiple of words
        return false;
    }
    
    //
    // issue Program Command
    // The Write buffer is GetFlashInfo().width entries deep
    // With 2 chips it is 32 bits wide
    unsigned long ulSize = (ulByteCount / (GetFlashInfo().Width / 8));
   
    int iBank = GetBankIndex(ulAddress);
    IssueFlashCommand(CMDUNLOCK, iBank, 0);    
    IssueFlashCommand(CMDWRITEBUFFER, ulAddress, ulSize - 1 |((ulSize - 1) << 16));
    
    while (ulSize--)
    {
        if(GetFlashInfo().Width == 16)
        {
            WriteFlash(ulAddress, *(reinterpret_cast<const unsigned short *>(pSrcData)));
        }
        else if(GetFlashInfo().Width == 32)
        {
            WriteFlash(ulAddress, *(reinterpret_cast<const unsigned long *>(pSrcData)));
        }

        ulAddress = ulAddress + (GetFlashInfo().Width / 8);

        if(GetFlashInfo().Width == 16)
        {
            pSrcData = reinterpret_cast<const void *>(reinterpret_cast<const unsigned short *>(pSrcData) + 1);
        }
        else if(GetFlashInfo().Width == 32)
        {
            pSrcData = reinterpret_cast<const void *>(reinterpret_cast<const unsigned long *>(pSrcData) + 1 );
        }
    
    }

    ulAddress = ulAddress - (GetFlashInfo().Width / 8);

    IssueFlashCommand(CMDCOMMITBUFFER, ulAddress, 0);
                   
 
    // wait until flash is ready to accept new command
    unsigned long ulStatus = GetFlashStatus(ulAddress);
       

    return (ulStatus != STATUSTIMEOUT);
}



bool CFlashAmd::SetFlashAddressBase(unsigned long ulAddress)
{
    m_ulAddressBase = ulAddress;
    return true;
}

unsigned long CFlashAmd::GetFlashAddressBase(void)
{
    return m_ulAddressBase;
}

bool CFlashAmd::SetFlashInfo(const Flash::FlashInfo & flashInfo)
{
    m_FlashInfo = flashInfo;

    return true;
}

const  Flash::FlashInfo & CFlashAmd::GetFlashInfo(void)
{
    return m_FlashInfo;
}




bool CFlashAmd::WriteFlash32(unsigned long ulAddr, unsigned long ulValue)
{
                                             
    *(volatile unsigned long * const)(ulAddr) = (ulValue);
    __asm("sync");                                    

    return (*(volatile unsigned long * const)(ulAddr) == (ulValue));
}


unsigned long CFlashAmd::ReadFlash32(unsigned long ulAddr)
{
    return *(volatile unsigned long * const)(ulAddr);
}



bool CFlashAmd::WriteFlash16(unsigned long ulAddr, unsigned long ulValue)
{
                                               
    *(volatile unsigned short * const)(ulAddr) = static_cast<unsigned short>( (ulValue) & 0xFFFF);
    __asm("sync");                                    

    return (*(volatile unsigned short * const)(ulAddr) == static_cast<unsigned short>( (ulValue) & 0xFFFF));
}


unsigned short CFlashAmd::ReadFlash16(unsigned long ulAddr)
{
    return *(volatile unsigned short * const)(ulAddr);
}


bool CFlashAmd::WriteFlash(unsigned long ulAddr, unsigned long ulValue)
{
    switch(m_FlashInfo.Width)
    {
        case 16:
            WriteFlash16(ulAddr,ulValue);
            break;
        case 32:
            WriteFlash32(ulAddr,ulValue);
            break;
        default:
            return false;
    }

    return true;
}

unsigned long CFlashAmd::ReadFlash(unsigned long ulAddr)
{
    switch(m_FlashInfo.Width)
    {
        case 16:
            return ReadFlash16(ulAddr);
            break;
        case 32:
            return ReadFlash32(ulAddr);    ;
        default:
            return 0;
    }
    
}


    CFlashAmd主要限制于DBAU1200的开发板,并且该板子上的FLASH型号为AM29LV256M。
    
    如果条件具备,那么让我们看看如何烧写flash吧。
    
  CFlashAmd flashAmd;
  //设置flash型号
    flashAmd.SetFlashInfo(Flash::FLASH_INFO_AM29LV256M);
    //设置flash的起始地址。在开发板中,FLASH的起始地址为0xBC000000。
    flashAmd.SetFlashAddressBase(0xBC000000);
    
    ...
    
    //烧写FLASH。在这里注意的是,地址为偏移地址。该偏移地址是相对于之前通过SetFlashAddressBase所设置的地址。
    flashAmd.WriteFlash(dwOffsetAddr,&vtStore[0],vtStore.size(),true);

你可能感兴趣的:(command,Flash,buffer,byte,WinCE,parallel)