微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

烧录的HEX文件大于flash存储空间问题

一、背景
在用一款芯片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是可以正常烧写进去的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