在Linux上将*.hex转换为*.bin用于ARM

12
我想使用st-flash命令将程序上传到我的STM32F4 Discovery板。问题是当我尝试上传*.hex或*.elf文件时,它就无法工作。我尝试了许多方法(比如使用xxd)将*.elf或*.hex转换为*.bin,但当我上传时它仍然无法工作。是的,我尝试从其他Windows电脑上传hex文件,它可以工作。
Hex文件示例(前三行只是为了向您展示内部的样子):
:020000040800F2
:100000000000022099020008A1020008A5020008D1
:10001000A9020008AD020008B102000800000000BB

我的操作系统是Ubuntu 14.04 LTS。

感谢您的帮助!

5个回答

18

我假设您已经安装了Linux和binutils,所以您只需执行以下操作:

objcopy --input-target=ihex --output-target=binary code00.hex code00.bin

1
注意:这会破坏加载基地址。但对于 OP 的情况,它可以工作,因为 ihex 数据字节从 0000 开始。此外,任何工具链都适用于此操作,不一定是 ARM。 - ulidtko
2
@ulidtko:1. 这个问题是针对ARM的,因此答案也是针对ARM的;2. bin文件不包含您声称会混乱的加载基地址。您在加载.bin文件时指定地址即可。 - A. Genchev
2
你如何更改起始段地址?我不想让它以0x00000000为基础,而是以0x80000000为例。 - Brandon Ros
这将复制到原始(裸机)二进制文件,而不是ELF格式。 - Michał Leon

2
你是否考虑过使用arm-none-linux-gnueabi-objcopy(或类似工具)代替xxd?这在任何ARM工具链中都可以找到。

是的,我做过,但有可能我做错了。现在我离开了电脑(使用手机发布)。我记得我使用了类似于 arm-none-eabi-objcopy myhex.hex -O binary mybin.bin 的命令,但现在我不确定了。等我回家后会告诉你的。 - Jacajack
好的,我现在可以访问我的电脑了。所以我尝试了两个选项:arm-none-eabi-objcopy "F4 Discovery test.elf" -Obinary "out.bin"arm-none-eabi-objcopy "F4 Discovery test.elf" -Oihex "newout.bin" - 至少对我来说它们都不起作用。我正在尝试理解OpenOCD,我已经上传了我的*.hex文件并且它可以运行... - Jacajack
也许你需要将它命名为以.hex结尾的文件。 - Luis Colorado

2

.hex文件格式已经在网络上有文档。你需要一个能够理解这种格式的加载程序,因为它具有控制加载过程的多种寄存器。其中一些寄存器用于控制入口点地址,而其他一些则是要加载到某个固定地址的数据。

您可以在维基百科上获得有关Intel Hex格式(也称为IHEX)的信息。如果所有数据都在一个段中且没有指定入口点,则理论上可以将其转换为要加载的二进制数据,但这是不太可能的。

它是一个由以“:”字符开头的行组成的文本文件,然后是表示此记录具有的数据字节数的两个字段十六进制数字,然后是要加载此数据的地址,然后是文件类型,可以是以下之一:

  • 00 这个值是一堆数据,通常是16个字节(0x10)
  • 01 文件结尾。它没有数据,因此始终被编码为::00000001FF
  • 02 扩展段地址,以允许具有超过16位的地址。
  • 03 启动入口点地址,以在0x86体系结构中注册初始CS:IP地址。
  • 04 扩展线性地址,以指定32位地址。这指定了00寄存器的上16位地址部分。
  • 05 启动线性入口点地址。这是32位线性入口点地址。

然后是n个字节(n是第一个字段的值)的数据(十六进制编码),最后是一个校验和字节(从冒号到所有记录字节的二进制补码之和)。


1
那么你对我有什么建议?我之前使用的是 st-flash write bingotfromhex.bin 0x8000000。我正在逐步学习openOCD,以便上传*.elf文件。感谢您解释hex文件的工作原理! - Jacajack
1
我不知道。Intel hex格式是一种通用的、非常广泛的格式。我不使用ARM。我不能给你更多的帮助。抱歉。也许你需要使用一个选项来解析hex文件...你试过st-flash --help吗? - Luis Colorado
没问题,c: 无论如何你给我的知识都非常有用。感谢您的帮助! - Jacajack
1
我正在搜索st-flash工具的文档,但目前还没有结果。 - Luis Colorado
1
请注意:以下内容已被翻译,仅供参考:https://tjakubowski.wordpress.com/2012/12/04/programming-stm32f4-discovery-board-under-linux/(似乎可以使用“.hex”文件) - Luis Colorado
显示剩余2条评论

0
我在下面提供一个函数来实现这个功能:
hex2bin path/to/myfirmware1.hex
hex2bin path/to/myfirmware1.hex path/to/myfirmware2.hex
hex2bin myfirmware1.hex myfirmware2.hex myfirmware3.hex myfirmware4.hex
# etc.

注意:在我的eRCaGuy_dotfiles存储库中获取我hex2binhex2xxdhex函数的最新版本,请点击这里:.bash_useful_functions

Bash函数用于批量转换Intel *.hex固件文件为*.bin固件文件,并生成用于在meld中进行比较的*.xxd.hex文件

