程序燒錄中SREC、Hex、Bin文件格式有啥區別?一文看懂!

在典型的應用程序中,編譯器或匯編器將程序的源代碼(例如C或匯編語言)轉換為機器代碼,并將其輸出到一個文件中。然后,這個文件由程序員導入,以將機器代碼“燒錄”到ROM(或Flash Memory)中

Image placeholder
管理員 2021-03-09 01:47

1. 關于燒錄文件

在典型的應用程序中,編譯器或匯編器將程序的源代碼(例如C或匯編語言)轉換為機器代碼,并將其輸出到一個文件中。然后,這個文件由程序員導入,以將機器代碼“燒錄”到ROM(或Flash Memory)中,或傳輸到目標系統以進行加載和執行。

這個存放機器碼的文件就是燒錄文件,它是用來燒錄到微控制器(如MCU、EEPROM、NOR/NAND Flash等)里面的flash memory里面的一個程序文件。燒錄文件可以有很多種格式,如bin、Hex,S19等。以下對這幾種文件格式做完全解析。

2. Bin文件

這種文件格式最簡單最直接,直接存儲flash memory的raw data。Bin文件有其優點和缺點——簡單直接,是優點也是缺點。

因為其里面存儲的是raw data,所以,我們可以直接通過文件地址就找到對應memory地址的內容。其缺點呢?正因為其文件地址跟memory地址對應,文件地址是連續的,所以,如果memory地址如果是一個很大的數值(例如0xFFB0000),memory在IC上的地址空間不連續的話,那就非常麻煩。

也許你會說,將空白的地方填0x00或者0xFF啊,那你得想想這個bin文件得多大了。

  • 優點:簡單,直接,文件內容地址跟memory內容地址一一對應,非常直觀;

  • 缺點:地址連續,無法跨空間,而且是二進制,需要特殊工具查看內容。

面對這個問題,那么SREC、HEX等文件格式就登場了。

3. HEX文件

本文討論的HEX,指的是Intel-HEX,它是由Intel制定的格式。

Intel Hex的描述

Intel HEX由ASCII文本行組成,這些行由換行符或回車符或兩者分隔。每個文本行均包含編碼多個二進制數字的十六進制字符。二進制數可以表示數據,內存地址或其他值,這取決于它們在行中的位置以及行的類型和長度。每個文本行都稱為一條記錄(record)。

Intel Hex的格式這個record包含6部分內容,其格式是這樣的:

record示例: :020000021200EA

格式 Start code Byte count Address Record type Data Checksum
示例 : 02 0000 02 1200 EA
  1. Start code, 1個字符,是ASCII的冒號 ':'.

  2. Byte count, 2個hex數字, 表示這個record的data區有幾個字節 (hex數字對)。最大值是255 (0xFF). 16 (0x10)32 (0x20)是最常用的。

  3. Address, 4個hex數字, 表示Memory數據開始16-bit地址偏移。物理地址通常是有這個偏移加上基地址。基地址默認是0,可以通過各種類型的record來更改。基地址和地址偏移通常是一個大端的數值。

  4. Record type , 2個hex數字, 00 ~ 05, 表示不同數據段的含義。

  5. Data, 一系列data, 表示為 2n 個hex數字,具體內容取決于實際應用數據。

  6. 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類型

有6種(00~05)標準類型:

Hex編碼 類型 描述 示例
00 Data 數據段, 為數據和16 bit起始地址 :0B0010006164647265737320676170A7
01 End Of File 結束行,一般為文件的最后一行,數據區一般為空 :00000001FF
02 Extended?Segment?Address 數據字段包含與80x86實模式尋址兼容的16位段基址(因此字節數為02)。地址字段(通常為0000)將被忽略。 :020000021200EA
03 Start Segment Address 對于80x86處理器,請指定CS:IP寄存器的初始內容。地址字段是0000,字節數是04,前兩個字節是CS值,后兩個字節是IP值。 :0400000300003800C1
04 Extended Linear Address 允許32位尋址(最大4GiB)。地址字段將被忽略(通常為0000),字節數始終為02。 :02000004FFFFFC
05 Start Linear Address 地址字段是0000(未使用),字節數是04。這四個數據字節代表加載到80386及更高版本CPU的EIP寄存器中的32位值。 :04000005000000CD2A

