ethdown.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 914 行 · 第 1/3 页
C
914 行
dwCurDataWord |= pbData[i] << ((i+bNumBytesInDataTail) * 8);
dwCurDataWord |= dwDataTailFromLastPacket;
// DWORD align the buffer
*cwLength -= 4 - bNumBytesInDataTail;
pdwBuffer = (DWORD UNALIGNED *) (pbData + (4-bNumBytesInDataTail)); //memmove( pbData, pbData + (4-bNumBytesInDataTail), *cwLength );
iBufferPos = -4;
}
else
dwCurDataWord = *pdwBuffer++;
// I'll keep looping until I get almost to the end of the packet buffer
while( iBufferPos + 4 <= *cwLength ) {
switch( BINFileParseState ) {
case BIN_PHYSADDR:
dwRecordAddr= dwCurDataWord;
if (fWriteToFlash) {
// Offset the start address so that flash data is written to the FlashCache[]
dwCurDataWord = (dwCurDataWord & 0x0FFFFFFFUL) - (dwPhysStart & 0x0FFFFFFFUL);
pdwDest = (LPDWORD)(FLASH_CACHE + dwCurDataWord);
pbCRC = (BYTE *)(FLASH_CACHE + dwCurDataWord);
#if ((SH_PLATFORM != PLATFORM_ASPEN)&&(SH_PLATFORM != PLATFORM_BIGSUR))
if (FlashErase( FLASH_CONT_ERASE, 0, 0, ppszErrorMsg ))
return 1;
#endif ((SH_PLATFORM != PLATFORM_ASPEN)&&(SH_PLATFORM != PLATFORM_BIGSUR))
}
else {
pdwDest = (DWORD UNALIGNED *)dwCurDataWord;
pbCRC = (BYTE *)dwCurDataWord;
}
BINFileParseState = BIN_PHYSLEN;
break;
case BIN_PHYSLEN:
dwRecordLen = dwCurDataWord;
BINFileParseState = BIN_CHECKSUM;
break;
case BIN_CHECKSUM:
if (pdwDest == 0 && dwCurDataWord == 0) {
dwLaunchAddr = dwRecordLen;
EdbgOutputDebugString( "End of image. Launch address=%Xh\r\n",dwLaunchAddr);
}
dwPerfectCRC = dwCurDataWord;
dwRecordPos = 0;
BINFileParseState = BIN_DATA;
*pdwRecNext++=dwRecordAddr;
*pdwRecNext++=dwRecordLen;
*pdwRecNext++=dwPerfectCRC;
// EdbgOutputDebugString("Addr %X Len %X checksum %X\r\n",dwRecordAddr,dwRecordLen,dwPerfectCRC);
break;
case BIN_DATA:
// If we aren't at the end of the record yet read another DWORD. Note that the number of
// bytes in a record is guaranteed to always be DWORD aligned, so we can assume that there
// won't be a partial DWORD at the end of a record.
*pdwDest++ = dwCurDataWord;
dwRecordPos += 4;
if (dwRecordPos < dwRecordLen)
BINFileParseState = BIN_DATA;
// If we have reached the end of the record
else {
if (dwRecordLen == sizeof(ROMHDR) && dwROMHDRAddr < dwRecordAddr) {
EdbgOutputDebugString("Found ROMHDR at Address %Xh\r\n",dwRecordAddr);
memcpy((LPVOID)&RomHdr,pbCRC,sizeof(ROMHDR));
dwROMHDRAddr=dwRecordAddr;
}
#if 1
// Check the CRC
dwPartialCRC = 0;
for( i = 0; i < dwRecordLen; i++ )
dwPartialCRC += *pbCRC++;
if (dwPartialCRC != dwPerfectCRC) {
EdbgOutputDebugString( "EthDown::TFTPD_WRITE::CRC Error - Calculated 0x%X Perfect 0x%X\r\n",
dwPartialCRC, dwPerfectCRC );
*ppszErrorMsg = "CRC Error";
return 1;
}
#endif
BINFileParseState = BIN_PHYSADDR;
}
break;
} // switch(BINFileParseState)
dwCurDataWord = *pdwBuffer++;
iBufferPos += 4;
} // while not at end of buffer
// Store the fragmented DWORD until we get the next packet
bNumBytesInDataTail = (BYTE)(*cwLength - iBufferPos);
dwDataTailFromLastPacket = dwCurDataWord;
// Mask off the garbage that was picked up from the end of the packet buffer
switch( bNumBytesInDataTail ) {
case 1:
dwDataTailFromLastPacket &= 0x000000FFUL;
break;
case 2:
dwDataTailFromLastPacket &= 0x0000FFFFUL;
break;
case 3:
dwDataTailFromLastPacket &= 0x00FFFFFFUL;
break;
}
break;
case TFTPD_DESTROY:
EdbgOutputDebugString( "EthDown::TFTPD_DESTROY::%s with %u bytes\r\n", pszFileName, *cwLength );
for( i = 0; i < *cwLength; i++ ) {
if (i > 0 && i % 8 == 0)
EdbgOutputDebugString( " " );
if (i > 0 && i % 16 == 0)
EdbgOutputDebugString( "\r\n" );
EdbgOutputDebugString( "%B ", pbData[i] );
}
break;
default:
EdbgOutputDebugString( "EthDown::Illegal Operation Code %u\r\n", Operation );
return 1;
break;
} // switch
return 0;
}
UINT16 IsFlash( DWORD dwPhysStart, DWORD dwPhysLen )
{
DWORD dwPhysEnd;
int retval;
EdbgOutputDebugString("IsFlash: dwPhysStart = 0x%x, dwPhysLen = 0x%x\nFLASH_ADDR_START = 0x%x, FLASH_ADDR_END = 0x%x", dwPhysStart, dwPhysLen, FLASH_ADDR_START, FLASH_ADDR_END);
dwPhysEnd = dwPhysStart + dwPhysLen;
if ((dwPhysStart & 0x0FFFFFFFUL) < (FLASH_ADDR_START & 0x0FFFFFFFUL) ||
(dwPhysEnd & 0x0FFFFFFFUL) >= (FLASH_ADDR_END & 0x0FFFFFFFUL))
retval = 0;
else
retval = 1;
EdbgOutputDebugString(" returning %d\n", retval);
return retval;
}
#if ((SH_PLATFORM != PLATFORM_ASPEN)&& (SH_PLATFORM != PLATFORM_BIGSUR))
// This routine is called repeatedly to erase all the blocks needed. When FlashErase() routine is called with
// the FLASH_START_ERASE parameter, all the blocks are marked DIRTY. Then all the ones that will be used
// are given commands to erase and are marked PENDING. On successive calls to FlashErase(), the routine
// will continue issuing erase commands if all the erase commands couldn't be issued before. Also, it
// will check on the progress of the PENDING blocks. If one of them finishes it will be marked ERASED. If
// and error occurs during erasure, the routine will return non-zero with an error message. Otherwise, the
// routine will return 0.UINT16 FlashErase(FlashCommands FlashCommand, DWORD dwPhysStart, DWORD dwPhysLen, char **ppszErrorMsg ) {
UINT16 FlashErase(FlashCommands FlashCommand, DWORD dwPhysStart, DWORD dwPhysLen, char **ppszErrorMsg )
{
DWORD dwPhysEnd;
static DWORD dwStartBlock, dwEndBlock;
volatile DWORD *pdwBSR, *pdwGSR;
DWORD i;
if(CheckFlashWriteProtect()) {
*ppszErrorMsg = "Error : write protected.";
return 1;
}
// If this is the first call, initialize all these variables for the next time
switch( FlashCommand ) {
case FLASH_START_ERASE:
dwPhysEnd = dwPhysStart + dwPhysLen;
// compute starting block number and number of blocks
dwStartBlock = (dwPhysStart & 0x01FE0000UL) / FLASH_BLOCK_SIZE;
dwEndBlock = (dwPhysEnd & 0x01FE0000UL) / FLASH_BLOCK_SIZE;
EdbgOutputDebugString( "dwStartBlock=%d dwEndBlock=%d FlashErase=%Xh\r\n",dwStartBlock,dwEndBlock,FlashErase);
// protect BLOCK 0 (ethernet bootloader block)
for( i = dwStartBlock; i <= dwEndBlock; i++ ) {
if(i == 0) {
*ppszErrorMsg = "Error : Block 0 is the bootloader block. Check the image start address.";
return 1;
}
}
// Make sure that SH3 writing to the flash is enabled
// *pwCpuCsr&= ~AUX_POWER_ENABLE;
// *pwCpuCsr = (*pwCpuCsr & 0xFFFD) | 0x0100;
for( i = 0; i < TOTAL_FLASH_BLOCKS; i++ )
EraseStatus[i] = BLOCK_DIRTY;
// I have to "initialize" all the chips by downloading the device info
// If I don't do this, then I can't read the BSR registers
if ( dwStartBlock < FLASH_BLOCKS_PER_BANK )
UploadDeviceInfo( 0 );
if ( dwEndBlock >= FLASH_BLOCKS_PER_BANK )
UploadDeviceInfo( 1 );
case FLASH_CONT_ERASE:
// Now fill the command queue with erase block commands
pdwGSR= (DWORD *)((FLASH_START | 0xA0000000UL) + dwStartBlock * FLASH_BLOCK_SIZE + 16);
pdwBSR= (DWORD *)((FLASH_START | 0xA0000000UL) + dwStartBlock * FLASH_BLOCK_SIZE + 8);
// FlashWriteCommand(pdwGSR, 0x50505050UL);
// FlashWriteCommand(pdwBSR, 0x71717171UL);
// EdbgOutputDebugString( "pdwBSR =%Xh value=%Xh\r\n",pdwBSR ,*(pdwBSR ));
// EdbgOutputDebugString( "pdwBSR+1=%Xh value=%Xh\r\n",pdwBSR+1,*(pdwBSR+1));
// FlashWriteCommand(pdwGSR, 0x50505050UL);
// FlashWriteCommand(pdwBSR, 0x71717171UL);
// EdbgOutputDebugString( "pdwGSR =%Xh value=%Xh\r\n",pdwGSR ,*(pdwGSR ));
// EdbgOutputDebugString( "pdwGSR+1=%Xh value=%Xh\r\n",pdwGSR+1,*(pdwGSR+1));
for( i = dwStartBlock; i <= dwEndBlock; i++ ) {
// If we're at a bank boundary, reset the status flags
if (i == dwStartBlock || i % FLASH_BLOCKS_PER_BANK == 0) {
FlashWriteCommand(pdwGSR, 0x50505050UL);
}
// Initialize reading of ESRs
FlashWriteCommand(pdwBSR, 0x71717171UL);
switch (EraseStatus[i]) {
case BLOCK_DIRTY:
// If the block is busy, come back to it later
if (!FlashBSR1(pdwBSR,0x00800080UL))
break;
// If either of the command queues is full, try the next block
if (!FlashBSR0(pdwBSR,0x00080008UL))
break;
// EdbgOutputDebugString( "Erasing address=%Xh\r\n",pdwBSR);
// Tell it to erase the next block
FlashWriteCommand(pdwBSR, 0x20202020UL);
FlashWriteCommand(pdwBSR, 0xD0D0D0D0UL);
// Check for errors
FlashWriteCommand(pdwBSR, 0x71717171UL);
if (!FlashGSR0(pdwGSR,0x00200020UL)) {
if (FlashError( pdwBSR, ppszErrorMsg ))
return 1;
else
break;
}
EraseStatus[i] = BLOCK_PENDING;
break;
case BLOCK_PENDING:
// Wait until the block is no longer busy (being erased).
if (!FlashBSR1(pdwBSR, 0x00800080UL))
break;
// Check for operation errors
if (!FlashBSR0(pdwBSR,0x00200020UL)) {
EdbgOutputDebugString( "FLASH_END_RANGE: Error On Flash Erase Block %u GSR %X, BSR %X\r\n",
i, *pdwGSR, *pdwBSR );
FlashError( pdwBSR, ppszErrorMsg );
// This will make the routine loop back and try to erase the block again.
EraseStatus[i] = BLOCK_DIRTY;
EdbgOutputDebugString( "Error In Attempting To Erase Block %u: %s\r\n", i, *ppszErrorMsg );
break;
}
// EdbgOutputDebugString( " %u", i );
EdbgOutputDebugString( "BLOCK_ERASED:%u\r\n", i );
v_FlashBlock = i;
#if ((SH_PLATFORM != PLATFORM_ASPEN)&&(SH_PLATFORM != PLATFORM_BIGSUR))
DisplayAlphaLED (MAKELONG(v_PacketNum, v_FlashBlock));
#endif ((SH_PLATFORM != PLATFORM_ASPEN)&&(SH_PLATFORM != PLATFORM_BIGSUR))
EraseStatus[i] = BLOCK_ERASED;
break;
} // Switch (EraseStatus)
pdwGSR += FLASH_BLOCK_SIZE / 4;
pdwBSR += FLASH_BLOCK_SIZE / 4;
} // For each block being flashed
break;
} // switch
return 0;
}
// This routine can be called when an error has been detected for a given operation. It will
// give an error message and will return 0 if the command causing the error should be
// re-attempted or it will return non-zero if the error is fatal.
UINT16 FlashError( volatile DWORD *pdwBSR, char **ppszErrorMsg )
{
// Read CSR
FlashWriteCommand(pdwBSR, 0x70707070UL);
if (!FlashBSR0(pdwBSR,0x00100010UL) || !FlashBSR0(pdwBSR,0x00200020UL)) {
// The spec. says that there was an error in the command sequence and
// to attempt it again.
EdbgOutputDebugString( "FLASH_CONT_ERASE Command Sequence Error\r\n");
*ppszErrorMsg = "FLASH_CONT_ERASE Command Sequence Error";
FlashWriteCommand(pdwBSR, 0x50505050UL);
return 0;
}
FlashWriteCommand(pdwBSR, 0x71717171UL);
if (!FlashBSR0(pdwBSR, 0x00040004UL)) {
*ppszErrorMsg = "FLASH_CONT_ERASE Vpp Error Detected";
FlashWriteCommand(pdwBSR, 0x50505050UL);
// Reset flash to normal mode
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?