有这样一种需求,在做OTA升级文件时需要根据本地编译生成的bin文件计算出一个头信息加再本地编译生成的bin文件头部组成一个新的bin文件放在服务器上,下面c语言是我写的一个例子。
// filename: make_ota_bin.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define HRADER_FLAG 0xaa55aa55
#define TAIL_FLAG 0x55aa55aa
#define FILE_TYPE ".bin"
typedef struct
{
unsigned int header_flag;//0xaa55aa55
unsigned int sw_version;//sofrware version
unsigned int bin_len;
unsigned int bin_sum;
unsigned int head_sum;//header_flag + sw_version + bin_len + bin_sum
unsigned int tail_flag;//0x55aa55aa
}BOOTLOADER_UPDATE_FILE_HDR_S;
int main(int argc,char* argv[])
{
if(argc<3 || argc>4)
{
printf("参数个数错误 例子:bin文件名 主版本号.子版本号 [生成ota文件名字](可选)\n");
printf("./make_ota_bin.o xxx.bin 1.0 [ota.bin]\n");
return 0;
}
char* file_name = argv[1];
if( strcmp(file_name+strlen(file_name)-strlen(FILE_TYPE),FILE_TYPE) !=0)
{
printf("bin文件名后缀错误\n");
return 0;
}
char* main_ver=NULL;char* sub_ver =NULL;
main_ver = argv[2];
sub_ver = strchr(argv[2],'.');
char * create_file_name =NULL;
if(argc ==4)
{
create_file_name = argv[3];
if( strcmp(create_file_name+strlen(create_file_name)-strlen(FILE_TYPE),FILE_TYPE) !=0)
{
printf("生成ota文件名字后缀错误\n");
return 0;
}
}
BOOTLOADER_UPDATE_FILE_HDR_S ota_header={0};
ota_header.header_flag = HRADER_FLAG;
ota_header.tail_flag = TAIL_FLAG;
if(sub_ver == NULL)
{
printf("sw_version param err --> main_ver.sub_ver\n");
return 0;
}
sub_ver++;
ota_header.sw_version = (atol(main_ver)<<16) |atol(sub_ver);
printf("sw_version %02d.%02d\n",(ota_header.sw_version&0xFFFF0000)>>16,(ota_header.sw_version&0xFFFF));
printf("bin name :%s \n",file_name);
FILE *fp_bin = fopen(file_name,"rb");
FILE * fp_out=NULL;
if(fp_bin == NULL)
{
printf("open file err\n");
return 0;
}
if(fseek(fp_bin,0,SEEK_END) != 0)
{
printf("fseek file err\n");
goto exit;
}
ota_header.bin_len = ftell(fp_bin);
printf("bin size :%d-hex(%x)\n",ota_header.bin_len,ota_header.bin_len);
int retry;
retry =0 ;
lp_retry:
fseek(fp_bin,0,SEEK_SET);
unsigned char dat;
int i=0;ota_header.head_sum=0; int ret=0;
while( (ret = fread(&dat,1,1,fp_bin)) !=0)
{
if(ret == 1)
{
i++;
ota_header.bin_sum += dat;
retry = 0;
}
else
{
printf("fread err retry %d\n",retry);
retry++;
if(retry <10)
goto lp_retry;
else
goto exit;
}
}
if(i!=ota_header.bin_len)
{
printf("read err\n");
goto exit;
}
printf("read done\n");
ota_header.head_sum = ota_header.header_flag + ota_header.sw_version + ota_header.bin_len + ota_header.bin_sum;
/*
printf("#########bin header info#######\n");
printf("header_flag : %X\n",ota_header.header_flag);
printf("sw_version : %X\n",ota_header.sw_version);
printf("bin_len : %X\n",ota_header.bin_len);
printf("bin_sum : %X\n",ota_header.bin_sum);
printf("head_sum : %X\n",ota_header.head_sum);
printf("tail_flag : %X\n",ota_header.tail_flag);
printf("##############################\n");
printf("%d\n",sizeof(BOOTLOADER_UPDATE_FILE_HDR_S));
*/
char *ota_file_name=NULL;
if(argc == 3)
ota_file_name = calloc(strlen("ota_")+strlen(file_name)+1,sizeof(char));
else if(argc == 4 && create_file_name!= NULL)
ota_file_name = calloc(strlen(create_file_name)+1,sizeof(char));
if(ota_file_name == NULL)
{
printf("ota_file_name zalloc fail\r\n");
goto exit;
}
if(argc == 3)
{
sprintf(ota_file_name,"ota_%s",file_name);
}
else if(argc ==4)
{
memcpy(ota_file_name,create_file_name,strlen(create_file_name));
}
printf("create ota name: %s\n",ota_file_name);
fp_out = fopen(ota_file_name,"wb+");
if(fp_out == NULL)
{
printf("无法打开 %s\n",ota_file_name);
goto exit;
}
retry = 0;ret = 0;
lp1_retry:
fseek(fp_out,0,SEEK_SET);
if( (ret = fwrite(&ota_header,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S),1,fp_out)) != 1 )
{
printf("fwrite ota header retry %d\n",retry);
retry++;
if(retry<10)
goto lp1_retry;
else
goto exit;
}
int retry_ota=0;
lp2_retry:
i=0;dat=0;retry =0;ret =0;retry_ota = 0;
fseek(fp_out,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S),SEEK_SET);
fseek(fp_bin,0,SEEK_SET);
while( i < ota_header.bin_len)
{
if( (ret = fread(&dat,1,1,fp_bin)) == 1)
{
retry = 0;
if( (ret = fwrite(&dat,1,1,fp_out)) ==1 )
{
retry_ota = 0;
i++;
}
else
{
printf("fwrite %s err %d\n",ota_file_name,retry_ota);
retry_ota++;
if(retry_ota<10)
goto lp2_retry;
else
goto exit;
}
}
else
{
printf("fread %s err %d\n",file_name,retry);
retry++;
if(retry<10)
goto lp2_retry;
else
goto exit;
}
}
if(fseek(fp_out,0,SEEK_END) != 0)
{
printf("fseek file err\n");
goto exit;
}
unsigned int out_bin_num = ftell(fp_out);
if( out_bin_num != (ota_header.bin_len) + sizeof(BOOTLOADER_UPDATE_FILE_HDR_S))
{
printf("create ota file fail !!!\n");
goto exit;
}
retry=0;BOOTLOADER_UPDATE_FILE_HDR_S ota_header_bak;
lp3_retry:
fseek(fp_out,0,SEEK_SET);
memset(&ota_header_bak,0,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S));
fread(&ota_header_bak,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S),1,fp_out);
if(memcmp(&ota_header_bak,&ota_header,sizeof(BOOTLOADER_UPDATE_FILE_HDR_S)) != 0)
{
printf("create ota file haeder err !!!\n");
goto exit;
}
printf("######### %s info ############\n",ota_file_name);
printf("header_flag: %X\n",ota_header.header_flag);
printf("sw_version : %X\n",ota_header.sw_version);
printf("bin_len : %X\n",ota_header.bin_len);
printf("bin_sum : %X\n",ota_header.bin_sum);
printf("head_sum : %X\n",ota_header.head_sum);
printf("tail_flag : %X\n",ota_header.tail_flag);
printf("###############################\n");
printf("create ota file success !!!\n");
exit:
if(ota_file_name !=NULL)
{
free(ota_file_name);ota_file_name =NULL;
}
if(fp_out != NULL)
fclose(fp_out);
if(fp_bin != NULL)
fclose(fp_bin);
return 0;
}
make_ota_bin.c 和要升级的bin文件放在同一级目录下如下图执行
用二进制对比文件可以看见新生成的bin添加了头部信息,而其他部分一样