? ? ? ? 做为嵌入式行业从业者,我想大家对bin文件肯定是不陌生的。从嵌入式程序来看,它就是我们实际的代码数据。当然我们还经常用到另外一种格式,hex文件。使用过keil的朋友肯定非常熟悉啦。一般我们使用stlink等下载工具用的就是这种格式。它们之间有什么区别呢?网上介绍的资料非常多,这不是我这篇文章要讨论的话题,不过我还是简单说一下,hex文件比bin文件大,前者包含了地址相关信息,存储的是ASCII格式内容,后者就是只包含程序数据,存储的是二进制格式内容。
? ? ? ? 不知道大家有没有做过在线升级的功能,俗称IAP;具体一点,IAP是In Application Programming的首字母缩写,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。我在项目中用到的还是比较多的,这里就会涉及bootloader程序和app程序两个,当我们准备好了这两个程序的时候,要一起烧入到mcu里面去,当然你也可以先烧入bootloader程序,在通过相关接口(比如串口等)去烧入app程序。我们就以第一种情况为例来讨论(当然实际也有很多其他情况需要用到)。假如我们要发两个程序去烧入,你可以是两个hex文件,不过这里我们讨论都是bin文件,那么你就要提供app的偏移地址数据,那有时候我们不想提供,有没有什么办法把两个bin合成一个bin在发过去烧入呢,肯定有,网上也有一些小软件可以下载。不过这种功能咱们自己是不是可以写个小工具自己去实现呢,是否更有意思?这里我提供一个小的代码供大家参考,大家可以在源码里添加更多的功能满足自己的需求。源码非常简洁不需要过多的解释,直接上代码。
#include<stdio.h>
int getFileLength(char const * filename)
{
FILE * fp = NULL;
int length = 0;
fp = fopen(filename,"r");
if(fp == NULL){
printf("open error");
return -1;
}
fseek(fp,0,SEEK_END);
length = ftell(fp);
fclose(fp);
return length;
}
int main(void)
{
int i = 0;
int ret = 0;
FILE *fp = NULL;
unsigned char buff[100*1024];
int filesize1 = getFileLength("bootloader.bin");
int filesize2 = getFileLength("app.bin");
int offset = 0;
/*输入并获取偏移地址,十六进制模式*/
printf("please input offset addr:");
scanf("%x",&offset);
/*获取BootLoader数据*/
fp = fopen("bootloader.bin","r");
if(fp == NULL){
printf("open error");
return 0;
}
ret = fread(buff,1,filesize1,fp);
if(ret != filesize1){
printf("read error");
}
fclose(fp);
/*获取app数据*/
fp = fopen("app.bin","r");
if(fp == NULL){
printf("open error");
return 0;
}
ret = fread(buff+filesize1+offset,1,filesize2,fp);
if(ret != filesize2){
printf("read error");
}
fclose(fp);
/*合并写入新的bin文件*/
fp = fopen("merge.bin","w");
if(fp == NULL){
printf("open error");
return 0;
}
ret = fwrite(buff,1,filesize1+offset+filesize2,fp);
if(ret != filesize1+offset+filesize2){
printf("write error");
}
fclose(fp);
return 0;
}
|