/******************************************************************************
* Function: static CHAR DecodeHex(BYTE *vHexData, WORD *wHexDataLen, BYTE *vMemoryData, DWORD *dwAddress, BOOL bInitialize)
*
* PreCondition: None
*
* Input: *vHexData: Pointer to Intel HEX formatted data to read
* *wHexDataLen: Pointer to a WORD containing the number of wHexData bytes that are available
* *vMemoryData: Pointer to RAM bytes were binary decoded data will be written. There must be exactly FLASH_WRITE_SIZE bytes available at this address.
* bInitialize: TRUE for very first call, FALSE for all subsequent calls of the same .hex file.
*
* Output: wHexDataLen: WORD containing the number of wHexData bytes that were processed from the *vHexData stream
* vMemoryData: RAM bytes containing binary data decoded from the hex stream
* dwAddress: DWORD containing the base memory address where you should write the vMemoryData array
* CHAR: < 0 on error (checksum error, illegal data in hex file, etc)
* 0 on success and need more data
* > 0 on success and end of file record found
*
* Side Effects: None
*
* Overview: Converts an Intel HEX file stream into a stream of binary
* data to be programming into Flash memory.
*
* Note: None
*****************************************************************************/
static CHAR DecodeHex(BYTE *vHexData, WORD *wHexDataLen, BYTE *vMemoryData, DWORD *dwAddress, BOOL bInitialize)
{
static enum
{
GetColon = 0,
GetRecordLength1,
GetRecordLength0,
GetAddress3,
GetAddress2,
GetAddress1,
GetAddress0,
GetRecordType1,
GetRecordType0,
GetDataBytes1,
GetDataBytes0,
GetChecksum1,
GetChecksum0
} smRecordParser;
static BYTE vRecordByte;
static BYTE vRecordLen;
static WORD_VAL wvVolatileAddress;
static WORD_VAL wvLatchedAddress;
static DWORD_VAL dwvVolatileExtAddress;
static DWORD_VAL dwvLatchedExtAddress;
static DWORD dwTemp;
static BYTE vRecordType;
static BYTE vChecksum;
BYTE vEncodedByte;
BYTE vDecodedByte;
WORD w;
WORD wHexLen;
BOOL bByteWritten;
// Reset state machine if this is a first time
if(bInitialize)
{
wvVolatileAddress.Val = 0;
wvLatchedAddress.Val = 0;
dwvVolatileExtAddress.Val = 0;
dwvLatchedExtAddress.Val = 0;
smRecordParser = GetColon;
return DECODE_SUCCESS_NEED_MORE_HEXDATA;
}
bByteWritten = FALSE;
wHexLen = *wHexDataLen;
*wHexDataLen = 0;
while(wHexLen)
{
wHexLen--;
vEncodedByte = vHexData[*wHexDataLen];
*wHexDataLen += 1;
vDecodedByte = HexToBin(vEncodedByte);
switch(smRecordParser)
{
case GetColon:
// Skip whitespace
if(vEncodedByte == '\r')
break;
if(vEncodedByte == '\n')
break;
if(vEncodedByte == ' ')
break;
// Make sure this character is a colon
if(vEncodedByte != ':')
return DECODE_ERROR_INVALID_FORMAT;
smRecordParser = GetRecordLength1;
break;
case GetRecordLength1:
vRecordLen = vDecodedByte<<4;
smRecordParser = GetRecordLength0;
break;
case GetRecordLength0:
vRecordLen |= vDecodedByte;
vChecksum = vRecordLen;
smRecordParser = GetAddress3;
break;
case GetAddress3:
wvVolatileAddress.Val = 0;
wvVolatileAddress.v[1] = vDecodedByte<<4;
smRecordParser = GetAddress2;
break;
case GetAddress2:
wvVolatileAddress.v[1] |= vDecodedByte;
vChecksum += wvVolatileAddress.v[1];
smRecordParser = GetAddress1;
break;
case GetAddress1:
wvVolatileAddress.v[0] = vDecodedByte<<4;
smRecordParser = GetAddress0;
break;
case GetAddress0:
wvVolatileAddress.v[0] |= vDecodedByte;
vChecksum += wvVolatileAddress.v[0];
smRecordParser = GetRecordType1;
wvLatchedAddress.Val = wvVolatileAddress.Val;
// Make sure we haven't moved out of this flash write page
if(bByteWritten)
{
dwTemp = dwvLatchedExtAddress.Val + wvLatchedAddress.Val;
if((dwTemp >= *dwAddress + FLASH_WRITE_SIZE) || (dwTemp < *dwAddress))
return DECODE_SUCCESS_NEW_ADDRESS;
}
break;
case GetRecordType1:
vRecordType = vDecodedByte<<4;
smRecordParser = GetRecordType0;
break;
case GetRecordType0:
vRecordType |= vDecodedByte;
vChecksum += vRecordType;
if(vRecordType == 0x01u) // End of records marker found
{
smRecordParser = GetChecksum1;
return DECODE_SUCCESS_EOF;
}
else if(vRecordType == 0x02u || vRecordType == 0x04u) // Extended Segment Address Record or Extended Linear Address Record
{
if(vRecordLen != 2u)
return DECODE_ERROR_INVALID_FORMAT;
}
else if(vRecordType != 0x00u) // Unrecognized record type found
{
return DECODE_ERROR_INVALID_FORMAT;
}
smRecordParser = vRecordLen ? GetDataBytes1 : GetChecksum1;
break;
case GetDataBytes1:
vRecordByte = vDecodedByte<<4;
smRecordParser = GetDataBytes0;
break;
case GetDataBytes0:
vRecordLen--;
smRecordParser = GetDataBytes1;
vRecordByte |= vDecodedByte;
vChecksum += vRecordByte;
if(vRecordType == 0x00u)
{
if(!bByteWritten)
{
dwTemp = dwvLatchedExtAddress.Val + wvLatchedAddress.Val;
*dwAddress = dwTemp & ~(FLASH_WRITE_SIZE-1ul);
bByteWritten = TRUE;
}
vMemoryData[wvLatchedAddress.v[0] & (FLASH_WRITE_SIZE-1)] = vRecordByte;
wvLatchedAddress.Val++;
}
else if(vRecordType == 0x02u)
{
// See if this is the high byte or low byte
if(vRecordLen)
{
dwvVolatileExtAddress.v[3] = 0x00;
dwvVolatileExtAddress.v[2] = vRecordByte>>4;
dwvVolatileExtAddress.v[1] = vRecordByte<<4;
}
else
{
dwvVolatileExtAddress.v[1] |= vRecordByte>>4;
dwvVolatileExtAddress.v[0] = vRecordByte<<4;
dwvLatchedExtAddress.Val = dwvVolatileExtAddress.Val;
}
}
else if(vRecordType == 0x04u)
{
// See if this is the high byte or low byte
if(vRecordLen)
{
dwvVolatileExtAddress.v[3] = vRecordByte;
dwvVolatileExtAddress.v[1] = 0x00;
dwvVolatileExtAddress.v[0] = 0x00;
}
else
{
dwvVolatileExtAddress.v[2] = vRecordByte;
dwvLatchedExtAddress.Val = dwvVolatileExtAddress.Val;
}
}
if(vRecordLen == 0u)
smRecordParser = GetChecksum1;
// Make sure we haven't moved out of this flash write page
if(bByteWritten)
{
dwTemp = dwvLatchedExtAddress.Val + wvLatchedAddress.Val;
if((dwTemp >= *dwAddress + FLASH_WRITE_SIZE) || (dwTemp < *dwAddress))
return DECODE_SUCCESS_NEW_ADDRESS;
}
break;
case GetChecksum1:
vRecordByte = vDecodedByte<<4;
smRecordParser = GetChecksum0;
break;
case GetChecksum0:
vRecordByte |= vDecodedByte;
if(vRecordByte != (~vChecksum + 1))
return DECODE_ERROR_CHECKSUM;
smRecordParser = GetColon;
break;
}
}
return DECODE_SUCCESS_NEED_MORE_HEXDATA;
}
文章评论(0条评论)
登录后参与讨论