自动以版本号命名keil生成的bin文件
Posted NULL_1969
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自动以版本号命名keil生成的bin文件相关的知识,希望对你有一定的参考价值。
0、 前言
在做项目中一直遇到一个小问题。一直也没管,最近花了点时间处理了,效果还不错。问题是这样的:每次编译后的生成的bin文件需要给客户,烧录到设备里进行更新。每次生成的bin文件都是固定的文件名,发给客户前,需要人为将bin文件改为vx.x.x.bin再发送。这一步需要人工命名,虽然花不了几分钟,但是还是觉得体验不太好,因为如果一次编译的版本多的话,人容易命名出现纰漏。所以如果能生成bin文件后,自动进行重命名,那可靠性比人工高多了。
1、方案:
仔细想了下,以及跟同事交流后,主要有两种方案:
方案一,编写一个可执行文件,来读取keil项目中的.c .h文件,找到其中的版本号信息,然后自动将版本号信息填写到生成bin文件名称中。
方案二,将版本号信息,写入bin文件的固定地址。然后编写一个可执行文件,来读取bin文件固定地址的版本号信息。最后将读到的版本号信息,写入生成的bin文件名称中。
最优的方案是方案一,但是难度比较大,兼容性较差,不利于移植到其他项目,还没想好如何实现。方案二兼容性更强,不过需要修改项目文件,将版本信息写入bin文件的固定地址。实现更为简单。
本次是基于方案二的实现。
2、版本号写入bin文件固定地址
写入固定地址的方式其实很简单。只需要在main函数前面添加1行代码即可
uint16_t version_addr[3] __attribute__((at(0x8010000))) = MAIN_VERSION_MAJOR,MAIN_VERSION_MINOR,MAIN_VERSION_BUILD;
这句话的意思是将version_addr数组写入到固定地址为0x8050000,其内容是版本号,版本号每个字段占2个字节。为什么要用两个字节来表示,主要是考虑到兼容性,一个字节最多是255,假如有个版本号是1.2.300,那么每个字段用一字节表示,就无法满足需求。
0x8050000是stm32的flash地址,那么对应bin文件的偏移地址是多少呢?已知stm32 内部flash的首地址是0x8000000,0x10000是偏移地址,bin文件地址是从0开始,则bin文件的0x10000开始就是version_addr数据。
下面验证下。
当前的
MAIN_VERSION_MAJOR 4
MAIN_VERSION_MINOR 2
MAIN_VERSION_BUILD 50
bin文件的0x10000地址后面的数据是0x0004 0x0002 0x0035,35十进制是50。
接下来的可执行文件只需要读取到这个地址的数据,然后重命名bin文件即可。
3、重命名bin文件
对于重命名的可执行文件,需要知道2个信息。
其一:生成的bin文件的路径
其二:版本信息的偏移地址
对于版本号而言,最好加上前缀,可以是公司简称,设备简称。比如abc_v1.1.1.bin这种形式。
所以要实现比较完成的名称,还需要告知可执行文件,版本号的前缀。
这san个信息可以抽象成可执行文件的3个输入参数。
比如:version.exe aa/bb/cc/dd.bin 0x10000 abc_v
可执行文件实现原理见后文。这里先说下操作方式。在keil的项目options里面按照Run #2输入,实际上就是上文说的可执行的3个参数。
编译以后生成效果如下:
可以看到,确实生成了对应的版本号。
至此功能全部实现,bin_read.exe下载链接如下:
https://download.csdn.net/download/sinat_36568888/87621034
4、bin_read.exe源码
bin_read源码采用c编写,编译采用gcc编译器,源码如下:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
/**
* @description: 获取当前文件所在的路径
* @return *
* @Date: 2023-03-24 17:01:37
* 比如aa/bb/cc/123.bin,则返回的路径是aa/bb/cc
* 目的是为了后面修改新的文件名称
*/
int get_file_dir(char*filename, char*file_dir)
int res = 0;
char *file_name = strrchr(filename, '/');
if(file_name != NULL)
int file_dir_len =strlen(filename)-strlen(file_name) ;
printf("file dir len: %d\\r\\n", file_dir_len);
memcpy(file_dir, filename, strlen(filename)-strlen(file_name));
file_dir[file_dir_len] = '\\0';
printf("file dir:%s\\r\\n", file_dir);
res = 0;
else
res = 1;
return res;
char file_dir[256] = 0;
char new_name[24] = 0;
char new_file_name[24] = 0;
int main(int argc, char **argv)
int rename_res = 0;
FILE *fp;
uint16_t buf[10]=0;
// printf("%s\\r\\n", argv[1]);
fp = fopen(argv[1], "rb");
if(fp == NULL)
printf("Error: file open failed\\r\\n");
return 1;
uint32_t version_addr = strtol(argv[3],NULL,16);
fseek(fp, version_addr, SEEK_SET);
uint16_t len = fread(buf,2,3,fp);
printf("len:%d data:",len);
for(int i =0;i<len;i++)
printf("%02X ",buf[i]);
sprintf(new_name,"%s%d.%d.%d.bin",argv[2],buf[0],buf[1],buf[2]);
printf("\\r\\n");
fclose(fp);
int ret = get_file_dir(argv[1],file_dir);
if(ret ==0)//文件不在当前目录
sprintf(new_file_name,"%s/%s",file_dir,new_name);
else
sprintf(new_file_name,"%s",new_name);
remove(new_file_name);
rename_res = rename(argv[1],new_file_name); //如果修改后的名称不加路径,rename函数就会把命名后的文件移动到当前的根目录
printf("new name:%s\\r\\n",new_file_name);
printf("res = %d\\r\\n",rename_res);
编译,win下打开powershell,在read_bin.c目录下,输入
gcc bin_read.c -o bin_read.exe
想自己研究的,可以直接编译源码。不想研究的,下载可执行文件即可使用。
windows下配置gcc编译环境请参考:
https://blog.csdn.net/sinat_36568888/article/details/129091766
keil_v5生成.bin文件方法
按ALT+F7,打开如下对话框
如上图,选择 After Build/ Rebuild下的Run#1,输入:
C:/keil_v5/ARM/ARMCC/bin/fromelf.exe -bin -o uart.bin ./Objects/uart.axf
与之前版本不同,Keil V5之后的版本,fromelf.exe在 C:\\Keil_v5\\ARM\\ARMCC\\bin 目录下。Keil V4是在:/Keil/ARM/BIN40/下。
注意:axf文件目录,不同的工程设置可能会不同,我的是在Objects目录下,所以
./Objects/uart.axf
#done
以上是关于自动以版本号命名keil生成的bin文件的主要内容,如果未能解决你的问题,请参考以下文章
STM32-关于Proteus 仿真无法运行STM32CubeMX自动生成的代码