11945|12

96

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

关于Hex文件合并及编辑的点点思考 [复制链接]

 
事情原由来自工厂生产中,一片单片机往往要在不同地址刷入相应的程序。姑且叫做BOOT程序、应用程序等等之类。可以用jlink刷、量产工具刷等等。更有些还在Flash特定地址写上特定的识别字符,增加一些识别功能。总而言之,麻烦,程序多。于是网上搜索了hex文件的格式,经过些许测试,证明可行,遂有此文。
      关于hex文件格式,我就不细表,网上太多,大家可以自行查阅,本文主要讲述如何合并hex以及增加特定内容。大致一个完整的hex包括四个部分:
      第一部分:段地址;以:020000040800F2来说,段地址为0x0800,左移16位得到基地址0x08000000;      第二部分:程序数据;主要存放程序内容,一般一行16字节;
      第三部分:main函数入口地址;以:0400000508000131BD来说,main函数入口地址为0x08000131,这个可以有程序map文件进行核对。
      第四部分:结束,以:00000001FF结尾。
      清楚了上述hex文件的组成,如果将两个hex文件合并。典型的是BOOT程序和应用程序,拿stm32说,程序起始地址一般为0x08000000,一般BOOT的起始地址就是这个,再就是应用程序,往往向后偏移一些,例如0x0800C000之类。所以观察两者的hex文件第一行是相同的,因为段地址都是0x0800。那么合并就好操作了,将BOOT文件的第一部分、第二部分首先放置,再继续添加应用程序的第二部分内容,再添加BOOT程序的第三部分内容及第四部分的结束部分。那么一个典型的合并就完成了。
      如果想在某个特定的地址写入特定的字节,例如,我还想再0x0803F000地址开始处写入0xAAAAFFFF内容,那该怎么操作?由于想写入的段地址不是0x0800而是0x0803,那么需要重新定义段地址部分。如图:将这部分加入程序数据后面即可。

EM截图_201791583225.png (2.64 KB, 下载次数: 1)

段地址

段地址

EM截图_20179158389.png (7.41 KB, 下载次数: 1)

程序数据

程序数据

EM截图_201791584157.png (1.97 KB, 下载次数: 1)

main函数入口地址

main函数入口地址

EM截图_201791585645.png (5.68 KB, 下载次数: 3)

特定地址写入数据

特定地址写入数据
此帖出自单片机论坛

最新回复

楼主,你还有C#写的合并hex的源码吗?想学习下,可以发我邮箱吗1451804815@qq.com   感谢   详情 回复 发表于 2019-7-11 22:44
点赞 关注(1)
 

回复
举报

7671

帖子

18

TA的资源

五彩晶圆(高级)

沙发
 
bin多简单。 cat b1 b2 > b2 就好了。
此帖出自单片机论坛

点评

没有您说的那么简单合并,bin文件是要地址连续的,不过BOOT程序和应用程序之间有很大的空档,还要补FF进行填充,并不是简单的合并。  详情 回复 发表于 2017-9-15 12:49
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 

回复

96

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
freebsder 发表于 2017-9-15 09:44
bin多简单。 cat b1 b2 > b2 就好了。

没有您说的那么简单合并,bin文件是要地址连续的,不过BOOT程序和应用程序之间有很大的空档,还要补FF进行填充,并不是简单的合并。
此帖出自单片机论坛

点评

那是你不会才搞这样复杂。  详情 回复 发表于 2017-9-15 15:44
 
 
 

回复

3238

帖子

5

TA的资源

五彩晶圆(中级)

4
 
项目研发人员都需要考虑到后期项目维护成本问题,其中一个很大的维护成本在于软件有Bug,固件更新问题。如果带网络的话,远程升级是成本最低,目前我做的产品都支持远程升级,千里之外更新固件解BUG,不留半点痕迹。
对于IAP升级,程序组成是BOOT区+APP区(一般两块app区),为了减少生产阶段的工作量,把两次烧录搞成一次烧录。这时就需要把boot和app的hex文件,楼主手动修改效率太低了,而且容易出事,可以使用工具直接合并,我现在都是用工具直接把BOTT和APP的hex文件合并生产一个新的hex文件,重新命名好,直接发给生产烧录就行。如果需要工具,我也可以分享
此帖出自单片机论坛
 
