【发布时间】:2014-07-09 00:28:41
【问题描述】:
我正在使用 STM32F4 (Cortex-M4) MCU 并使用 arm-none-eabi-g++ 进行编译(我正在使用 C++)。
我需要减少将二进制文件上传到 MCU 闪存所需的时间。我发现我可以通过仅在修改之间将更改上传到我的二进制文件来做到这一点。然而,编译器正在生成一些有趣的代码,这使得这变得不可能。
考虑以下 2 个程序:
(1)
int main()
{
printf("hello");
return 0
}
(2)
int main()
{
//printf("hello");
return 0
}
只需删除printf 调用,二进制文件就完全不同了。我可以通过使用arm-none-eabi-objdump -D mybinary 反汇编代码来看到这一点。以下是 WinMerge 中的差异示例:
从图中可以看出,几乎所有函数都有一个略有不同的stmdaeq指令,我想了解更多。
这个问题的答案将包括以下内容:
- 我知道
stmdaeq指令是什么,但为什么它几乎在所有函数的末尾?这是函数的尾声吗? - 我能做些什么(编译器选项或其他)来确保小的代码更改(如我上面的示例)不会导致整个二进制文件发生此类更改?
我正在使用GNU Tools for ARM Embedded Processors GCC 工具链。
您的帮助将不胜感激。
【问题讨论】:
-
你的尝试可能是徒劳的。在实践中,虽然大块代码在指令方面可能保持不变,但几乎可以肯定它们通常会随着代码的插入或删除而改变地址。此外,闪存是块擦除的,因此特定块内没有变化的可能性很小 - 在任何情况下您都必须擦除和写入整个块。根据具体的部分,实际的 Flash 块大小可能非常大。您可以通过应用积极的大小优化并指示链接器用 0xFF 填充未使用的空间来获得进一步的结果。
-
@Clifford,即使修改了 1 个字节,您也必须写入整个块是正确的。我已经在我的闪存程序中适应了这一点。 @Seva Alekseyev 是对的。
stmdaeq行实际上是在链接时插入的地址。我发现通过精心组织和排序链接器脚本中的符号,我可以让二进制文件在更改之间更加一致并达到我想要的结果。 -
也许对于这个小例子,但是在一个真实的(和大型的)应用程序上?
-
@Clifford,是的,但我承认这取决于变化。某些更改将需要重新刷新整个程序,但我的链接描述文件修改降低了这种情况发生的频率。只需更新 1 个区块即可进行细微更改,这非常好。
标签: gcc assembly embedded thumb