.hex文件是什么
它是由一行行符合Intel HEX 文件格式的文本所构成的ASCII 文本文件。每一行包含一 个 HEX 记录 ,由对应机器语言码和/或常量数据的十六进制编码数字组成。Hex文件通常用于传输将被存于ROM 或者EPROM 中的程序和数 据。大多数EPROM 编程器或模拟器使用Intel HEX 文件。Hex文件是可以烧写到单片机中,被单片机执行的一种文件格式,生成Hex文件的方式由很多种,可以通过不同的编译器将C程序或者汇编程序编译生成hex。
.hex文件的数据结构
Hex文件的记录格式如下: Intel HEX 由任意数量的十六进制记录组成。每个记录包含5个域,每一组字母 对应一个不同的域,每一个字母对应一个十六进制编码的数字。每一个域由至少两个十六进制编码数字组成,它们构成一个字节。
:(冒号) 每个Intel HEX 记录都由冒号开头;
LL 是数据长度域, 它代表记录当中数据字节 (D…D) 的数量;
aaaa 是地址域, 它代表记录当中数据的起始地址;
TT 是代表HEX 记录类型的域 , 它可能是以下数据当中的一 个: 00 :数据记录(Data Record),用来记录数据,HEX文件的大部分记录都是数据记录。 01 :文件结束记录(End of FileRecord),用来标识文件结束,放在文件的最后,标识HEX文件的结尾。 02 :扩展段地址记录(ExtendedSegment Address Record),用来标识扩展段地址的记录,扩展段地址记录(HEX86),它包含4~19位数据地址段。由于普通的Intel的HEX记录文件只能记录64K的地址范围,所以大于64K的地址数据要靠扩展段地址记录。 03 :开始段地址记录(Start Segment Address Record) 04 :扩展线性地址记录(Extended Linear Address Record),用来标识扩展线性地址的记录,扩展线性地址记录也叫32位地址记录或者HEX386记录,这些记录包含了数据在存储器里真实地址的高16位。 当一个扩展线性地址记录被读取后,将一直保持有效,直到它被另一个扩展地址记录改变。因为它记录的是后面数据在存储器里存放的真实起始地址,所以它的起始地址偏移量(Load offset)总是0000。 05 :开始线性地址记录(Start Linear Address Record),32位机(80386或更高的CPU)的EIP寄存器里存放的地址(main函数的入口地址)。
D…D 是数据域,它代表一个字节的数据。一个记录可以有许多数据字节。记录当中数据字节的数量必须和数据长度域(LL)中指定的数字相符。
CC 是校验和域,它表示这个记录的校验和。校验和的计算是通过将记录当中所有十六进制编码数字对 的值相加,以256为模进行以下补足。
(CheckSum: two’s complement of length,address,record type and data fields module 256.)
记录格式可表示为:“: [1字节长度] [2字节地址] [1字节记录类型] [n字节数据段] [1字节校验和] ”
关于位、字节、二进制、十六进制: 二进制,是计算机为了快速方便而采用的一种记数方式,十六进制也是一种常用的记数方式。位(bit)就是一个二进制位,即可表示0和1,而字节(Byte)是计算机更通用的计算单位,1字节等于8位,可以代表256个数字(在编程中可以通过这些数字作为判断),int类型一般为4字节,即32位。一个十六进制数,如0xf,代表16个数字,2的4次方,即4位,所以两个十六进制数如0xff就是一个字节。
按照记录类型具体分析
数据记录”00” Intel HEX文件由任意数量以回车换行符结束的数据记录组成,数据记录外观如下: :10246200464C5549442050524F46494C4500464C33 其中,10 是这个记录当中数据字节的数量,即0x10 ;2462 是数据将被下载 到存储器当中的地址,即0x2462 ;00 是记录类型(数据记录),即0x00 ;464C…464C是数据,分别代表0x46,0x4C… ,注意hex中的数据域是小端序的,即按照先低位字节后高位字节的方式记录的 ;33 是这个记录的校验和,即0x33 ;计算方法如下: 256D-(10H+24H+62H+00H+46H+4CH+55H+49H+44H+20H+50H+52H+4FH+46H+49H+4CH+45H+00H+46H+4CH)%256D=33H。
各种进制数的后缀字母分别为: B :二进制数。 Q :八进制数。 D :十进制数。 H :十六进制数。 关于%是取余和取模: 在JAVA、C、C++里,%是取余运算,英文remainder; 在Python里,%号是取模运算,英文modulus; 取余运算的除法是向零舍入,取模运算的除法是向小值舍入; 取余运算结果的符号与被除数相同,取模运算结果的符号与除数相同。
文件结束(EOF)”01” Intel HEX文件必须以文件结束(EOF)记录结束这个记录的记录类的值必须是01.EOF记录外观总是如下: :00000001FF 其中,00 是记录当中数据字节的数量; 0000 是数据被下载到存储器当中的地址,在文件结束记录当中地址是没有意义、被忽略的。0000h 是典型的地址; 01 是记录类型 01(文件结束记录); FF 是这个记录的校验和,计算方法如下: 256D-(00H+00H+00H+01H)=FFH。
扩展线性地址记录(HEX386) ”04” 由于每行标识数据地址的只有2Byte,所以最大只能到64K,为了可以保存高地址的数据,就有了Extended Linear AddressRecord。如果这行的数据类型是0x04,那么,这行的数据就是随后数据的基地址。扩展线性地址记录也叫作32位地址记录或HEX386记录,这些记录含数据的高16位扩展线性地址记录总是有两个数据字节,外观如下: :02000004FFFFFC 其中,02 是这个记录当中数据字节的数量; 0000 是地址域,对于扩展线性地址记录,这个域总是0000; 04 是记录类型04( 扩展线性地址记录); FC 是这个记录的校验和, 计算如下: 256D-(02H+00H+00H+04H+FFH+FFH)/256D=FFH。
当一个扩展线性地址记录被读取,存储于数据域的扩展线性地址被保存,它被用于从 Intel HEX 文件读取来的随后的记录。线性地址保持有效,直到它被另外一个扩展地址记录所改变。通过把记录当中的地址域与被移位的来自扩展线性地址记录的地址数据相加获得数据记录的绝对存储器地址。
以下的例子演示了这个过 程:
:0200000480007A //数据记录的绝对存储器地址高16位为0x8000
:100000001D000A00000000000000000000000000C9
:100010000000000085F170706F0104005D00BD00FC
第一行,是扩展线性地址记录,里面的数据、也就是基地址是0x8000,第二行是数据记录,里面的地址值是0x0000。那么数据1D000A00000000000000000000000000(共16个字节)要写入FLASH中的地址为 (0x00008000<< 16)| 0x0000,也就是写入FLASH的0x80000000这个地址;第三行的数据写入地址为0x80000010。当一个HEX文件的数据超过64k的时候,文件中就会出现多个扩展线性地址记录。
左移运算符(<<): 将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 例:a = a << 2 将a的二进制位左移2位,右补0, 左移1位后a = a * 2; 若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。
按位或运算符(|): 参加运算的两个对象,按二进制位进行“或”运算。 运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1; 即 :参加运算的两个对象只要有一个为1,其值为1。 例如:3|5 即 0000 0011 | 0000 0101 = 0000 0111 因此,3|5的值得7。 另,负数按补码形式参加按位或运算。 “或运算”特殊作用: 常用来对一个数据的某些位置1。 方法:找到一个数,对应X要置1的位,该数的对应位为1,其余位为零。此数与X相或可使X中的某些位置1。 例:将X=10100000的低4位置1 ,用 X | 0000 1111 = 1010 1111即可得到。
扩展段地址记录(HEX86)“02“ 扩展段地址记录也叫HEX86 记录 , 它包括4-19 位数据地址段。扩展段地址记总是有两个数 据字节 , 外观如下: :020000021200EA 其中,02 是记录当中数据字节的数量; 0000 是地址域。对于扩展段地址记录,这个域总是0000; 02 是记录类型 02( 扩展段地址记录); 1200 是地址段; EA 是这个记录的校验和。
当一个扩展段地址记录被读取,存储于数据域的扩展段地址被保存, 它被应用于 从 Intel HEX 文件读取来的随后的记录。段地址保持有效, 直到它被另外一 个扩展地址记录所改变。通过把记录当中的地址域与被移位的来自扩展段地址记录的地址数据相加获得数据记录的绝对存储器地址。
以下的例子演示了这个过程:
来自数据记录地址域的地址 2462 扩展段地址记录数据域 +1200 --------- 绝对存储器地址 00014462
2018年12月29日15:17:45
Mermaid
编译连接示意:
编译
链接
打包
编译
打包
链接
.c/.h源文件
.o二进制文件
.hex烧录文件
.a压缩文件
.c/.h更新源文件
.o二进制文件
项目相关需求:
寻址
替换
.map地址文件
.hex烧录文件
更新数据
2018年12月29日15:20:33
Flowchart
具体流程细节
Created with Raphaël 2.2.0
开始
n=0
读取.map文件中待替换变量在
pflash中的起始地址和字节数,
记作aa和s
获取下一个行数:n=n+1
读取.hex文件中第n行的地址域,
记作an
搜索替换的起始行数:
an<=aa<an+32?
计算替换变量所占行数:
l=s/32向上取整;
令i=n;a(i)=an+32*(i-n)
判断变量是否多跨一行:
an+32*l<aa+s?
l=l+1
从第i行数据域的aa-a(i)字节后开始替换;
替换完成后重算该行的校验和;
判断循环是否继续:
i+1<n+l?
获取下一行行数:i=i+1;
从第i行数据域开始替换;
替换完成后重算该行的校验和;
结束
yes
no
yes
no
yes
no