以十六进制(Intel)C读取扩展线性地址记录

时间:2017-05-15 15:22:18

标签: c file hex intel checksum

我有三个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已知,所以我忽略了它。在两个字符上指定类型的部分应始终为0400然后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,但我不知道如何编写它。

关于这些部件的任何暗示,新信息或可能的解释,特别是如何处理它们,都将是一种祝福。如果有什么令人困惑的话,我会很高兴进一步解释自己。

1 个答案:

答案 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;

}

我并不打算在第一时间分享这个,但认为它可以提供帮助。不是完整的解决方案,而是帮助构建解决方案的主要功能。如果可以添加任何改进,请不要犹豫,分享它们。