在典型的应用程序中,编译器或汇编器将程序的源代码(例如C或汇编语言)转换为机器代码,并将其输出到一个文件中。然后,这个文件由程序员导入,以将机器代码“烧录”到ROM(或Flash Memory)中,或传输到目标系统以进行加载和执行。
这个存放机器码的文件就是烧录文件,它是用来烧录到微控制器(如MCU、EEPROM、NOR/NAND Flash等)里面的flash memory里面的一个程序文件。烧录文件可以有很多种格式,如bin、Hex,S19等。以下对这几种文件格式做完全解析。
直接存储flash memory的raw data,因为其里面存储的是raw data,所以我们可以直接通过文件地址就找到对应memory地址的内容。缺点是文件地址跟memory地址对应,文件地址是连续的,所以,如果memory地址如果是一个很大的数值(例如0xFFB0000),memory在IC上的地址空间不连续的话,那就非常麻烦。
优点:简单,直接,文件内容地址跟memory内容地址一一对应,非常直观;缺点:地址连续,无法跨空间,而且是二进制,需要特殊工具查看内容。本文讨论的HEX,指的是Intel-HEX,它是由Intel制定的格式。
Intel HEX由ASCII文本行组成,这些行由换行符或回车符或两者分隔。每个文本行均包含编码多个二进制数字的十六进制字符。二进制数可以表示数据,内存地址或其他值,这取决于它们在行中的位置以及行的类型和长度。每个文本行都称为一条记录(record)。
Intel Hex的格式这个record包含6部分内容,其格式是这样的:record 实例:020000021200EA
格式Start codeByte countAddressRecord typeDataChecksum示例:020000021200EAStartCode:1个字符,ASCII 的冒号 ‘:’
Byte count: 2 个Hex 数字,表示这个record 的data 区有几个字节(hex 数字对)。最大值255(0XFF), 16(0X10),和32(0x20 ) 常用
Address: 4个hex数字, 表示Memory数据开始16-bit地址偏移。物理地址通常是有这个偏移加上基地址。基地址默认是0,可以通过各种类型的record来更改。基地址和地址偏移通常是一个大端的数值。
Record type: 2个hex数字, 00 ~ 05, 表示不同数据段的含义。
Data, 一系列data, 表示为 2n 个hex数字,具体内容取决于实际应用数据.
Checksum, 2个hex数字, 以校验这段record内容。
Intel Hex的Checksum 解释:
*record示例 :0300300002337A1E数据和为:03 + 00 + 30 + 00 + 02 + 33 + 7A = E2,这个E2的补码是1E,即这个数据record的补码。
文本行的结束符
Hex文件中,一行记录一个record,所以一个record后面跟这个结束符,即行结束符(可简单理解为换行符),这取决于系统环境,例如Linux用一个LF(即0A),而Windows的是CR LF(0D 0A)。
Record 类型:
Hex编码类型描述示例00Data数据段, 为数据和16 bit起始地址:0B0010006164647265737320676170A701End Of File结束行,一般为文件的最后一行,数据区一般为空:00000001FF02Extended Segment Address数据字段包含与80x86实模式寻址兼容的16位段基址(因此字节数为02)。地址字段(通常为0000)将被忽略。:020000021200EA03Start Segment Address对于80x86处理器,请指定CS:IP寄存器的初始内容。地址字段是0000,字节数是04,前两个字节是CS值,后两个字节是IP值。:0400000300003800C104Extended Linear Address允许32位寻址(最大4GiB)。地址字段将被忽略(通常为0000),字节数始终为02。:02000004FFFFFC05Start Linear Address地址字段是0000(未使用),字节数是04。这四个数据字节代表加载到80386及更高版本CPU的EIP寄存器中的32位值。:04000005000000CD2A ![img](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9naXRlZS5jb20vYnVpbGRtZS9JbWFnZS9yYXcvbWFzdGVyL2ltZy8yMDIwMDkwMTE0MDc0MA?x-oss-process=image/format,png)有时会使用特殊名称来表示使用记录类型的特定子集的HEX文件的格式。例如:
I8HEX 文件只用了 record types 00 and 01 (16 bit addresses)I16HEX 文件只用了 record types 00 through 03 (20 bit addresses)I32HEX 文件只用了 record types 00, 01, 04, and 05 (32 bit addresses)SREC的描述这个SREC跟Hex格式类似,它是由Motorola制定的,一般也叫Motorola S-Record。这种格式通常就是我们平时见的SRECORD, SREC, S19, S28, S37。SREC的文件后缀有好多种,例如:.s19, .s28, .s37, .s, .s1, .s2, .s3, .sx, .srec, .mot
SREC 的格式:
*示例:* S1137AF00A0A0D0000000000000000000000000061
STypeByte CountAddressDataChecksumS1137AF00A0A0D0000000000000000000000000061 一个SREC格式文件由一系列ASCII文本记录组成。记录从左到右具有以下结构:
Record type,两个字符,一个大写的“ S”(0x53),然后是一个数字0到9,定义了记录的类型。Byte count,两个十六进制数字,表示记录的其余部分(地址+数据+校验和)后面的字节数(十六进制数字对)。对于16位地址字段,此字段的最小值为3,另加1个校验和字节,最大值为255(0xFF)。Address,由记录类型决定的四/六/八十六进制数字。地址字节按大端格式排列。Data(2n个十六进制数字的序列),用于数据的n个字节。对于S1 / S2 / S3记录,每条记录通常最多32个字节,因为它适合80字符宽的终端屏幕,尽管16字节将更容易从视觉上解码特定地址的每个字节。Checksum,两个十六进制数字,是字节计数,地址和数据字段的两个十六进制数字对表示的值之和的最低有效字节的补码。有关详细的校验和示例,请参见示例部分。文本行的结束符
跟Hex文件的类似
Record类型
下表描述了10种可能的S记录。S4是保留的,当前未定义。S6最初是保留的,但后来在某个时候重新定义。
Record FieldRecord PurposeAddress FieldData FieldRecord DescriptionS0Header16-bit “0000”√该记录包含特定于供应商的ASCII文本,表示为一系列十六进制数字对。通常以空终止字符串的格式查看此记录的数据。S1Data16-bit Address√该记录包含以16位地址字段开头的数据。该记录通常是 用于8位微控制器,例如AVR,PIC,8051、68xx,6502、80xx,Z80。S2Data24-bit Address√该记录包含以24位地址开头的数据。S3Data32-bit Address√该记录包含以32位地址开头的数据。此记录通常用于 适用于32位微控制器,例如ARM和680x0。S4ReservedN/AN/A保留字段S5Count16-bit Count×此可选记录包含 S1 / S2 / S3记录的16位计数。S6Count24-bit Count×此可选记录包含S1 / S2 / S3记录的24位计数。S7Start Address (Termination)32-bit Address×该记录包含一个32位地址的起始执行位置。S8Start Address (Termination)24-bit Address×该记录包含24位地址处的起始执行位置。S9Start Address (Termination)16-bit Address×该记录在16位地址处包含开始执行位置。Record顺序尽管某些Unix文档指出“文件中S记录的顺序无关紧要,并且可以假定没有特定顺序”,实际上,大多数软件都对SREC记录进行了排序。典型的记录顺序以(有时是可选的)S0头记录开始,以一个或多个S1 / S2 / S3数据记录的序列继续,可能具有一个可选的S5 / S6计数记录,并以一个合适的S7 / S8 / S9终止记录。
S19-style 16-bit address records S0S1 (one or more records)S5 (optional record)S9SREC的Checksum
*示例:* S1137AF00A0A0D0000000000000000000000000061
相加:13 + 7A+F0 + 0A+0A+0D+00+00+00+00+00+00+00+00+00+00+00+00+00 = 19E(hex) 掩码:保留总数的最低有效字节= 9E(hex)。
补码:计算最低有效字节的补码= 61(hex)。
我们来看看一个完整的SREC文件是怎样的:
这个SREC的实际内存内容是:
值得一提的是,SREC文件里面有个S0段,这个段的内容不是存放Memory有效数据的,而是一个文件头信息,可以存一些如这个文件的长度、校验码等。在做软件发布和升级文件的时候,这个内容非常有用。
这个软件功能非常强大,它是用C/C++写的,很多其他软件都引用它,例如keil也有使用这个工具BIN2MOT。
使用IntelHex
pip install intelhex # 读数据 # >>> from intelhex import IntelHex>>> ih = IntelHex() # create empty object >>> ih.loadbin('foo.bin') # load from bin >>> ih.fromfile('bar.bin',format='bin') # also load from bin >>> ih.loadbin('baz.bin',offset=0x1000) # load binary data and place them >>> # starting with specified offset # 写数据 # >>> from cStringIO import StringIO >>> from intelhex import IntelHex >>> ih = IntelHex() >>> ih[0] = 0x55 >>> sio = StringIO() >>> ih.write_hex_file(sio) >>> hexstr = sio.getvalue() >>> sio.close() # 合并文件 # >>> original = IntelHex("foo.hex") >>> new = IntelHex("bar.hex")>>> original.merge(new[0x0F:0x3F])f.minimum_address 256
f.maximum_address 320
len(f) 64
f[f.minimum_address] 33
f[f.minimum_address:f.minimum_address + 1] bytearray(b’!’)