如何将数据插入到 MCU 的已编译二进制文件中
How to insert data into compiled binary for MCU
我正在尝试将我的部分二进制文件的 md5 哈希值插入到二进制文件中,以跟踪 MCU 固件版本。
我是这样处理的:
在 link 脚本中,我将闪光灯分成两部分
MEMORY
{
FLASH0 (rx) : ORIGIN = 0x8000000, LENGTH = 64K - 16
FLASH1 (r) : ORIGIN = 0x800FFF0, LENGTH = 16
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
}
然后我指定了一个输出部分,如下所示:
.fw_version :
{
KEEP(*(.fw_version))
} >FLASH1
接下来我的 firmware_version.c 文件只包含:
#define FW_VERSION_SIZE 16
const unsigned char FW_VERSION[FW_VERSION_SIZE]
__attribute__((section(".fw_version"), used)) = {0};
然后在编译二进制文件并使用 objcopy 创建一个 .bin 文件后,我有一个 65536 B 的大文件,我将该文件拆分为 65520 字节,对第一部分进行 md5 校验和并将其插入到第二部分(16 B)。最后我做了 cat parta partb > final.bin
.
当我用 hexdump 检查这个二进制文件时,我可以看到 md5 校验和确实在最后。
使用 objdump -h
我得到:
...
8 .fw_version 00000010 0800fff0 0800fff0 00017ff0 2**2
...
和objdump -t
给出:
...
0800fff0 g O .fw_version 00000010 FW_VERSION
...
我认为这意味着我可以只使用 FW_VERSION[i]
从 mcu fw 中获取 md5 校验和的第 i 部分,但是当我检查 gdb 中的内存时,我发现它已经全部清零了从未改变。
我在这里错过了什么?
[edit] 该设备是通过 gdb 编程的 stm32f030c8t6 arm cortex m0。
就像我在问题下评论的那样,我发现它不起作用的(一个)原因是当我在使用 gdb 编程时加载 .elf 文件时操作 .bin 文件。
如果我使用编程器或引导加载程序将 .bin 文件下载到目标,它应该(可能)有效。
虽然我找到了更好的(我认为)方法。
- 将项目中的所有源代码编译为.o 文件。
- cat *.o > /tmp/tmp.something_unique。我在 Makefile
中使用了 $(shell mktemp)
- openssl dgst -md5 -binary /tmp/tmp.something_unique > version_file
- objcopy -I binary -O elf32-littlearm -B arm version_file v_file.o
- link脚本有一段
.fw_version : { KEEP(v_file.o(.data)) } >FLASH1
- link申请
- 在应用程序中通过
extern unsigned char _binary_version_file_start; uint8_t *FW_VERSION = &_binary_version_file_start; const size_t FW_VERSION_SIZE = (size_t) &_binary_version_file_size;
获取版本号的地址。请注意 &
的用法是正确的。
这将导致校验和接管从源代码编译的所有对象,然后将此校验和link编辑到目标中闪烁的二进制文件中。
我正在尝试将我的部分二进制文件的 md5 哈希值插入到二进制文件中,以跟踪 MCU 固件版本。
我是这样处理的: 在 link 脚本中,我将闪光灯分成两部分
MEMORY
{
FLASH0 (rx) : ORIGIN = 0x8000000, LENGTH = 64K - 16
FLASH1 (r) : ORIGIN = 0x800FFF0, LENGTH = 16
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
}
然后我指定了一个输出部分,如下所示:
.fw_version :
{
KEEP(*(.fw_version))
} >FLASH1
接下来我的 firmware_version.c 文件只包含:
#define FW_VERSION_SIZE 16
const unsigned char FW_VERSION[FW_VERSION_SIZE]
__attribute__((section(".fw_version"), used)) = {0};
然后在编译二进制文件并使用 objcopy 创建一个 .bin 文件后,我有一个 65536 B 的大文件,我将该文件拆分为 65520 字节,对第一部分进行 md5 校验和并将其插入到第二部分(16 B)。最后我做了 cat parta partb > final.bin
.
当我用 hexdump 检查这个二进制文件时,我可以看到 md5 校验和确实在最后。
使用 objdump -h
我得到:
...
8 .fw_version 00000010 0800fff0 0800fff0 00017ff0 2**2
...
和objdump -t
给出:
...
0800fff0 g O .fw_version 00000010 FW_VERSION
...
我认为这意味着我可以只使用 FW_VERSION[i]
从 mcu fw 中获取 md5 校验和的第 i 部分,但是当我检查 gdb 中的内存时,我发现它已经全部清零了从未改变。
我在这里错过了什么?
[edit] 该设备是通过 gdb 编程的 stm32f030c8t6 arm cortex m0。
就像我在问题下评论的那样,我发现它不起作用的(一个)原因是当我在使用 gdb 编程时加载 .elf 文件时操作 .bin 文件。 如果我使用编程器或引导加载程序将 .bin 文件下载到目标,它应该(可能)有效。
虽然我找到了更好的(我认为)方法。
- 将项目中的所有源代码编译为.o 文件。
- cat *.o > /tmp/tmp.something_unique。我在 Makefile 中使用了 $(shell mktemp)
- openssl dgst -md5 -binary /tmp/tmp.something_unique > version_file
- objcopy -I binary -O elf32-littlearm -B arm version_file v_file.o
- link脚本有一段
.fw_version : { KEEP(v_file.o(.data)) } >FLASH1
- link申请
- 在应用程序中通过
extern unsigned char _binary_version_file_start; uint8_t *FW_VERSION = &_binary_version_file_start; const size_t FW_VERSION_SIZE = (size_t) &_binary_version_file_size;
获取版本号的地址。请注意&
的用法是正确的。
这将导致校验和接管从源代码编译的所有对象,然后将此校验和link编辑到目标中闪烁的二进制文件中。