1、 文档目标
在嵌入式系统开发中,HEX文件是程序编译后生成的一种常见输出格式,尤其在基于ARM架构的开发环境中,由Keil MDK工具链生成的HEX文件被广泛用于烧录和调试。然而,尽管工程师们对其用途较为熟悉,但对其内部结构及数据段的具体含义却往往缺乏深入了解。本文旨在解析由MDK生成的HEX文件中各数据段的组成,帮助开发者理解其内部逻辑,并通过校验和计算验证文件的完整性。
具体目标包括:
● 解析HEX文件中每行数据的组成部分及其意义;
● 探讨不同数据类型(如线性地址、扩展段地址等)的作用;
● 提供详细的校验和计算方法,以确认HEX文件是否正确生成。
通过本文的解析,读者将能够更全面地掌握HEX文件的结构与生成机制,为后续的调试与优化提供理论支持。
2、 问题场景
在嵌入式项目开发过程中,HEX文件通常作为程序烧录的主要载体。然而,许多工程师在使用HEX文件时,往往只关注其功能性(如能否正常烧录或运行),而忽视了其内部结构的细节。例如,在图2-1所示的HEX文件中,每一行数据都包含特定的信息字段,这些字段决定了程序代码和数据如何映射到目标硬件的存储空间中。从图2-1可以看到,HEX文件的每一行数据均遵循严格的格式规范,包含起始标志、数据长度、地址偏移量、数据类型标识、实际数据以及校验码等字段。如果对这些字段的意义不甚了解,可能会导致在分析或调试过程中遇到困难。例如,错误的地址偏移可能导致程序无法正确加载,而校验码的错误则可能暗示文件生成过程中存在异常。
因此,深入解析HEX文件的结构不仅有助于理解其生成机制,还能有效提升开发过程中的问题定位能力。

图 2-1
3、软硬件环境
1)、软件版本:Keil MDK 5.38a
2)、电脑环境:Windows 11
3)、外设硬件:无
4、解决方法
1)、首先,Intel HEX文件是一个ASCII文本文件,其中的文本行遵循Intel HEX文件格式。Intel 十六进制文件中的每一行包含一条十六进制记录。这些记录由表示机器语言代码和/或常量数据的十六进制数组成。Intel十六进制文件通常用于传输将存储在ROM或EPROM中的程序和数据。大多数EPROM程序员或模拟器可以使用Intel十六进制文件。
2)、Hex文件的数据格式为:“:LLAAAATTDDDDDDDD...DDCC”
(1)“:”:表示开头,每一行数据都会用冒号进行开头,表示一个新的内存地址数据开头
(2)“LL”:表示数据长度,L是4位的十六进制,LL表示一个字节。
(3)“AAAA”:表示偏移量,基于起始地址的偏移量是多少
(4)“TT”:表示这一行数据类型或数据标识是什么。
a) 00:表示数据标识;
b) 01:表示文件结束标识,通常的hex文件的最后一行数据中;
c) 02:表示扩展段的地址;
d) 04:表示线性地址;
e) 05:表示线性起始地址
(5)“DDD.....DDD”:这里就表示数据。每一个数字都是占4位,2个数字就是一个字节。
(6)“CC”:表示校验码。校验码是通过下面的公式进行计算出来的。
CheckSum = 0x100 - (Sum & 0xFF)
其中Sum是由这一行的所有字节进行相加所得,Sum与上0xFF后即保留Sum的后8位数据,然后再减去0x100。
3)、例子:
(1)、HEX文件的开头第一行(如图4-3-1):“:020000040040BA”
(a)、“:”:表示开头
(b)、“02”:表示数据长度,02是十六进制,单位的byte,即表示这一行的数据长度是2个字节。
(c)、“0000”:基于起始地址的偏移量是0x0000
(d)、“04”:表示这一行是线性地址
(e)、“0040”:这里就表示段地址信息。每一个数字都是占4位,这一行中4个数字,则16位即2bytes,和前面的第二部分的“10”进行对应。地址是0x0400000,是内存的起始地址即基地址
(f)、“BA”:表示校验码。校验和的计算过程如下:
Sum = 0x02+0x00+0x00+0x04+0x00+0x40=0x46
CheckSum = 0x100-0x46&0xFF=0x100-0x46=0xBA

4-3-1
(2)、HEX文件的中间的数据行(如图4-3-2):“:1000A0009B0340009B0340009B0340009B034000D8”
(a)、“:”:表示开头
(b)、“10”:表示数据长度,这一行的数据长度是16个字节。
(c)、“00A0”:基于起始地址的偏移量是0x00A0
(d)、“00”:表示这一行是数据
(e)、“9B03......4000”:这里就表示数据。每一个数字都是占4位,这一行中32个数字,则128位即16bytes,和前面的第二部分的“10”进行对应。
(f)、“D8”:表示校验码。校验和的计算过程如下:
Sum = 0x10+0x00+0xA0+0x00+0x9B+0x03+0x40+0x00+0x9B+0x03+0x40+0x00+0x9B+0x03+0x40+0x00+0x9B+0x03+0x40+0x00=0x428
CheckSum = 0x100-0x428&0xFF=0x100-0x28=0xD8

图 4-3-2
(4)、Hex文件的倒数第二行数据(如图4-3-3-2):“:040000050040014175”
(a)、“:”:表示开头
(b)、“04”:表示数据长度,这一行的数据长度是4个字节。
(c)、“0000”:基于起始地址的偏移量是0x0000,这个偏移地址是无效数据,无需关注
(d)、“05”:表示这一行是线性起始地址
(e)、“00400141”:这里就表示线性起始地址。地址为0x00400141,是指令集执行的起始地址,这个地址指向的是__scatterload函数,该函数用于将程序代码和数据从链接文件中加载到内存中,是由编译器提供的。(如图4-3-3-1)

图4-3-3-1
(f)、“75”:表示校验码。校验和的计算过程如下:
Sum = 0x04+0x00+0x00+0x05+0x00+0x40+0x01+0x41= =0x8B
CheckSum = 0x100-0x428&0xFF=0x100-0x8B=0x75

图4-3-3-2
(5)、Hex文件的最后一行数据:“:00000001FF”
(a)、“:”:表示开头
(b)、“00”:表示数据长度。
(c)、“0000”:基于起始地址的偏移量是0x0000,这个偏移地址是无效数据,无需关注
(d)、“01”:表示文件结束标识
(e)、“FF”:校验和

图4-3-4

首页 > 资源中心 > FAQ