补充@A. Genchev's answer:当我想一次转换多个十六进制文件时,我发现使用如此长的命令很繁琐,所以我编写了这个辅助函数。

将此内容复制并粘贴到您的~/.bashrc文件底部,然后运行. ~/.bashrc重新源您的~/.basrhc文件,并使此功能对您可用:
# Function to convert .hex firmware files to .bin
#
# Example usage:
#
#       # this produces "path/to/myfile.bin" from "path/to/myfile.hex"
#       hex2bin path/to/myfile.hex
#
#       # you can pass multiple paths at once too
#       hex2bin path/to/myfile1.hex path/to/myfile2.hex path/to/myfile3.hex
#
hex2bin() {
    # treat all input args as file paths
    for filepath_hex in "$@"; do
        # See: https://dev59.com/c3NA5IYBdhLWcg3wbNQ4#965072
        filepath_hex_no_extension="${filepath_hex%.*}"
        filepath_bin="${filepath_hex_no_extension}.bin"
        # debugging
        # echo "filepath_hex_no_extension = $filepath_hex_no_extension"
        # echo "filepath_bin = $filepath_bin"
        echo "Converting \"$filepath_hex\" to \"$filepath_bin\"."

        objcopy --input-target=ihex --output-target=binary \
            "$filepath_hex" "$filepath_bin"
    done
}

# (Optional) add an alias prefixed with your initials so you can find all your
# custom aliases and functions easily by typing your initials followed by an
# underscore and hitting Tab Tab.
alias gs_hex2bin="hex2bin"

如果您使用不同的工具链,只需将 objcopy 替换为您工具链中相应版本的 objcopy。例如,对于适用于 PIC 微控制器的 Microchip MPLAB XC32 编译器工具链,请使用 xc32-objcopy 而非 objcopy
现在,不再需要这样写:
objcopy --input-target=ihex --output-target=binary \
    path/to/myfirmware1.hex path/to/myfirmware1.bin

objcopy --input-target=ihex --output-target=binary \
    path/to/myfirmware2.hex path/to/myfirmware2.bin

...你可以这样做:

hex2bin path/to/myfirmware1.hex path/to/myfirmware2.hex

您可以一次性传入尽可能多的路径名。

深入了解:使用 objcopyxxdmeld 进行比较和分析十六进制/二进制文件差异

如果您想要比较两个英特尔十六进制固件文件以查找差异,该怎么办?也许两个十六进制固件镜像几乎相同,但仅在其中存储的某些字符串、IP 地址或时间戳方面存在差异。那将很好知道。

具体步骤如下:

# - for "path/to/myfirmware1.hex", produce both "path/to/myfirmware1.bin"
#   and "path/to/myfirmware1.xxd.hex"
# - for "path/to/myfirmware2.hex", produce both "path/to/myfirmware2.bin"
#   and "path/to/myfirmware2.xxd.hex"
hex2xxdhex "path/to/myfirmware1.hex" "path/to/myfirmware2.hex"

# now compare the two `.xxd.hex` output files in `meld`
meld "path/to/myfirmware1.xxd.hex" "path/to/myfirmware2.xxd.hex"

meld 中的示例输出:

enter image description here

enter image description here

这是我hex2xxdhex函数的定义:
# Function to convert .hex firmware files to .bin and then to a
# human-compare-friendly .xxd.hex, so you can easily compare two files with
# `diff` or `meld`.
# - See my answer here: https://superuser.com/a/1790518/425838
#
# Example usage:
#
#       # this produces both "path/to/myfile.bin" and "path/to/myfile.xxd.hex"
#       # from "path/to/myfile.hex"
#       hex2xxdhex path/to/myfile.hex
#
#       # you can pass multiple paths at once too
#       hex2xxdhex path/to/myfile1.hex path/to/myfile2.hex
#       # then compare the two output ".xxd.hex" files with `meld`
#       meld path/to/myfile1.xxd.hex path/to/myfile2.xxd.hex
#
hex2xxdhex() {
    # treat all input args as file paths
    for filepath_hex in "$@"; do
        # See: https://dev59.com/c3NA5IYBdhLWcg3wbNQ4#965072
        filepath_hex_no_extension="${filepath_hex%.*}"
        filepath_bin="${filepath_hex_no_extension}.bin"
        filepath_xxdhex="${filepath_hex_no_extension}.xxd.hex"
        echo "Converting \"$filepath_hex\" to \"$filepath_bin\" and to"\
            "\"$filepath_xxdhex\"."

        objcopy --input-target=ihex --output-target=binary \
            "$filepath_hex" "$filepath_bin"
        xxd "$filepath_bin" "$filepath_xxdhex"
    done
}
alias gs_hex2xxdhex="hex2xxdhex"

要获取更多详细信息,请查看我的答案:超级用户:如何使用meld比较二进制文件、十六进制文件和Intel Hex固件文件


-1
arm-none-eabi-objcopy.exe -I ihex file.hex -O binary file.bin

1
目前你的回答不是很清晰。请编辑并添加额外的细节来帮助其他人了解如何解决问题。你可以在帮助中心找到更多关于如何写好答案的信息。 - Amit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接