📄 flash.c
字号:
return(PASS);
}
int32 CFI_Read_Block (unsigned16 *address, unsigned16 *data, unsigned32 size)
{
unsigned32 i = 0;
// Size if passed in, in bytes, but must be an integral number of longwords.
size /= sizeof(unsigned16);
/* Read the block as standard memory */
for ( ; i < size; i++)
{
*data++ = *address++;
}
return(PASS);
}
int32 CFI_Erase_Block (unsigned16 *address)
{
volatile unsigned16 *vflash = (volatile unsigned16*)address;
int32 retry = 10, iRet;
CFI_Lock_Bit_Clear( address );
do
{
retry--;
iRet = PASS;
/* Issue single block erase command */
*vflash = BLOCK_ERASE;
/* Confirm Action 0xd0 with block address */
*vflash = PROGRAM_VERIFY;
if (CFI_Check_Status(vflash)==-1) iRet = FAIL;
/* Reset for Read operation */
*vflash = READ_ARRAY;
} while( (0 < retry) && (FAIL == iRet) );
CFI_Lock_Bit_Set( address );
return(iRet);
}
///////////////////////////////////////////////////////////////////
// Bootloader Flash Routines.
//
DWORD ConvertNKAddr(DWORD dwAddr)
{
// RAM address and forced flash download?
if( dwAddr < PHYS_FLASH_BASE && g_BldrSettings.nFlags & BLDR_SETTINGS_FLAGS_FSHDLOAD)
{
// Convert a physical NK RAM image address to a physical Flash address
return dwAddr + (NK_FLASH_BASE - NK_RAM_BASE);
}
else
{
// Probably already a Flash address, or we aren't forcing a download
return dwAddr;
}
}
BOOL OEMIsFlashAddr(DWORD dwAddr)
{
dwAddr = ConvertNKAddr(dwAddr);
// The last few blocks are reserved for eboot settings and the SIB.
// Don't download and write to these blocks (or anything higher than
// the lowest of these two sections).
if (dwAddr >= BLDR_FLASH_BASE && dwAddr <= RESERVED_FLASH_BASE )
return(TRUE);
return(FALSE);
}
LPBYTE OEMMapMemAddr (DWORD dwImageStart, DWORD dwAddr)
{
if (OEMIsFlashAddr(dwAddr))
{
//
// This image is destined for flash, cache it in RAM temporarily.
//
dwAddr -= dwImageStart;
dwAddr += FCACHE;
}
return((LPBYTE) dwAddr);
}
BOOL OEMWriteFlash(DWORD dwImageStart, DWORD dwImageLength)
{
DWORD dwFlashAddr, dwExtraBytes = 0;
LPBYTE pbCache = NULL;
UCHAR nNumBlocks = 0;
BOOL bRet = TRUE;
if( dwImageStart != ConvertNKAddr(dwImageStart) )
{
// We are forcing a flash download, so set the jump address
dwImageStart = ConvertNKAddr(dwImageStart);
g_BldrSettings.nJumpAddr = dwImageStart + 0x1000;
}
//
// Make sure the start and end addresses are in flash.
//
if (!OEMIsFlashAddr(dwImageStart) || !OEMIsFlashAddr(dwImageStart + dwImageLength - 1))
{
EdbgOutputDebugString("ERROR: OEMWriteFlash - not a flash address (0x%x or 0x%x).\r\n",
dwImageStart, (dwImageStart + dwImageLength - 1));
return(FALSE);
}
//
// Make sure image start is on a block boundary.
//
if (dwImageStart % ARMVPB_FLASH_BLOCK_SIZE)
{
EdbgOutputDebugString("ERROR: OEMWriteFlash - image start address isn't on a flash block boundary (0x%x).\r\n",
dwImageStart);
return(FALSE);
}
EdbgOutputDebugString ("INFO: Writing to FLASH: Start = 0x%X Length = 0x%X...\r\n",
dwImageStart, dwImageLength);
nNumBlocks = (UCHAR)(dwImageLength / ARMVPB_FLASH_BLOCK_SIZE);
dwExtraBytes = (dwImageLength % ARMVPB_FLASH_BLOCK_SIZE);
dwFlashAddr = dwImageStart;
pbCache = OEMMapMemAddr (dwImageStart, dwFlashAddr);
// apCHARLCD_PrintXY(0, 0, "Flash Writing" );
//
// Write flash blocks...
//
while(nNumBlocks && bRet)
{
EdbgOutputDebugString("Writing to Block %d, (%d of %d):\r\n",
BLOCK_NUM(dwFlashAddr),
BLOCK_NUM(dwFlashAddr) - BLOCK_NUM(dwImageStart) + 1,
gnBlocks);
if (CFI_Write_Block((unsigned16*)dwFlashAddr,
(unsigned16*)pbCache, ARMVPB_FLASH_BLOCK_SIZE) != PASS)
{
EdbgOutputDebugString("ERROR: OEMWriteFlash - unable to write to block (block address=0x%x).\r\n",
dwFlashAddr);
bRet = FALSE;
break;
}
dwFlashAddr += ARMVPB_FLASH_BLOCK_SIZE;
pbCache = OEMMapMemAddr (dwImageStart, dwFlashAddr);
--nNumBlocks;
}
//
// If a partial block remains, write it.
//
if (dwExtraBytes && bRet)
{
EdbgOutputDebugString("Writing %d bytes of last Block %d:\r\n",
dwExtraBytes, BLOCK_NUM(dwFlashAddr));
if (CFI_Write_Block((unsigned16*)dwFlashAddr, (unsigned16*)pbCache,
dwExtraBytes) != PASS)
{
EdbgOutputDebugString("ERROR: OEMWriteFlash - unable to write to block (block address=0x%x).\r\n",
dwFlashAddr);
bRet = FALSE;
}
}
// apCHARLCD_PrintXY(0, 0, " " );
return(bRet);
}
//
// This function is called periodically during download to allow us to
// continue the block erasure sequence...
//
void OEMContinueEraseFlash(void)
{
UCHAR nEraseCount = BLOCK_ERASE_STEP; // Number of blocks to erase...
//
// Have we finished erasing all the blocks?
//
if (!gnBlocks || (gnBlockCount == gnEndBlock))
return;
//
// Erase a few blocks...
//
while ((gnBlockCount < gnEndBlock) && nEraseCount)
{
if (CFI_Erase_Block((unsigned16*)BLOCK_ADDR(gnBlockCount)) != PASS)
{
EdbgOutputDebugString("ERROR: OEMContinueEraseFlash - flash erase error (block number %d).\r\n",
gnBlockCount);
return;
}
++gnBlockCount;
--nEraseCount;
}
return;
}
BOOL OEMFinishEraseFlash(void)
{
EdbgOutputDebugString("INFO: Finishing flash erase...");
while(gnBlocks && (gnBlockCount != gnEndBlock))
{
OEMContinueEraseFlash();
}
EdbgOutputDebugString("last block %d\r\n",gnBlockCount-1);
return(TRUE);
}
BOOL OEMStartEraseFlash (DWORD dwStartAddr, DWORD dwLength)
{
//
// Make sure the start and end addresses are in flash.
//
if (!OEMIsFlashAddr(dwStartAddr) || !OEMIsFlashAddr(dwStartAddr + dwLength - 1))
{
EdbgOutputDebugString("ERROR: OEMStartEraseFlash - not a flash address (0x%x or 0x%x).\r\n",
dwStartAddr, (dwStartAddr + dwLength - 1));
return(FALSE);
}
dwStartAddr = ConvertNKAddr(dwStartAddr);
//
// Make sure start address is block-aligned.
//
if (dwStartAddr % ARMVPB_FLASH_BLOCK_SIZE)
{
EdbgOutputDebugString("ERROR: OEMStartEraseFlash - start address isn't block aligned (0x%x).\r\n",
dwStartAddr);
return(FALSE);
}
if (dwLength & 0x03)
{
EdbgOutputDebugString("ERROR: OEMStartEraseFlash - length isn't an integral number of longwords (0x%x).\r\n",
dwLength);
return(FALSE);
}
//
// Determine affected flash blocks.
//
gnStartBlock = BLOCK_NUM(dwStartAddr);
gnEndBlock = BLOCK_NUM(dwStartAddr + dwLength + (ARMVPB_FLASH_BLOCK_SIZE - 1));
gnBlocks = (int)(gnEndBlock - gnStartBlock);
gnBlockCount = gnStartBlock;
EdbgOutputDebugString("Erasing flash blocks: start block = %d end block = %d\r\n",
gnStartBlock, gnEndBlock-1);
return(TRUE);
}
//
///////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -