我有三个Intel十六进制行,看起来像这样:
:02 0000 04 FFFF FC // 04 means Extended Linear Address Record
:0B 0010 00 6164647265737320676170 A7 // 00 means Data
:00 0000 01 FF // 01 means EOF
我故意添加空格以使其更具可读性,但它通常是单件。从Intel HEX Wikipedia page获取的示例和解释。
我的目的是编写一个提取数据部分的函数,在本例中为6164647265737320676170
。
到目前为止,我想像这样;第一个两个字符,数据的大小,将使用如下:
int getSize(char* intelHex)
{
return intelHex[1]*16 + intelHex[2]; // Skip colon and compute only data's size
}
在我的情况下四个字符上的物理地址部分,其中第二行是0010
已知,所以我忽略了它。在两个字符上指定类型的部分应始终为04
,00
然后01
,所以我会检查那样的:
getline(file, hexLine); // Fill hexLine with first line
if (hexLine[7] != '0' ||hexLine[8] != '4') // First line need "04" as type
puts("Error, Extended Linear Address Record type is expected.\n"); //
else {
// Process first line
}
getline(file, hexLine); // Fill hexLine with second line
if (hexLine[7] != '0' || hexLine[8] != '0') // Second line need "00" as type
puts("Error, Data type is expected.\n");
else {
// Process second line, extract data
// for example
int size = getSize(hexLine);
char data[size];
for (int i = 9; i < 9 + size; i++)
data[i - 9] = hexLine[i]; // Each data part's hexadecimal number is stored
}
getline(file, hexLine); // Fill hexLine with third and last line
if (strcmp(hexLine, ":00000001FF") != 0) // EOF is always the same so we check the whole line instead of just the type
puts("Error, EOF type is expected.\n");
我不明白并且无法想象如何计算是第一行的数据部分,这里是FFFF
以及如何检查 CheckSum部分,这是最后两个字符。
引自ARM Information Center Hex File Format:
扩展线性地址记录也称为32位地址记录和HEX386记录。这些记录包含数据地址的高16位(位16-31)。扩展线性地址记录总是有两个数据字节。
在我的特定情况下,这部分等于1FFF
,尽管第二行的数据部分完全包含我想要提取的数据。那是什么意思呢?或者我应该忽略它?
关于校验和,再次引用英特尔HEX维基百科页面:
例如,在记录的情况下:0300300002337A1E,解码的字节值之和为03 + 00 + 30 + 00 + 02 + 33 + 7A = E2。 E2的两个补码是1E,它是出现在记录末尾的校验和字节。
我想我需要一个函数来从1E
中找到E2
,但我不知道如何编写它。
关于这些部件的任何暗示,新信息或可能的解释,特别是如何处理它们,都将是一种祝福。如果有什么令人困惑的话,我会很高兴进一步解释自己。
答案 0 :(得分:0)
我使用了这样的结构:
struct HexIntel {
size_t m_len;
unsigned char m_addr[8];
unsigned char m_data[255];
unsigned char m_checkSum;
bool m_endOfFile;
bool m_success; // Only set true after checking the EOF, the checksums etc.
};
避免幻数的两个非常有用的枚举:
一种类型
enum HEX_INTEL_TYPE {
DATA = 0, HEX_EOF = 1, EXTENDED_SEGMENT_ADDRESS = 2, START_SEGMENT_ADDRESS = 3,
EXTENDED_LINEAR_ADDRESS = 4, START_LINEAR_ADDRESS = 5
}; // In fact initializing those values is useless since the default values are the same
一个用于命名选项卡的每个值:
enum HEX_INTEL_RECORD {
LEN_MSB = 0, LEN_LSB = 1, ADDR_MSB = 2, ADDR_MSB2 = 3, ADDR_LSB2 = 4, ADDR_LSB = 5,
TYPE_MSB = 6, TYPE_LSB = 7, DATA_START = 8
};
使用以下函数将每行解析为int选项卡后:
unsigned char hexCharToInt(char c)
{
const unsigned char ERROR = 16;
const int asciiNumberBetweenDigitAndAlpha = 7; // In ASCII, 7 ponctuations marks separate digits from uppercase alphabetical character
if (c > '/' && c < ':') // In ASCII, '0' is after '/' and ':' after '9'
return c - '0'; // In ASCII '0' = 48; '1' = 49..
else if (c > '@' && c < 'G') // In ASCII, 'A' is after '@'
return c - '0' - asciiNumberBetweenDigitAndAlpha;
else
{
fprintf(stderr, "Not hexadecimal character, can't be parsed into a int.\n");
return ERROR;
}
}
我刚刚根据我正在阅读的行的类型初始化了结构。
检查线路校验和的功能如下:
bool checkSum(const int* hexTab, const size_t sizeOfTab)
{
unsigned char checkSum = 0;
for (size_t i = 0; i + 1 < sizeOfTab - 2; i += 2) // Byte by byte until checksum
{
unsigned char currentByteValue = hexTab[i] * 16 + hexTab[i + 1];
if (currentByteValue + checkSum < 256)
checkSum += currentByteValue;
else
{
while (currentByteValue != 0)
{
if (checkSum == 255)
checkSum = 0;
else
checkSum++;
currentByteValue--;
}
}
}
const unsigned char twoComplement = 256 - checkSum;
const unsigned char tabCheckSum = hexTab[sizeOfTab - 2] * 16 + hexTab[sizeOfTab - 1];
if (twoComplement == tabCheckSum)
return true;
else
return false;
}
我并不打算在第一时间分享这个,但认为它可以提供帮助。不是完整的解决方案,而是帮助构建解决方案的主要功能。如果可以添加任何改进,请不要犹豫,分享它们。