硬汉嵌入式论坛

 找回密码
 立即注册
查看: 392|回复: 8
收起左侧

[其它] 通过批处理文件拷贝HEX文件并添加版本信息

[复制链接]

1

主题

12

回帖

15

积分

新手上路

积分
15
发表于 2025-7-9 11:31:54 | 显示全部楼层 |阅读模式
本帖最后由 StupidLED 于 2025-7-9 11:44 编辑

用人工智障写了一个用来拷贝HEX文件并且自动添加版本号和计算文件哈希的批处理脚本,感觉挺好用的分享给大家参考一下。


首先是版本信息存放的位置,参考论坛里大佬们的帖子,直接放到了启动文件里面
屏幕截图 2025-07-09 110152.jpg
屏幕截图 2025-07-09 110041.jpg
用的时候直接按照地址读出来就好了
屏幕截图 2025-07-09 110322.jpg
屏幕截图 2025-07-09 110426.jpg

然后就是批处理脚本每次从这里读出版本数据然后加到hex的文件名后面就好了。
[C] 纯文本查看 复制代码
@echo off
setlocal enabledelayedexpansion

:: 配置参数(使用相对路径)
set "SCRIPT_DIR=%~dp0"
set "SOURCE_S_FILE=你的存放路径\startup_gd32f10x_hd.s" 
set "HEX_FILE=.\你的存放路径\你自己的keil项目工程名.hex"
set "TARGET_DIR=.\FirmwareReleases"

:: 检查必需文件是否存在
if not exist "%SCRIPT_DIR%%SOURCE_S_FILE%" (
    echo [ERR] can't find source file: %SOURCE_S_FILE%
    echo full path: %SCRIPT_DIR%%SOURCE_S_FILE%
    goto :pause_exit
)
if not exist "%SCRIPT_DIR%%HEX_FILE%" (
    echo [ERR] can't find hex file: %HEX_FILE%
    echo full path: %SCRIPT_DIR%%HEX_FILE%
    goto :pause_exit
)

:: 从.s文件中提取版本号
set VERSION_HEX=
for /f "usebackq tokens=3" %%i in (`type "%SCRIPT_DIR%%SOURCE_S_FILE%" ^| findstr /i /c:"appFirmwareVersion" /c:"EQU"`) do (
    set "ver_token=%%i"
    if "!ver_token:~0,2!"=="0x" (
        set VERSION_HEX=!ver_token:~2!
        goto :version_found
    )
)

:version_found
if not defined VERSION_HEX (
    echo [ERR] can't find version info
    echo plesase check the source file is include "appFirmwareVersion" and "EQU"
    goto :pause_exit
)

:: 确保版本号是8位十六进制
set "VERSION_HEX=00000000%VERSION_HEX%"
set "VERSION_HEX=!VERSION_HEX:~-8!"

:: 转换BCD编码的版本号
set /a "full_version = 0x!VERSION_HEX!" 2>nul || (
    echo [ERR] version format error: 0x!VERSION_HEX!
    goto :pause_exit
)

:: 提取版本组件
set /a "major = (full_version >> 24) & 0xFF"
set /a "b_version = (full_version >> 16) & 0xFF"
set /a "d_version = full_version & 0xFFFF"

:: 将BCD值转换为十进制
call :convert_bcd major %major%
call :convert_bcd b_version %b_version%

set /a "d_high = (d_version >> 8) & 0xFF"  
set /a "d_low = d_version & 0xFF"          

call :convert_bcd d_high_val %d_high%
call :convert_bcd d_low_val %d_low%

:: 组合为4位十进制数
set /a "d_dec = d_high_val * 100 + d_low_val"
set d_version=!d_dec!


:: 格式化版本字符串
set "major=00%major%"
set "b_version=00%b_version%"
set "d_version=0000%d_version%"
set VERSION_STR=V%major:~-2%B%b_version:~-2%D%d_version:~-4%