看看一個hex文件長什么樣:

這個hex的實際內容是:

從中可以看到,地址并非一定要從0x0000開始的。

名稱格式

有時會使用特殊名稱來表示使用記錄類型的特定子集的HEX文件的格式。例如:

  1. I8HEX?文件只用了?record?types?00?and?01?(16?bit?addresses)

  2. I16HEX?文件只用了?record?types?00?through?03?(20?bit?addresses)

  3. I32HEX?文件只用了?record?types?00,?01,?04,?and?05?(32?bit?addresses)

4. SREC文件

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

S Type Byte Count Address Data Checksum
S 1 13 7AF0 0A0A0D00000000000000000000000000 61

一個SREC格式文件由一系列ASCII文本記錄組成。記錄從左到右具有以下結構:

  1. Record?type,兩個字符,一個大寫的“ S”(0x53),然后是一個數字0到9,定義了記錄的類型。

  2. Byte?count,兩個十六進制數字,表示記錄的其余部分(地址+數據+校驗和)后面的字節數(十六進制數字對)。對于16位地址字段,此字段的最小值為3,另加1個校驗和字節,最大值為255(0xFF)。

  3. Address,由記錄類型決定的四/六/八十六進制數字。地址字節按大端格式排列。

  4. Data(2n個十六進制數字的序列),用于數據的n個字節。對于S1 / S2 / S3記錄,每條記錄通常最多32個字節,因為它適合80字符寬的終端屏幕,盡管16字節將更容易從視覺上解碼特定地址的每個字節。

  5. Checksum,兩個十六進制數字,是字節計數,地址和數據字段的兩個十六進制數字對表示的值之和的最低有效字節的補碼。有關詳細的校驗和示例,請參見示例部分。

文本行的結束符

跟Hex文件的類似。此處不累述。

Record類型

下表描述了10種可能的S記錄。S4是保留的,當前未定義。S6最初是保留的,但后來在某個時候重新定義。

Record Field Record Purpose Address Field Data Field Record Description
S0 Header 16-bit "0000" 該記錄包含特定于供應商的ASCII文本,表示為一系列十六進制數字對。通常以空終止字符串的格式查看此記錄的數據。
S1 Data 16-bit Address
該記錄包含以16位地址字段開頭的數據。該記錄通常是 用于8位微控制器,例如AVR,PIC,8051、68xx,6502、80xx,Z80。
S2 Data 24-bit Address 該記錄包含以24位地址開頭的數據。
S3 Data 32-bit Address 該記錄包含以32位地址開頭的數據。此記錄通常用于 適用于32位微控制器,例如ARM和680x0。
S4 Reserved N/A N/A 保留字段
S5 Count 16-bit Count ×
此可選記錄包含?S1?/?S2?/?S3記錄的16位計數。
S6 Count 24-bit Count × 此可選記錄包含S1?/?S2?/?S3記錄的24位計數。
S7 Start Address (Termination) 32-bit Address × 該記錄包含一個32位地址的起始執行位置。
S8 Start Address (Termination) 24-bit Address × 該記錄包含24位地址處的起始執行位置。
S9 Start 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

  1. S0

  2. S1 (one or more records)

  3. S5 (optional record)

  4. S9

  • S28-style 24-bit address records

  1. S0

  2. S2 (one or more records)

  3. S5 (optional record)

  4. S8

  • S37-style 32-bit address records

  1. S0

  2. S3 (one or more records)

  3. S5 (optional record)

  4. 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)?掩碼:保留總數的最低有效字節= 9E(hex)。

補碼:計算最低有效字節的補碼= 61(hex)。

我們來看看一個完整的SREC文件是怎樣的:

這個SREC的實際內存內容是:

