📄 flash.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 + -