:: 创建时间戳(兼容性方法)
for /f "tokens=2 delims==" %%d in ('wmic os get localdatetime /value 2^>nul') do set "datetime=%%d"
if not defined datetime (
    echo [警告] 无法使用WMIC获取时间,使用替代方法
    set "datetime=%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%"
)
set TIMESTAMP=%datetime:~0,8%_%datetime:~8,6%
set TIMESTAMP=%TIMESTAMP: =0%

:: 创建目标目录
if not exist "%SCRIPT_DIR%%TARGET_DIR%" (
    mkdir "%SCRIPT_DIR%%TARGET_DIR%"
)

:: 构造新文件名
for %%F in ("%SCRIPT_DIR%%HEX_FILE%") do (
    set "hex_name=%%~nF"
    set "hex_ext=%%~xF"
)

set "safe_filename=%hex_name%_%VERSION_STR%_%TIMESTAMP%%hex_ext%"
set "safe_filename=%safe_filename::=%"
set "safe_filename=%safe_filename: =_%"
set "safe_filename=%safe_filename:/=_%"
set "safe_filename=%safe_filename:\=_%"

echo caculating hash...
set "hash="
set "hash_file=HASH_%VERSION_STR%.txt"
set "full_hash="

:: 计算完整SHA256哈希值
for /f "delims=" %%h in ('powershell -Command "(Get-FileHash -LiteralPath '%SCRIPT_DIR%%HEX_FILE%' -Algorithm SHA256).Hash" 2^>nul') do (
    set "full_hash=%%h"
)

:: 检查哈希值是否获取成功
if "!full_hash!"=="" (
    echo [ERR] can't get file hash!
    set "full_hash=0000000000000000000000000000000000000000000000000000000000000000"
)

:: 复制文件到目标位置
copy "%SCRIPT_DIR%%HEX_FILE%" "%SCRIPT_DIR%%TARGET_DIR%\%safe_filename%" >nul
if errorlevel 1 (
    echo [ERR] file copy failed!
    echo source file: %SCRIPT_DIR%%HEX_FILE%
    echo target file: %SCRIPT_DIR%%TARGET_DIR%\%safe_filename%
    goto :pause_exit
)

:: 创建哈希文件
echo creating hash file...
echo SHA256: !full_hash! > "%SCRIPT_DIR%%TARGET_DIR%\!hash_file!"
echo File: %safe_filename% >> "%SCRIPT_DIR%%TARGET_DIR%\!hash_file!"
echo Version: %VERSION_STR% >> "%SCRIPT_DIR%%TARGET_DIR%\!hash_file!"
echo Timestamp: %TIMESTAMP% >> "%SCRIPT_DIR%%TARGET_DIR%\!hash_file!"

:: 显示成功信息
echo version code: %VERSION_STR%
echo timestamp: %TIMESTAMP%
echo save file as: %SCRIPT_DIR%%TARGET_DIR%\%safe_filename%
echo hash file: %SCRIPT_DIR%%TARGET_DIR%\!hash_file!
goto :pause_exit

:: BCD转十进制函数
:convert_bcd
setlocal
set "value=%~2"
set /a "high = (value >> 4) * 10"
set /a "low = value & 0xF"
set /a "dec = high + low"
endlocal & set "%~1=%dec%"
exit /b


:: 暂停并退出
:pause_exit
echo.
echo Press any key to exit...
pause >nul
endlocal
exit /b



用的时候记得改一下你的启动文件和hex文件的路径,按实际情况就可以

然后我是习惯把这个放到keil里面直接编译完调用
屏幕截图 2025-07-09 110529.jpg

最后是关于时间戳和哈希码,由于我这个只是公司内部同事软件测试的时候标记版本用的,就没有用编译时间(不会用,求指导),只是简单把拷贝文件的时间添加到文件名里面,然后按照版本生成一个hex文件的哈希值,暂时不知道可以拿来干嘛。。。。。。