值得一提的是,SREC文件里面有個S0段,這個段的內容不是存放Memory有效數據的,而是一個文件頭信息,可以存一些如這個文件的長度、校驗碼等。在做軟件發布和升級文件的時候,這個內容非常有用。

5. 燒錄文件的實際應用

通過IDE編譯生成文件直接燒錄就可以了,學習這些文件格式有什么用?

  1. 合并和拆分文件在做MCU的升級功能的時候,往往有兩個工程,會生成兩個燒錄文件。在仿真調試的時候,要燒錄兩個文件很不方便,在發布軟件的時候,發兩個燒錄文件也不好管理。那么你可以根據這些文件格式要求,將文件合并在一切。如果有一個比較大的文件,存放不同的內容,你也可以將這個大文件拆分成兩個或多個。

  2. 在原來文件上添加附加信息升級文件往往是從一個特殊固定的地址開始,也就是說升級文件是量身定做的。不管bin還是s19文件,我們都可以在文件上附加一些頭信息。例如對于bin文件,可以在前面128個字節中存放一些諸如CRC32,Length等信息,以方便升級程序的解析。

  3. 空白處填充特定內容Hex文件和Srec文件中,是允許有空隙的,即某些地址是沒有內容的。對于實際的Memory來說,這個空隙有可能默認是0xFF(如ARM系列的STM32),但也有是隨機的(如小日本Renesas的RH850)。所以,在需要的情況下,我們可以給這些空隙填充0xFF或者0x00,方便日后做處理,例如做Checksum校驗。

  4. 文件校驗在軟件發布之前,我們可以通過計算這個燒錄文件,已獲得其校驗值(如CRC/XOR/SUM等),以校驗燒錄到實際物理地址的內容是否正確。這就需要知道其具體文件格式再能進行。

6. 燒錄文件處理軟件

通過上面章節,文件格式我們是了解了,怎么才能做一個文件處理程序呢,或者有沒有現成的工具可以使用?

  1. 自己動手寫一個

根據實際需要的功能要求,自行實現一個軟件或者腳本程序。實際上,寫一個這樣的程序并不難,因為其格式也不復雜。對于MCU里面的升級程序,往往需要解析這樣的hex文件或者srec文件格式,也是需要實現這個文件解析的。網上也有很多這樣的例子。對于網上的例子,建議多驗證多測試。

  1. 使用SRecord

這個軟件功能非常強大,它是用C/C++寫的,很多其他軟件都引用它,例如keil也有使用這個工具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支持非常多的文件格式,你想的到的你想不到的都支持(多達40種格式):Ascii-HexASMAtmel GenericBASICBinaryB-RecordCIntel-HexMotorola-Record……

實際上,它只有三板斧:srec_catsrec_cmpsrec_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.

這個不但有Windows的程序點擊鏈接下載(https://sourceforge.net/projects/srecord/files/srecord-win32/1.64/),還開放了源碼點擊鏈接下載(https://sourceforge.net/projects/srecord/files/srecord/1.64/),里面的實現是非常值得我們學習的。

更多內容詳見:http://srecord.sourceforge.net

  1. 使用IntelHex

IntelHex是用Python寫的,如其名字,專門用來處理Intel-Hex文件,當然也可以處理bin文件。其用法非常簡單。

安裝

?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])

還有幾個現成的script給你使用

  • Script hex2bin.py

  • Script bin2hex.py

  • Script hex2dump.py

  • Script hexmerge.py

  • Script hexdiff.py

  • Script hexinfo.py

更多內容詳見:https://python-intelhex.readthedocs.io/en/latest

  1. 使用bincopy

也是Python實現的,但功能比Intelhex更強大點

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

使用

直接看個例子比較好理解

?>>> 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'!')

更多內容詳見:https://bincopy.readthedocs.io/en/latest/

  1. 其他的

  • 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)



注:本文轉載自公眾號“嵌入式軟件實戰派”,作者實戰派師姐,轉載目的在于傳遞更多信息,并不代表本網贊同其觀點和對其真實性負責。如有侵權行為,請聯系我們,我們會及時刪除。

評論0