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 + -
显示快捷键?