【发布时间】:2011-09-17 06:33:59
【问题描述】:
我正在为嵌入式系统编写启动代码——在跳转到 main() 函数之前加载初始堆栈指针的代码——我需要告诉它我的应用程序将使用多少字节的堆栈(或一些更大的保守估计)。
我被告知 gcc 编译器现在有一个 -fstack-usage 选项和 -fcallgraph-info 选项,它们可以以某种方式用于为我静态计算确切的“最大堆栈使用量”。 ("Compile-time stack requirements analysis with GCC" 由 Botcazou、Comar 和 Hainque 撰写)。
Nigel Jones 说递归在嵌入式系统中是一个非常糟糕的主意(“计算堆栈大小”,2009 年),所以我一直小心不要在这段代码中创建任何相互递归的函数。
另外,我确保我的中断处理程序在它们最后的从中断返回指令之前都不会重新启用中断,所以我不需要担心可重入中断处理程序。
没有递归或重入中断处理程序,应该可以静态确定最大堆栈使用量。 (因此How to determine maximum stack usage? 的大多数答案都不适用)。 我的理解是我(或者最好是我的 PC 上的一些代码,每次我重建可执行文件时都会自动运行)首先找到每个中断处理程序的最大堆栈深度,当它没有被更高优先级的中断中断时,以及最大值main() 函数未中断时的堆栈深度。 然后我将它们全部加起来以找到总(最坏情况)最大堆栈深度。当 main() 后台任务在被最低优先级中断中断时处于其最大深度时,会发生这种情况(在我的嵌入式系统中),并且当它被下一个最低优先级中断时,该中断处于其最大深度中断,等等。
我正在使用 YAGATO 和 gcc 4.6.0 来编译 LM3S1968 ARM Cortex-M3 的代码。
那么如何使用 gcc 的 -fstack-usage 选项和 -fcallgraph-info 选项来计算最大堆栈深度?还是有更好的方法来确定最大堆栈使用量?
(有关针对 Keil 编译器的几乎相同问题,请参阅 How to determine maximum stack usage in embedded system?。)
【问题讨论】:
-
还要注意,任何函数指针的使用都只会被动态分析捕获。
-
要获取调用者和被调用者信息,您可以使用-fdump-ipa-cgraph。您引用的调用图选项不存在,afaik。
-
在您从 ISR 返回之前重新启用中断不会阻止允许嵌套中断的系统重新进入。实现这一点的唯一方法是禁用 ISR 中的中断并从主代码重新启用它们。
-
@iheanyi:嗯?我非常小心 not 在从中断返回指令 (RETI) 之前重新启用中断,所以我不明白你的评论。 stackoverflow.com/questions/52886592/… ; infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0460d/… ;等暗示还有其他几种方法可以防止重新进入,这些方法不涉及在主代码中重新启用中断。如果某个中断处理程序在最终 RETI 之前从未重新启用中断,则永远不会重新进入(嵌套)该中断处理程序,对吗?
-
大卫,重读你的问题,我知道我错了。假设您在进入 ISR 时禁用中断,在最终 RETI 之前重新启用将确保您不会损坏 ISR 中触及的任何数据。那时你是否重新进入 ISR 并不重要。
标签: gcc embedded code-analysis static-analysis