4

我有一个 STM32F427 的十六进制文件,它是使用具有连续内存地址的 GCC(gcc-arm-none-eabi) 4.6 版构建的。我编写了用于加载该 hex 文件的引导加载程序,还添加了校验和功能,以在启动应用程序之前确保 Hex 文件正确。十六进制文件的片段:

:10 05C8 0018460AF02FFE07F5A64202F1D00207F5F9 :10 05D8 008E4303F1A803104640F6C821C2F2000179 :10 05E8 001A460BF053F907F5A64303F1D003184652 :10 05F8 000BF068F907F5A64303F1E80340F6FC1091 :10 0608 00C2F2000019463BF087FF07F5A64303F145 :10 0618 00E80318464FF47A710EF092FC07F5A643EA :10 0628 0003F1E80318460EF03DFC034607F5A64221 :10 0638 0002F1E0021046194601F0F2FC07F56A5390

如您所见,所有地址都是连续的。然后我们将编译器更改为 4.8 版本,我得到了相同类型的 Hex 文件。

但是现在我们使用了 6.2 版本的编译器,生成的 Hex 文件不是连续的。有点像这样:

:10016000B9BC0C08B9BC0C08B9BC0C08B9BC0C086B
:10017000B9BC0C08B9BC0C08B9BC0C08B9BC0C085B
:08018000B9BC0C08B9BC0C0865
:1001900081F0004102E000BF83F0004330B54FEA38
:1001A00041044FEA430594EA050F08BF90EA020FA5

正如您在 0188 之后看到的那样,它从 0190 开始意味着其余 8 个字节(0189 到 018F)是 0xFF,因为它们没有被刷新。

现在引导加载程序有点愚蠢,我们只传递起始地址和字节数来计算校验和。

有没有办法像编译器 4.6 和编译器 4.8 一样以连续的方式制作 hex 文件?代码在所有三个时间都是相同的。

4

4 回答 4

3

如果后处理 hex 文件是一个选项,您可以考虑使用IntelHex python 库。这使您可以操纵十六进制文件数据(即忽略“标记”;记录类型、地址、校验和等),而不是作为行,例如使用正确的行校验和创建输出。

启动和运行它的一种快速方法是使用捆绑的便利脚本hex2bin.pybin2hex.py

python hex2bin.py --pad=FF noncontiguous.hex tmp.bin
python bin2hex.py tmp.bin contiguous.hex

第一行将输入文件转换为二进制文件,在没有数据noncontiguous.hex的地方填充它。FF第二行将二进制文件转换回十六进制文件。

结果将是

:08018000B9BC0C08B9BC0C0865

变成

:10018000B9BC0C08B9BC0C08FFFFFFFFFFFFFFFF65

如您所见,在输入没有任何数据的地方添加了填充字节,相当于将输入文件写入设备并将其读回。输入文件中的字节保持不变 - 并且位于相同的地址。校验和也是正确的,因为将长度字节更改0x080x10补偿额外的0xFF字节。如果你用其他东西填充,IntelHex 会输出正确的校验和

您可以通过管道跳过创建临时文件:tmp.bin在第一行中省略并在第二行中将其替换为-

python hex2bin.py --pad=FF noncontiguous.hex | python bin2hex.py - contiguous.hex

另一种方法可能是拥有一个包含 all 的基本文件,FF并使用hexmerge.py便捷脚本将 gcc 的输出与--overlap=replace

更长、更灵活的方法是使用 IntelHex API 实现您自己的工具。在与您的情况类似的情况下,我已使用此方法取得了良好的效果 - 调整 hex 文件以满足更改成本高昂的工具,但仅以编写工具时的方式处理 hex 文件。

于 2018-04-18T22:47:43.547 回答
1

许多可能的方法之一:

  • 使用 v6.2 制作您的 hex 文件,例如foo.hex.
  • 使用这个 Perl oneliner 对其进行后处理:

    perl -pe 'if(m/^:(..)(.*)$/) { my $rest=16-hex($1); $_ = ":10" . $2 . ("FF" x $rest) . "\n"; }' foo.hex > foo2.hex
    

现在foo2.hex将有所有 16 字节的行

注意:所有这些都是 FF-pad 到 0x10 字节。它不检查地址或其他任何内容。

解释

perl -pe '<some script>' <input file><some script>对 的每一行运行<input file>,并打印结果。脚本是:

if(m/^:(..)(.*)$/) {         # grab the existing byte count into $1
    my $rest=16 - hex($1);   # how many bytes of 0xFF we need
    $_ = ":10" . $2 . ("FF" x $rest) . "\n";  # make the new 16-byte line
# existing bytes-^^   ^^^^^^^^^^^^^^-pad bytes
}
于 2018-04-18T13:53:13.437 回答
1

您可以使用bincopy用 0xff 填充所有空白空间。

$ pip install bincopy
$ bincopy fill foo.hex
于 2020-08-07T21:07:01.730 回答
1

另一种解决方案是更改链接描述文件以确保前面的 .isr_vector 部分以 16 字节对齐结束,因为映射文件显示以下 .text 部分是 16 字节对齐的。这将确保两个部分之间没有未编程的闪存字节

于 2019-07-10T11:42:48.360 回答