效果
95ec14424c062852fa5561d53047d78.png
9639c03404b5ee338237d502ab52389.png

最后是想请教一下论坛的各位巨佬,是怎么搞这种输出文档的版本信息的管理的,GCC的话是不是用makefile搞?想学习一下


回复

使用道具 举报

4

主题

1459

回帖

1471

积分

至尊会员

积分
1471
发表于 2025-7-9 12:41:18 | 显示全部楼层
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2025-7-9 13:59:40 | 显示全部楼层
回复

使用道具 举报

0

主题

49

回帖

49

积分

初级会员

积分
49
发表于 2025-7-9 15:41:00 | 显示全部楼层
makefile 的话很简单,直接调用 git 命令生成版本信息然后被 c 程序使用,譬如这个:

https://github.com/dukelec/cdbus ... /fw_bridge/Makefile

另有项目需要加密,也是 makefile 里面调用一个外部 python 脚本,make 的时候就会自动生成加密的 hex 固件
回复

使用道具 举报

1

主题

12

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2025-7-10 10:02:44 | 显示全部楼层
dukelec 发表于 2025-7-9 15:41
makefile 的话很简单,直接调用 git 命令生成版本信息然后被 c 程序使用,譬如这个:

https://github.co ...

看了一下是
[C] 纯文本查看 复制代码
GIT_VERSION := $(shell git describe --dirty --always --tags)

这里把git的版本号读取出来,然后
[C] 纯文本查看 复制代码
# C defines
C_DEFS =  \
-DUSE_STDPERIPH_DRIVER \
-DAT32F405KCU7_4 \
-DOTG_USE_DMA \
-DSW_VER=\"$(GIT_VERSION)\"


这里丢到宏定义里面。然后在程序里面写到固定位置就OK了?
这样确实会方便很多,而且不用自己手动去改。
回复

使用道具 举报

1

主题

12

回帖

15

积分

新手上路

积分
15
 楼主| 发表于 2025-7-10 10:21:03 | 显示全部楼层
dukelec 发表于 2025-7-9 15:41
makefile 的话很简单,直接调用 git 命令生成版本信息然后被 c 程序使用,譬如这个:

https://github.co ...

这样的话用makefile也可以像加版本号一样把编译时间写到flash里面,确实是方便啊。就是现在用的GD的芯片,搭建GCC环境比较麻烦,官方连GCC的启动文件这些都没有,整的有点头大
回复

使用道具 举报

6

主题

306

回帖

324

积分

高级会员

积分
324
发表于 2025-7-10 10:46:45 | 显示全部楼层
思路挺好,用保留的中断,填充版本号

这是我的版本管理,每次编译时,自动更新日期时间,然后软件读取显示出来,效果还行,但缺点是每次必须完整编译,
不过正常发版都是完整编译的也没问题。

[C] 纯文本查看 复制代码
//编译日期及时间
volatile static const char * BUILD_DATE  =__DATE__;	
volatile static const char * BUILD_TIME  =__TIME__;	
回复

使用道具 举报

12

主题

63

回帖

99

积分

初级会员

积分
99
发表于 2025-7-10 11:43:38 | 显示全部楼层
这个是之前写的,可以看看
我这个是使用.h文件里面的版本号
这个是多项目版本同时更新,使用编译时间作为文件后缀
https://forum.anfulai.cn/forum.p ... d=126114&extra=
回复

使用道具 举报

0

主题

51

回帖

51

积分

初级会员

积分
51
发表于 2025-7-10 11:46:11 | 显示全部楼层
fxyc87 发表于 2025-7-10 10:46
思路挺好,用保留的中断,填充版本号

这是我的版本管理,每次编译时,自动更新日期时间,然后软件读取显 ...

KEIL里可以设置保存这个信息的文件每次都参与编译

回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-11 23:53 , Processed in 0.075819 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表