C语言 如何链接数据在ELF文件中显示在运行时?STM32



我被卡住了,试图让我的FW版本显示在运行时

我已经尝试使用的例子从gcc是否有任何选项在ELF二进制文件中添加版本信息?但是没有运气。以下是我目前所掌握的信息。

在STM32CubeIDE (MacOS)上使用STM32L462

内部源文件:

static uint32_t git_commit __attribute__((section(".gitcommit"))) = 0xffffffff;
static uint32_t version_number __attribute__((section(".version"))) =
0xffffffff;

在我的应用程序文件夹中,我有一个version_number.txt,其中包含版本号(现在是1.0.0)

一旦代码成功复制,一个python脚本就会运行,它从version_number.txt中获取版本号和git提交的哈希值,并使用objcopy将它们放入elf节中。

"""This script get git commit and version number and push it to STM32 elf and bin
file into specific section"""
import sys
import subprocess
import os
import binascii
import struct
import platform
def write_to_file_binary(file_name, data):
"""write data to binary file"""
with open(file_name, 'w+b') as file_obj:
data = binascii.unhexlify("0" + data)
file_obj.write(data)
def get_git_revision_short_hash(dir_path):
"""get git commit number"""
return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], cwd=dir_path)
def write_version_to_binary_file(version_array, file_path):
"""write version major minor patch commit to binary file"""
version_major = version_array[0]
version_minor = version_array[1]
version_patch = version_array[2]
with open(file_path, 'w+b') as file_obj:
file_obj.write(struct.pack("B", int(version_major)))
file_obj.write(struct.pack("B", int(version_minor)))
file_obj.write(struct.pack("H", int(version_patch)))
def main(args):
"""This script connects to git and get the commit number of the project and write it
to commit_number_file.txt,
Then get the project version number from version_number.txt.
Write binary to temp.txt file the version number and git commit number.
Access to elf file and push git commit to .gitcommit and git version to .version section.
Change the bin file.
Change bin file name to contains version number and git commit number.
"""
path_name = args[1]
project_name = os.path.split(path_name)[-1]
print("project name:" + project_name)
debug_path_in_project = path_name + "/Debug"
git_commit_number = get_git_revision_short_hash(path_name)[:-1].decode()
commit_file_name = "commit_number_file.txt"
commit_file_path = debug_path_in_project + "/" + commit_file_name
write_to_file_binary(commit_file_path, git_commit_number)
version_array = open(path_name + "/version_number.txt", "r").readline().split('.')
version_file_temp = debug_path_in_project + "/temp.txt"
print(version_file_temp)
write_version_to_binary_file(version_array, version_file_temp)
version = version_array[0] + '.' + version_array[1] + '.' + version_array[2] + 
'.' + git_commit_number
print("version: " + version)
if(platform.system() == 'Darwin'):
out = subprocess.check_output(['arm-none-eabi-objcopy', '--update-section', '.gitcommit=' + 
commit_file_name, project_name + '.elf'], cwd=debug_path_in_project)
print("out1:" ,out)
out = subprocess.check_output(['arm-none-eabi-objcopy', '--update-section', '.version=' + 
version_file_temp, project_name + '.elf'], cwd=debug_path_in_project)
print("out2:" ,out)
out = subprocess.check_output(['arm-none-eabi-objcopy', '-O', 'binary', project_name + '.elf', 
project_name + '.bin'], cwd=debug_path_in_project)
print("out3:" ,out)
if(platform.system() == 'Windows'):
subprocess.check_output(['arm-none-eabi-objcopy.exe', '--update-section', '.gitcommit=' + 
commit_file_name, project_name + '.elf'], cwd=debug_path_in_project)
subprocess.check_output(['arm-none-eabi-objcopy.exe', '--update-section', '.version=' + 
version_file_temp, project_name + '.elf'], cwd=debug_path_in_project)
subprocess.check_output(['arm-none-eabi-objcopy.exe', '-O', 'binary', project_name + '.elf', 
project_name + '.bin'], cwd=debug_path_in_project)
list_of_files_in_directory = os.listdir(debug_path_in_project)
for file_in_list in list_of_files_in_directory:
if file_in_list != (project_name + '.bin'):
if file_in_list.endswith('.bin') and file_in_list is not project_name + '.bin':
os.remove(file_in_list)
os.rename(project_name + '.bin', project_name + '_' + version  + '.bin')
os.remove(version_file_temp)
os.remove(commit_file_path)
if __name__ == '__main__':
main(sys.argv)

脚本完成后,我可以运行

objdump -s -j .gitcommit /Users/path/to/elf/Application.elf
objdump -s -j .version /Users/path/to/elf/Application.elf

输出将匹配git提交和version_number.txt中列出的版本(改变txt中的数字将改变objdump的输出)。

但是,在运行时,当我试图获取version_number

的值时git_commit我只得到默认的垃圾值。 运行:

software_version.major = version_number;
software_version.minor = version_number >> 8;
software_version.patch = version_number >> 16;
software_version.commit = SWAP32(git_commit);

不工作

欢迎任何想法!谢谢你!

对于感兴趣的人,
将以下行添加到STM32L4

.gitcommit :
{
. = ALIGN(4);
KEEP (*(.gitcommit))         /* .gitcommit sections (constants, strings, etc.) */
KEEP (*(.gitcommit*))        /* .gitcommit* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.version :
{
. = ALIGN(4);
KEEP (*(.version))         /* .version sections (constants, strings, etc.) */
KEEP (*(.version*))        /* .version* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH

完整的解释-如何有版本号和git提交保存在flash (STM32):

应用程序文件夹内:

将版本号保存在version_number.txt文件中每个版本更新,更新文本文件。


声明保存git-commit和版本号的变量,如下所示(可以随意更改节名,但要确保与名称一致)
static uint32_t git_commit __attribute__((section(".gitcommit"))) = 0xffffffff;
static uint32_t version_number __attribute__((section(".version"))) =
0xffffffff;

链接文件(STM32

使用老式的makefiles和xxd命令将提交转换为二进制文件来简化一下

GIT_TARGET = commit.bin
$(GIT_TARGET):
@echo $(shell git rev-parse HEAD) | xxd -r -p > $@
...
main.elf: $(OBJ) $(GIT_COMMIT)
@$(CC) $(LDFLAGS) -Wl,-Map=$(notdir $(patsubst %.elf,%.map,$@)) -o $@ $(OBJ)
@$(OBJCOPY) --update-section .git_commit=$(GIT_TARGET) $@
...

在链接器脚本

上使用这些行
...
/* Constant data into "ROM" Rom type memory */
.rodata :
{
. = ALIGN(4);
*(.rodata)         /* .rodata sections (constants, strings, etc.) */
*(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.git_commit :
{
. = ALIGN(4);
KEEP (*(.git_commit))         /* .git_commit sections (constants, strings, etc.) */
KEEP (*(.git_commit*))        /* .git_commit* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
...

并配置源

中的变量
...
#define COMMIT_SIZE 20
uint8_t git_commit[COMMIT_SIZE] __attribute__((section(".git_commit")));
...

最新更新