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

Read Extended Linear Address Records in Hex (Intel) C

我有三个 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

Extended linear address records are also known as 32-bit address records and HEX386 records. These records contain the upper 16 bits (bits 16-31) of the data address. The extended linear address record always has two data bytes.

在我的特定情况下,这部分等于 1FFF 尽管第二行的数据部分完全包含我希望提取的数据。那是什么意思呢?还是我应该忽略它?

至于校验和,再次引用 Intel HEX 维基百科页面:

For example, in the case of the record :0300300002337A1E, the sum of the decoded byte values is 03 + 00 + 30 + 00 + 02 + 33 + 7A = E2. The two's complement of E2 is 1E, which is the checksum byte appearing at the end of the record.

我想我需要一个从E2中找到1E的函数,但我不知道怎么写。

关于这些部分的任何提示、新信息或可能的解释,尤其是如何处理它们,将是一种祝福。如果有任何混淆,我很乐意进一步解释自己。

我使用过这样的结构:

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;

}

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