使用GCC生成连续的Hex文件

时间:2018-04-18 13:45:18

标签: c gcc stm32 bootloader hex-file

我有一个用于STM32F427的Hex文件,它是使用具有连续内存地址的GCC(gcc-arm-none-eabi)版本4.6构建的。我编写了用于加载该hex文件的引导加载程序,并添加了校验和功能,以确保在启动应用程序之前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 个答案:

答案 0 :(得分:2)

如果可以选择对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填充,没有数据。第二行将二进制文件转换回hex文件。

结果将是

:08018000B9BC0C08B9BC0C0865

变为

:10018000B9BC0C08B9BC0C08FFFFFFFFFFFFFFFF65

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

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

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

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

更长,更灵活的方法是使用IntelHex API实现您自己的工具。我已经在类似于你的情况下使用了这个效果 - 调整hex文件以满足更改成本高昂的工具,但只能像编写工具时那样处理hex文件。

答案 1 :(得分: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
}

答案 2 :(得分:1)

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

$ pip install bincopy
$ bincopy fill foo.hex

答案 3 :(得分:0)

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