1. 程式人生 > 其它 >燒錄的HEX檔案大於flash儲存空間問題

燒錄的HEX檔案大於flash儲存空間問題

技術標籤:嵌入式keil mdk

一、背景
在用一款晶片NRF52832做專案,發現使用Keil編譯後的檔案大小達到了1M,但是片內flash資源只有512K。結果程式可以正常通過J-link燒寫,且執行正常。
晶片資源如下:
nRF52832 是 32 位 ARM® Cortex®-M4F 處理器, 64MHz 、512kB
片內 Flash 和 64kB 片內 RAM、單電源供電、支援多協議,具備低功耗和無線公能。
燒錄檔案:
Load “XXXXXXXXXXX\project\mdk5\Objects\nrf52832_qfaa.axf”
編譯產物:
編譯產物
二、原因
實際的燒錄大小並不是hex檔案打小,hex檔案儲存了其它資訊導致檔案較大,實際燒寫內容小於檔案打小。

三、hex檔案介紹
HEX檔案和BIN檔案是我們經常碰到的2種檔案格式。因為自己也是新手,所以一直對這兩個檔案懵懵懂懂,不甚瞭解,最近在做STM32微控制器的IAP更新,其中要考慮HEX檔案和BIN檔案,所以需要學習下這兩種檔案。下面是最近的我的瞭解,如有不對地方還請指正。

  1. HEX檔案是包括地址資訊的,而BIN檔案格式只包括了資料本身
    在燒寫或下載HEX檔案的時候,一般都不需要使用者指定地址,因為HEX檔案內部的資訊已經包括了地址。而燒寫BIN檔案的時候,使用者是一定需要指定地址資訊的。

  2. HEX檔案格式
    HEX檔案都是由記錄(RECORD)組成的。在HEX檔案裡面,每一行代表一個記錄。以下為記錄(Record)的具體格式:

Record structure
A record (line of text) consists of six fields (parts) that appear in order from left to right:

Start code, one character, an ASCII colon ‘:’.
Byte count, two hex digits, indicating the number of bytes (hex digit pairs) in the data field. The maximum byte count is 255 (0xFF). 16 (0x10) and 32 (0x20) are commonly used byte counts.

Address, four hex digits, representing the 16-bit beginning memory address offset of the data. The physical address of the data is computed by adding this offset to a previously established base address, thus allowing memory addressing beyond the 64 kilobyte limit of 16-bit addresses. The base address, which defaults to zero, can be changed by various types of records. Base addresses and address offsets are always expressed as big endian values.
Record type (see record types below), two hex digits, 00 to 05, defining the meaning of the data field.
Data, a sequence of n bytes of data, represented by 2n hex digits. Some records omit this field (n equals zero). The meaning and interpretation of data bytes depends on the application.
Checksum, two hex digits, a computed value that can be used to verify the record has no errors.

看個例子:
:020000040000FA
:10000400FF00A0E314209FE5001092E5011092E5A3
:00000001FF

  對上面的HEX檔案進行分析:
  第1條記錄的長度為02,LOAD OFFSET為0000,RECTYPE為04,說明該記錄為擴充套件段地址記錄。資料為0000,校驗和為FA。從這個記錄的長度和資料,我們可以計算出一個基地址,這個地址為0X0000。後面的資料記錄都以這個地址為基地址。
  第2條記錄的長度為10(16),LOAD OFFSET為0004,RECTYPE為00,說明該記錄為資料記錄。資料為FF00A0E314209FE5001092E5011092E5,共16個BYTE。這個記錄的校驗和為A3。此時的基地址為0X0000,加上OFFSET,這個記錄裡的16BYTE的資料的起始地址就是0x0000 + 0x0004 = 0x0004.
    第3條記錄的長度為00,LOAD OFFSET為0000,TYPE = 01,校驗和為FF。說明這個是一個END OF FILE RECORD,標識檔案的結尾。
   
    在上面這個例子裡,實際的資料只有16個BYTE:FF00A0E314209FE5001092E5011092E5,其起始地址為0x4。
  1. BIN檔案格式
    對二進位制檔案而言,其實沒有”格式”。檔案只是包括了純粹的二進位制資料。

  2. HEX檔案是用ASCII來表示二進位制的數值。例如一般8-BIT的二進位制數值0x3F,用ASCII來表示就需要分別表示字元’3’和字元’F’,每個字元需要一個BYTE,所以HEX檔案需要 > 2倍的空間。
    對一個BIN檔案而言,你檢視檔案的大小就可以知道檔案包括的資料的實際大小。而對HEX檔案而言,你看到的檔案 大小並不是實際的資料的大小。一是因為HEX檔案是用ASCII來表示資料,二是因為HEX檔案本身還包括別的附加資訊。

四、HEX與flash大小關係
1、hex檔案其實是個格式規範的文字檔案。
程式程式碼大小與hex檔案大小沒有絕對的關聯性,因為我們在用串列埠下載程式時一般都是用的hex檔案下載,,所以大家會以為hex檔案大小和flash大小息息相關,hex檔案大小超過了flash大小就會出問題,我也以為是這樣,直到最近我發現有hex檔案大於flash的大小但是依然可以寫進去,因為真正燒寫進去的是二進位制檔案,在hex檔案中包含了bin檔案的資訊。
2、hex檔案大小和bin檔案大小沒有決定性關係
hex檔案內容很多,其中就包含了bin檔案二進位制的內容,所有很多軟體都能直接把hex檔案轉化成bin檔案,燒寫進flash的檔案不是hex而是一堆bin檔案。
3、flash大小和bin檔案大小息息相關
bin檔案就是完全的程式檔案,裡面包含了所有的程式內容,bin檔案燒寫進flash就可以執行,可以用STlink進入模擬檢視相關的flash,就是bin檔案內容。

五、實際大小
程式碼編譯後各項大小如下: keil編譯大小
Program Size: Code=35968 RO-data=357188 RW-data=7972 ZI-data=11228

Code是程式碼佔用的空間,RO-data是 Read Only 只讀常量的大小,如const型,RW-data是(Read Write) 初始化了的可讀寫變數的大小,ZI-data是(Zero Initialize) 沒有初始化的可讀寫變數的大小。ZI-data不會被算做程式碼裡因為不會被初始化。

在燒寫的時候是FLASH中的被佔用的空間為:Code+RO Data+RW Data
程式執行的時候,晶片內部RAM使用的空間為: RW Data + ZI Data

所以1M的hex檔案實際燒錄了35968+357188+7972=401128Byte=391.7Kb,所以512K的flash是可以正常燒寫進去的。