个人签名淘宝:https://viiot.taobao.com/Q群243090717
多年专业物联网行业经验,个人承接各类物联网外包项目
 
 

回复

3238

帖子

5

TA的资源

五彩晶圆(中级)

5
 
我还是直接把工具分享出来,正好公司电脑也有,希望能对楼主有用。我现在都是用这个工具合并hex文件,用的不错,这个也是我之前在网上找的。

hex合并.rar

27.5 KB, 下载次数: 235

此帖出自单片机论坛

点评

谢谢,我自己用C#也写了个,应用测试都OK。不过还是感谢您。做了这个后发现应该有人需要,就写了个帖子。  详情 回复 发表于 2017-9-15 15:01
 
个人签名淘宝:https://viiot.taobao.com/Q群243090717
多年专业物联网行业经验,个人承接各类物联网外包项目
 
 

回复

96

帖子

0

TA的资源

一粒金砂(高级)

6
 
wateras1 发表于 2017-9-15 14:33
我还是直接把工具分享出来,正好公司电脑也有,希望能对楼主有用。我现在都是用这个工具合并hex文件,用的 ...

谢谢,我自己用C#也写了个,应用测试都OK。不过还是感谢您。做了这个后发现应该有人需要,就写了个帖子。
此帖出自单片机论坛
 
 
 

回复

7671

帖子

18

TA的资源

五彩晶圆(高级)

7
 
dige 发表于 2017-9-15 12:49
没有您说的那么简单合并,bin文件是要地址连续的,不过BOOT程序和应用程序之间有很大的空档,还要补FF进 ...

那是你不会才搞这样复杂。
此帖出自单片机论坛

点评

人固有自己不熟练地方,不会学了就会了。请问您测试没有?告诉您,您的直接合并的方法是不行的。实践检验真知,我固然喜欢简单方法,您要是有更好的确切可行的摆出来说。  详情 回复 发表于 2017-9-15 15:50
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

96

帖子

0

TA的资源

一粒金砂(高级)

8
 
freebsder 发表于 2017-9-15 15:44
那是你不会才搞这样复杂。

人固有自己不熟练地方,不会学了就会了。请问您测试没有?告诉您,您的直接合并的方法是不行的。实践检验真知,我固然喜欢简单方法,您要是有更好的确切可行的摆出来说。
此帖出自单片机论坛

点评

你手段太low,早几年就自动生成bin了。 直接合并当然也需要借助外部小程序。首先需要一个小程序能取得bin的大小,然后写入一个头文件。如果是gcc的话,有现成的objdump命令可以拿到。 然后在第二个,姑且叫app的工  详情 回复 发表于 2017-9-15 17:03
 
 
 

回复

7671

帖子

18

TA的资源

五彩晶圆(高级)

9
 
dige 发表于 2017-9-15 15:50
人固有自己不熟练地方,不会学了就会了。请问您测试没有?告诉您,您的直接合并的方法是不行的。实践检验 ...

你手段太low,早几年就自动生成bin了。
直接合并当然也需要借助外部小程序。首先需要一个小程序能取得bin的大小,然后写入一个头文件。如果是gcc的话,有现成的objdump命令可以拿到。
然后在第二个,姑且叫app的工程,pre build的时候用这个小程序生成头文件,然后在link file 里面include 进去就取得了boot的大小。然后link脚本就可以知道实际合并之后的链接地址,通过脚本可以把app自身的启动部分放在最开始,这样可以紧接着boot。boot里面需要调用app吗?它产生的时候可以把link脚本里面的flash结尾export出来,然后+4,就知道app的启动地址。
然后在app 的 after build里面 直接cat 或者windows 的字节拷贝,就行了。
以上boot和app有任何改变,整个手段不需要调整。
此帖出自单片机论坛

点评

恕我愚笨,没有完全理解您的意思,但大概明白您说的流程。貌似我的单片机应用和您的不在一个频道,基本上做BOOT+APP方式的都是包含有远程更新功能的,而APP一般包含两块,一块应用,一块备份。拿stm32说,APP的起始  详情 回复 发表于 2017-9-15 18:12
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

96

帖子

0

TA的资源

一粒金砂(高级)

10
 
freebsder 发表于 2017-9-15 17:03
你手段太low,早几年就自动生成bin了。
直接合并当然也需要借助外部小程序。首先需要一个小程序能取得bi ...

