程序燒錄中SREC、Hex、Bin文件格式有啥區(qū)別?一文看懂!
掃描二維碼
隨時(shí)隨地手機(jī)看文章
▍1. 關(guān)于燒錄文件
在典型的應(yīng)用程序中,編譯器或匯編器將程序的源代碼(例如C或匯編語(yǔ)言)轉(zhuǎn)換為機(jī)器代碼,并將其輸出到一個(gè)文件中。然后,這個(gè)文件由程序員導(dǎo)入,以將機(jī)器代碼“燒錄”到ROM(或Flash Memory)中,或傳輸?shù)侥繕?biāo)系統(tǒng)以進(jìn)行加載和執(zhí)行。
這個(gè)存放機(jī)器碼的文件就是燒錄文件,它是用來(lái)燒錄到微控制器(如MCU、EEPROM、NOR/NAND Flash等)里面的flash memory里面的一個(gè)程序文件。燒錄文件可以有很多種格式,如bin、Hex,S19等。以下對(duì)這幾種文件格式做完全解析。
▍2. Bin文件
這種文件格式最簡(jiǎn)單最直接,直接存儲(chǔ)flash memory的raw data。Bin文件有其優(yōu)點(diǎn)和缺點(diǎn)——簡(jiǎn)單直接,是優(yōu)點(diǎn)也是缺點(diǎn)。
因?yàn)槠淅锩娲鎯?chǔ)的是raw data,所以,我們可以直接通過(guò)文件地址就找到對(duì)應(yīng)memory地址的內(nèi)容。其缺點(diǎn)呢?正因?yàn)槠湮募刂犯鷐emory地址對(duì)應(yīng),文件地址是連續(xù)的,所以,如果memory地址如果是一個(gè)很大的數(shù)值(例如0xFFB0000),memory在IC上的地址空間不連續(xù)的話,那就非常麻煩。
也許你會(huì)說(shuō),將空白的地方填0x00或者0xFF啊,那你得想想這個(gè)bin文件得多大了。
優(yōu)點(diǎn):簡(jiǎn)單,直接,文件內(nèi)容地址跟memory內(nèi)容地址一一對(duì)應(yīng),非常直觀;
缺點(diǎn):地址連續(xù),無(wú)法跨空間,而且是二進(jìn)制,需要特殊工具查看內(nèi)容。
面對(duì)這個(gè)問(wèn)題,那么SREC、HEX等文件格式就登場(chǎng)了。
▍3. HEX文件
本文討論的HEX,指的是Intel-HEX,它是由Intel制定的格式。
Intel Hex的描述
Intel HEX由ASCII文本行組成,這些行由換行符或回車符或兩者分隔。每個(gè)文本行均包含編碼多個(gè)二進(jìn)制數(shù)字的十六進(jìn)制字符。二進(jìn)制數(shù)可以表示數(shù)據(jù),內(nèi)存地址或其他值,這取決于它們?cè)谛兄械奈恢靡约靶械念愋秃烷L(zhǎng)度。每個(gè)文本行都稱為一條記錄(record)。
Intel Hex的格式這個(gè)record包含6部分內(nèi)容,其格式是這樣的:
record示例: :020000021200EA
格式 | Start code | Byte count | Address | Record type | Data | Checksum |
---|---|---|---|---|---|---|
示例 | : | 02 | 0000 | 02 | 1200 | EA |
Start code, 1個(gè)字符,是ASCII的冒號(hào) ':'.
Byte count, 2個(gè)hex數(shù)字, 表示這個(gè)record的data區(qū)有幾個(gè)字節(jié) (hex數(shù)字對(duì))。最大值是
255 (0xFF)
.16 (0x10)
和32 (0x20)
是最常用的。Address, 4個(gè)hex數(shù)字, 表示Memory數(shù)據(jù)開(kāi)始16-bit地址偏移。物理地址通常是有這個(gè)偏移加上基地址?;刂纺J(rèn)是0,可以通過(guò)各種類型的record來(lái)更改?;刂泛偷刂菲仆ǔJ且粋€(gè)大端的數(shù)值。
Record type , 2個(gè)hex數(shù)字,
00 ~ 05
, 表示不同數(shù)據(jù)段的含義。Data, 一系列data, 表示為
2n
個(gè)hex數(shù)字,具體內(nèi)容取決于實(shí)際應(yīng)用數(shù)據(jù)。Checksum, 2個(gè)hex數(shù)字, 以校驗(yàn)這段record內(nèi)容。
Intel Hex的Checksum直接用例子解釋吧:
record示例: :0300300002337A1E數(shù)據(jù)和為:03 + 00 + 30 + 00 + 02 + 33 + 7A = E2,這個(gè)E2的補(bǔ)碼是1E,即這個(gè)數(shù)據(jù)record的補(bǔ)碼。
文本行的結(jié)束符
Hex文件中,一行記錄一個(gè)record,所以一個(gè)record后面跟這個(gè)結(jié)束符,即行結(jié)束符(可簡(jiǎn)單理解為換行符),這取決于系統(tǒng)環(huán)境,例如Linux用一個(gè)LF(即0A),而Windows的是CR LF(0D 0A)。
Record類型
有6種(00~05)標(biāo)準(zhǔn)類型:
Hex編碼 | 類型 | 描述 | 示例 |
---|---|---|---|
00 | Data | 數(shù)據(jù)段, 為數(shù)據(jù)和16 bit起始地址 | :0B0010006164647265737320676170A7 |
01 | End Of File | 結(jié)束行,一般為文件的最后一行,數(shù)據(jù)區(qū)一般為空 | :00000001FF |
02 | Extended Segment Address | 數(shù)據(jù)字段包含與80x86實(shí)模式尋址兼容的16位段基址(因此字節(jié)數(shù)為02)。地址字段(通常為0000)將被忽略。 | :020000021200EA |
03 | Start Segment Address | 對(duì)于80x86處理器,請(qǐng)指定CS:IP寄存器的初始內(nèi)容。地址字段是0000,字節(jié)數(shù)是04,前兩個(gè)字節(jié)是CS值,后兩個(gè)字節(jié)是IP值。 | :0400000300003800C1 |
04 | Extended Linear Address | 允許32位尋址(最大4GiB)。地址字段將被忽略(通常為0000),字節(jié)數(shù)始終為02。 | :02000004FFFFFC |
05 | Start Linear Address | 地址字段是0000(未使用),字節(jié)數(shù)是04。這四個(gè)數(shù)據(jù)字節(jié)代表加載到80386及更高版本CPU的EIP寄存器中的32位值。 | :04000005000000CD2A |
看看一個(gè)hex文件長(zhǎng)什么樣:
這個(gè)hex的實(shí)際內(nèi)容是:
從中可以看到,地址并非一定要從0x0000開(kāi)始的。
名稱格式
有時(shí)會(huì)使用特殊名稱來(lái)表示使用記錄類型的特定子集的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)
▍4. SREC文件
SREC的描述這個(gè)SREC跟Hex格式類似,它是由Motorola制定的,一般也叫Motorola S-Record。這種格式通常就是我們平時(shí)見(jiàn)的SRECORD, SREC, S19, S28, S37。SREC的文件后綴有好多種,例如:.s19, .s28, .s37, .s, .s1, .s2, .s3, .sx, .srec, .mot
SREC的格式
示例: S1137AF00A0A0D0000000000000000000000000061
S | Type | Byte Count | Address | Data | Checksum |
---|---|---|---|---|---|
S | 1 | 13 | 7AF0 | 0A0A0D00000000000000000000000000 |
61 |
一個(gè)SREC格式文件由一系列ASCII文本記錄組成。記錄從左到右具有以下結(jié)構(gòu):
Record type,兩個(gè)字符,一個(gè)大寫的“ S”(0x53),然后是一個(gè)數(shù)字0到9,定義了記錄的類型。
Byte count,兩個(gè)十六進(jìn)制數(shù)字,表示記錄的其余部分(地址+數(shù)據(jù)+校驗(yàn)和)后面的字節(jié)數(shù)(十六進(jìn)制數(shù)字對(duì))。對(duì)于16位地址字段,此字段的最小值為3,另加1個(gè)校驗(yàn)和字節(jié),最大值為255(0xFF)。
Address,由記錄類型決定的四/六/八十六進(jìn)制數(shù)字。地址字節(jié)按大端格式排列。
Data(2n個(gè)十六進(jìn)制數(shù)字的序列),用于數(shù)據(jù)的n個(gè)字節(jié)。對(duì)于S1 / S2 / S3記錄,每條記錄通常最多32個(gè)字節(jié),因?yàn)樗m合80字符寬的終端屏幕,盡管16字節(jié)將更容易從視覺(jué)上解碼特定地址的每個(gè)字節(jié)。
Checksum,兩個(gè)十六進(jìn)制數(shù)字,是字節(jié)計(jì)數(shù),地址和數(shù)據(jù)字段的兩個(gè)十六進(jìn)制數(shù)字對(duì)表示的值之和的最低有效字節(jié)的補(bǔ)碼。有關(guān)詳細(xì)的校驗(yàn)和示例,請(qǐng)參見(jiàn)示例部分。
文本行的結(jié)束符
跟Hex文件的類似。此處不累述。
Record類型
下表描述了10種可能的S記錄。S4是保留的,當(dāng)前未定義。S6最初是保留的,但后來(lái)在某個(gè)時(shí)候重新定義。
Record Field | Record Purpose | Address Field | Data Field | Record Description |
---|---|---|---|---|
S0 | Header | 16-bit "0000" | √ | 該記錄包含特定于供應(yīng)商的ASCII文本,表示為一系列十六進(jìn)制數(shù)字對(duì)。通常以空終止字符串的格式查看此記錄的數(shù)據(jù)。 |
S1 | Data | 16-bit Address | √ |
該記錄包含以16位地址字段開(kāi)頭的數(shù)據(jù)。該記錄通常是 用于8位微控制器,例如AVR,PIC,8051、68xx,6502、80xx,Z80。 |
S2 | Data | 24-bit Address | √ | 該記錄包含以24位地址開(kāi)頭的數(shù)據(jù)。 |
S3 | Data | 32-bit Address | √ | 該記錄包含以32位地址開(kāi)頭的數(shù)據(jù)。此記錄通常用于 適用于32位微控制器,例如ARM和680x0。 |
S4 | Reserved | N/A | N/A | 保留字段 |
S5 | Count | 16-bit Count | × |
此可選記錄包含 S1 / S2 / S3記錄的16位計(jì)數(shù)。 |
S6 | Count | 24-bit Count | × | 此可選記錄包含S1 / S2 / S3記錄的24位計(jì)數(shù)。 |
S7 | Start Address (Termination) | 32-bit Address | × | 該記錄包含一個(gè)32位地址的起始執(zhí)行位置。 |
S8 | Start Address (Termination) | 24-bit Address | × | 該記錄包含24位地址處的起始執(zhí)行位置。 |
S9 | Start Address (Termination) | 16-bit Address | × | 該記錄在16位地址處包含開(kāi)始執(zhí)行位置。 |
Record順序盡管某些Unix文檔指出“文件中S記錄的順序無(wú)關(guān)緊要,并且可以假定沒(méi)有特定順序”,實(shí)際上,大多數(shù)軟件都對(duì)SREC記錄進(jìn)行了排序。典型的記錄順序以(有時(shí)是可選的)S0頭記錄開(kāi)始,以一個(gè)或多個(gè)S1 / S2 / S3數(shù)據(jù)記錄的序列繼續(xù),可能具有一個(gè)可選的S5 / S6計(jì)數(shù)記錄,并以一個(gè)合適的S7 / S8 / S9終止記錄。
S19-style 16-bit address records
S0
S1 (one or more records)
S5 (optional record)
S9
S28-style 24-bit address records
S0
S2 (one or more records)
S5 (optional record)
S8
S37-style 32-bit address records
S0
S3 (one or more records)
S5 (optional record)
S7
SREC的Checksum
示例: S1137AF00A0A0D0000000000000000000000000061
相加:13 + 7A+F0 + 0A+0A+0D+00+00+00+00+00+00+00+00+00+00+00+00+00
= 19E
(hex) 掩碼:保留總數(shù)的最低有效字節(jié)= 9E
(hex)。
補(bǔ)碼:計(jì)算最低有效字節(jié)的補(bǔ)碼= 61
(hex)。
我們來(lái)看看一個(gè)完整的SREC文件是怎樣的:
這個(gè)SREC的實(shí)際內(nèi)存內(nèi)容是:
值得一提的是,SREC文件里面有個(gè)S0段,這個(gè)段的內(nèi)容不是存放Memory有效數(shù)據(jù)的,而是一個(gè)文件頭信息,可以存一些如這個(gè)文件的長(zhǎng)度、校驗(yàn)碼等。在做軟件發(fā)布和升級(jí)文件的時(shí)候,這個(gè)內(nèi)容非常有用。
▍5. 燒錄文件的實(shí)際應(yīng)用
通過(guò)IDE編譯生成文件直接燒錄就可以了,學(xué)習(xí)這些文件格式有什么用?
合并和拆分文件在做MCU的升級(jí)功能的時(shí)候,往往有兩個(gè)工程,會(huì)生成兩個(gè)燒錄文件。在仿真調(diào)試的時(shí)候,要燒錄兩個(gè)文件很不方便,在發(fā)布軟件的時(shí)候,發(fā)兩個(gè)燒錄文件也不好管理。那么你可以根據(jù)這些文件格式要求,將文件合并在一切。如果有一個(gè)比較大的文件,存放不同的內(nèi)容,你也可以將這個(gè)大文件拆分成兩個(gè)或多個(gè)。
在原來(lái)文件上添加附加信息升級(jí)文件往往是從一個(gè)特殊固定的地址開(kāi)始,也就是說(shuō)升級(jí)文件是量身定做的。不管bin還是s19文件,我們都可以在文件上附加一些頭信息。例如對(duì)于bin文件,可以在前面128個(gè)字節(jié)中存放一些諸如CRC32,Length等信息,以方便升級(jí)程序的解析。
空白處填充特定內(nèi)容Hex文件和Srec文件中,是允許有空隙的,即某些地址是沒(méi)有內(nèi)容的。對(duì)于實(shí)際的Memory來(lái)說(shuō),這個(gè)空隙有可能默認(rèn)是0xFF(如ARM系列的STM32),但也有是隨機(jī)的(如小日本Renesas的RH850)。所以,在需要的情況下,我們可以給這些空隙填充0xFF或者0x00,方便日后做處理,例如做Checksum校驗(yàn)。
文件校驗(yàn)在軟件發(fā)布之前,我們可以通過(guò)計(jì)算這個(gè)燒錄文件,已獲得其校驗(yàn)值(如CRC/XOR/SUM等),以校驗(yàn)燒錄到實(shí)際物理地址的內(nèi)容是否正確。這就需要知道其具體文件格式再能進(jìn)行。
▍6. 燒錄文件處理軟件
通過(guò)上面章節(jié),文件格式我們是了解了,怎么才能做一個(gè)文件處理程序呢,或者有沒(méi)有現(xiàn)成的工具可以使用?
自己動(dòng)手寫一個(gè)
根據(jù)實(shí)際需要的功能要求,自行實(shí)現(xiàn)一個(gè)軟件或者腳本程序。實(shí)際上,寫一個(gè)這樣的程序并不難,因?yàn)槠涓袷揭膊粡?fù)雜。對(duì)于MCU里面的升級(jí)程序,往往需要解析這樣的hex文件或者srec文件格式,也是需要實(shí)現(xiàn)這個(gè)文件解析的。網(wǎng)上也有很多這樣的例子。對(duì)于網(wǎng)上的例子,建議多驗(yàn)證多測(cè)試。
使用SRecord
這個(gè)軟件功能非常強(qiáng)大,它是用C/C++寫的,很多其他軟件都引用它,例如keil也有使用這個(gè)工具BIN2MOT。
The SRecord package is a collection of powerful tools for manipulating EPROM load files. I wrote SRecord because when I was looking for programs to manipulate EPROM load files, I could not find very many. The ones that I could find only did a few of the things I needed. SRecord is written in C++ and polymorphism is used to provide the file format flexibility and arbitrary filter chaining. Adding more file formats and filters is relatively simple.
SRecord支持非常多的文件格式,你想的到的你想不到的都支持(多達(dá)40種格式):Ascii-Hex、ASM、Atmel Generic、BASIC、Binary、B-Record、C、Intel-Hex、Motorola-Record……
實(shí)際上,它只有三板斧:srec_cat 、srec_cmp、srec_info
The primary tools of the package are srec_cat and srec_cmp. All of the tools understand all of the file formats, and all of the filters.
Name | Description |
---|---|
srec_cat | The srec_cat program may be used to catenate (join) EPROM load files, or portions of EPROM load files, together. Because it understands all of the input and output formats, it can also be used to convert files from one format to another. |
srec_cmp | The srec_cmp program may be use to compare EPROM load files, or portions of EPROM load files, for equality. |
srec_info | The srec_info program may be used to print summary information about EPROM load files. |
這個(gè)不但有Windows的程序點(diǎn)擊鏈接下載(https://sourceforge.net/projects/srecord/files/srecord-win32/1.64/),還開(kāi)放了源碼點(diǎn)擊鏈接下載(https://sourceforge.net/projects/srecord/files/srecord/1.64/),里面的實(shí)現(xiàn)是非常值得我們學(xué)習(xí)的。
更多內(nèi)容詳見(jiàn):http://srecord.sourceforge.net
使用IntelHex
IntelHex是用Python寫的,如其名字,專門用來(lái)處理Intel-Hex文件,當(dāng)然也可以處理bin文件。其用法非常簡(jiǎn)單。
安裝:
pip install intelhex
讀數(shù)據(jù):
>>> 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
寫數(shù)據(jù):
>>> 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])
還有幾個(gè)現(xiàn)成的script給你使用:
Script
hex2bin.py
Script
bin2hex.py
Script
hex2dump.py
Script
hexmerge.py
Script
hexdiff.py
Script
hexinfo.py
更多內(nèi)容詳見(jiàn):https://python-intelhex.readthedocs.io/en/latest
使用bincopy
也是Python實(shí)現(xiàn)的,但功能比Intelhex更強(qiáng)大點(diǎn)
Mangling of various file formats that conveys binary information (Motorola S-Record, Intel HEX, TI-TXT and binary files).Project homepage: https://github.com/eerimoq/bincopyDocumentation: https://bincopy.readthedocs.io
安裝:
pip install bincopy
使用:
直接看個(gè)例子比較好理解
>>> import bincopy>>> f = bincopy.BinFile("tests/files/in.hex")
>>> print(f.as_ihex())
:20010000214601360121470136007EFE09D219012146017E17C20001FF5F16002148011979:20012000194E79234623965778239EDA3F01B2CA3F0156702B5E712B722B7321460134219F:00000001FF
>>> print(f.as_srec())
S32500000100214601360121470136007EFE09D219012146017E17C20001FF5F16002148011973
S32500000120194E79234623965778239EDA3F01B2CA3F0156702B5E712B722B73214601342199
S5030002FA
>>> print(f.as_ti_txt())
@0100
21 46 01 36 01 21 47 01 36 00 7E FE 09 D2 19 01
21 46 01 7E 17 C2 00 01 FF 5F 16 00 21 48 01 19
19 4E 79 23 46 23 96 57 78 23 9E DA 3F 01 B2 CA
3F 01 56 70 2B 5E 71 2B 72 2B 73 21 46 01 34 21
q
>>> f.as_binary()
bytearray(b'!F\x016\x01!G\x016\x00~\xfe\t\xd2\x19\x01!F\x01~\x17\xc2\x00\x01\xff_\x16\x00!H\x01\x19\x19Ny#F#\x96Wx#\x9e\xda?\x01\xb2\xca?\x01Vp+^q+r+s!F\x014!')
>>> list(f.segments)
[Segment(address=256, data=bytearray(b'!F\x016\x01!G\x016\x00~\xfe\t\xd2\x19\x01!F\x01~\x17\xc2\x00\x01\xff_\x16\x00!H\x01\x19\x19Ny#F#\x96Wx#\x9e\xda?\x01\xb2\xca?\x01Vp+^q+r+s!F\x014!'))]
>>> 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'!')
更多內(nèi)容詳見(jiàn):https://bincopy.readthedocs.io/en/latest/
其他的
BIN2MOT(), BINARY to Motorola S-Record file converter utility.(http://www.keil.com/download/docs/4.asp)
SRecordizer is a tool for viewing, editing, and error checking S19 format files.(http://srecordizer.codeplex.com/)
binex - a converter between Intel HEX and binary for Windows.(http://www.nlsw.nl/software/)
libgis, open source C library that converts Intel HEX, Motorola S-Record, Atmel Generic files.(https://github.com/vsergeev/libGIS)
kk_srec is a C library and program for reading the SREC format.(https://github.com/arkku/srec)
本文參考:
Wikipedia-SREC (File format)(https://en.wikipedia.org/wiki/SREC_(file_format))
Wikipedia-Intel Hex(https://en.wikipedia.org/wiki/Intel_HEX)
-END-
本文授權(quán)轉(zhuǎn)載自公眾號(hào)“嵌入式軟件實(shí)戰(zhàn)派”,作者實(shí)戰(zhàn)派師姐
推薦閱讀
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!