恕我愚笨,没有完全理解您的意思,但大概明白您说的流程。貌似我的单片机应用和您的不在一个频道,基本上做BOOT+APP方式的都是包含有远程更新功能的,而APP一般包含两块,一块应用,一块备份。拿stm32说,APP的起始地址就是固定了,不存在随着程序变动修改而APP的起始地址变来变去的情况。prebuild我确实用的少,afterbuild做些事情还常见。请问您如何解决远程更新的问题?
此帖出自单片机论坛

点评

升级的其中一个问题就是app的偏移地址的确定,这涉及到符号定位。一旦确定地址,剩下的你之前怎么升级,后面也怎么升级。 前面可变地址的情况复杂一些,但是你既然要固定地址的,那就更简单了,只需要脚本就基本能  详情 回复 发表于 2017-9-15 20:40
 
 
 

回复

7671

帖子

18

TA的资源

五彩晶圆(高级)

11
 
本帖最后由 freebsder 于 2017-9-15 20:51 编辑
dige 发表于 2017-9-15 18:12
恕我愚笨,没有完全理解您的意思,但大概明白您说的流程。貌似我的单片机应用和您的不在一个频道,基本上 ...

升级的其中一个问题就是app的偏移地址的确定,这涉及到符号定位。一旦确定地址,剩下的你以前怎么搞升级的,以后还怎么搞。
前面可变地址的情况复杂一些,但是你既然要固定地址的,那就更简单了,只需要脚本就基本能达成。
gcc强大到根本不用费脑。下面是iar的(keil我不会)。

假设你的flash有100k,而boot小于20k,你打算在20k起始的地方放置app,也就是0x5000字节偏移
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x08004FFF;   // boot 20k,app可以从0x08005000 start
xxx     // 正常放置各种rom,ram
// 最后
define section fill { udata32 0xbeadbead; };
"FILL": place noload at end of ROM_region { section fill };
keep {section fill}; // 填充满整个bin空间
如此,boot的bin大小就被固定在20k。

你要在这里面的某地方填什么标记,数据之类的,你可以用
define symbol FLAG_end_offset = 0x20;                            // 随便举例的地址
define section flag {udata32 0xabcdabcd, 0x12345678;};    // 需要填写的标志,等等
"FLAG": place noload at address (__ICFEDIT_region_ROM_end__ - FLAG_end_offset) { section flag };
define section fill { udata32 0xbeadbead; };
"FILL": place noload at end of ROM_region { section fill };
keep {section flag, section fill};
来设定flag。
然后就可以在 after build的时候copy /b boot.bin+app.bin bootapp.bin 了。

用link来搞这个事情,本来它是工程的一个文件,当然会被版本管理,另外这里面的符号,都可以export出来,整个程序就只依赖这一个地方的设定,而不会c里面一个#define ADDRESS,外面命令行你还需要编写或者告诉操作者这个ADDRESS一定要一致。

留一个完整版作参考。
[mw_shl_code=c,false]/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x08004FFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x20004FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x800;
define symbol __ICFEDIT_size_heap__   = 0x800;
/**** End of ICF editor section. ###ICF###*/

define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readwrite };
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

place in ROM_region   { readonly };
place in RAM_region   { readwrite,
                        block CSTACK, block HEAP };

define symbol FLAG_end_offset = 0x20;
define section flag {udata32 0xabcdabcd, 0x12345678;};
"FLAG": place noload at address (__ICFEDIT_region_ROM_end__ - FLAG_end_offset) { section flag };
define section fill { udata32 0xbeadbead; };
"FILL": place noload at end of ROM_region { section fill };
keep {section flag, section fill};
[/code]
此帖出自单片机论坛

点评

谢谢指点,受教!  详情 回复 发表于 2017-9-15 23:39
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

96

帖子

0

TA的资源

一粒金砂(高级)

12
 
freebsder 发表于 2017-9-15 20:40
升级的其中一个问题就是app的偏移地址的确定,这涉及到符号定位。一旦确定地址,剩下的你以前怎么搞升级 ...

谢谢指点,受教!
此帖出自单片机论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

13
 

楼主,你还有C#写的合并hex的源码吗?想学习下,可以发我邮箱吗1451804815@qq.com   感谢

此帖出自单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表