如何使用gcc确定嵌入式系统中的最大堆栈使用量? [英] How to determine maximum stack usage in embedded system with gcc?

查看:58
本文介绍了如何使用gcc确定嵌入式系统中的最大堆栈使用量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为嵌入式系统编写启动代码——在跳转到 main() 函数之前加载初始堆栈指针的代码——我需要告诉它我的应用程序将使用多少字节的堆栈(或一些更大的保守估计).

I'm writing the startup code for an embedded system -- the code that loads the initial stack pointer before jumping to the main() function -- and I need to tell it how many bytes of stack my application will use (or some larger, conservative estimate).

我被告知 gcc 编译器现在有一个 -fstack-usage 选项和 -fcallgraph-info 选项,可以以某种方式用于静态计算我的确切最大堆栈使用".( 使用 GCC 进行编译时堆栈需求分析" 作者:Botcazou,Comar, 和海因克).

I've been told the gcc compiler now has a -fstack-usage option and -fcallgraph-info option that can somehow be used to statically calculates the exact "Maximum Stack Usage" for me. ( "Compile-time stack requirements analysis with GCC" by Botcazou, Comar, and Hainque ).

Nigel Jones 说递归在嵌入式系统中是一个非常糟糕的主意(计算堆栈大小"2009),所以我一直很小心,不要在这段代码中创建任何相互递归的函数.

Nigel Jones says that recursion is a really bad idea in embedded systems ("Computing your stack size" 2009), so I've been careful not to make any mutually recursive functions in this code.

另外,我确保我的中断处理程序在它们最后的从中断返回指令之前不会重新启用中断,所以我不需要担心可重入的中断处理程序.

Also, I make sure that none of my interrupt handlers ever re-enable interrupts until their final return-from-interrupt instruction, so I don't need to worry about re-entrant interrupt handlers.

没有递归或重入中断处理程序,应该可以静态确定最大堆栈使用量.(因此,如何确定最大堆栈使用量?的大部分答案是什么?不适用).我的理解是我(或者最好是我的 PC 上的一些代码,每次我重建可执行文件时都会自动运行)首先找到每个中断处理程序的最大堆栈深度,当它没有被更高优先级的中断中断时,最大堆栈深度main() 函数未中断时的堆栈深度.然后我将它们全部加起来以找到总(最坏情况)最大堆栈深度.当 main() 后台任务在被最低优先级中断中断时处于其最大深度时(在我的嵌入式系统中),当它被下一个最低优先级中断时该中断处于其最大深度时会发生这种情况中断等等.

Without recursion or re-entrant interrupt handlers, it should possible to statically determine the maximum stack usage. (And so most of the answers to How to determine maximum stack usage? do not apply). My understanding is I (or preferably, some bit of code on my PC that is automatically run every time I rebuild the executable) first find the maximum stack depth for each interrupt handler when it's not interrupted by a higher-priority interrupt, and the maximum stack depth of the main() function when it is not interrupted. Then I add them all up to find the total (worst-case) maximum stack depth. That occurs (in my embedded system) when the main() background task is at its maximum depth when it is interrupted by the lowest-priority interrupt, and that interrupt is at its maximum depth when it is interrupted by the next-lowest-priority interrupt, and so on.

我使用 YAGARTO 和 gcc 4.6.0 来编译 LM3S1968 ARM Cortex-M3 的代码.

I'm using YAGARTO with gcc 4.6.0 to compile code for the LM3S1968 ARM Cortex-M3.

那么我如何在 gcc 中使用 -fstack-usage 选项和 -fcallgraph-info 选项来计算最大堆栈深度?或者是否有更好的方法来确定最大堆栈使用量?

So how do I use the -fstack-usage option and -fcallgraph-info option with gcc to calculate the maximum stack depth? Or is there some better approach to determine maximum stack usage?

(参见如何确定嵌入式系统中的最大堆栈使用量? 几乎针对 Keil 编译器的相同问题.)

(See How to determine maximum stack usage in embedded system? for almost the same question targeted to the Keil compiler .)

推荐答案

GCC 文档:

-fstack-usage

-fstack-usage

在每个函数的基础上使编译器输出程序的堆栈使用信息.转储的文件名是通过将 .su 附加到 auxname 来生成的.auxname 是从输出文件的名称生成的,如果明确指定并且它不是可执行文件,否则它是源文件的基本名称.一个条目由三个字段组成:

Makes the compiler output stack usage information for the program, on a per-function basis. The filename for the dump is made by appending .su to the auxname. auxname is generated from the name of the output file, if explicitly specified and it is not an executable, otherwise it is the basename of the source file. An entry is made up of three fields:

  • 函数的名称.
  • 字节数.
  • 一个或多个限定符:静态、动态、有界.

限定符 static 表示函数静态操作堆栈:在函数入口为帧分配固定数量的字节,在函数退出时释放;函数中不会以其他方式进行堆栈调整.第二个字段是这个固定的字节数.

The qualifier static means that the function manipulates the stack statically: a fixed number of bytes are allocated for the frame on function entry and released on function exit; no stack adjustments are otherwise made in the function. The second field is this fixed number of bytes.

限定符动态意味着函数动态操作堆栈:除了上面描述的静态分配之外,还在函数体中进行堆栈调整,例如在函数调用周围推送/弹出参数.如果限定符 bounded 也存在,则这些调整的数量在编译时是有界的,第二个字段是函数使用的堆栈总量的上限.如果不存在,则这些调整的数量在编译时不受限制,第二个字段仅表示有界部分.

The qualifier dynamic means that the function manipulates the stack dynamically: in addition to the static allocation described above, stack adjustments are made in the body of the function, for example to push/pop arguments around function calls. If the qualifier bounded is also present, the amount of these adjustments is bounded at compile-time and the second field is an upper bound of the total amount of stack used by the function. If it is not present, the amount of these adjustments is not bounded at compile-time and the second field only represents the bounded part.

我找不到任何对 -fcallgraph-info 的引用

I can't find any references to -fcallgraph-info

您可能会从 -fstack-usage 和 -fdump-tree-optimized 中创建您需要的信息

You could potentially create the information you need from -fstack-usage and -fdump-tree-optimized

对于 -fdump-tree-optimized 中的每个叶子,从 -fstack- 获取其父级并将它们的堆栈大小号相加(请记住,此数字适用于具有动态"但不是有界"的任何函数)使用量,找到这些值的最大值,这应该是您的最大堆栈使用量.

For each leaf in -fdump-tree-optimized, get its parents and sum their stack size number (keeping in mind that this number lies for any function with "dynamic" but not "bounded") from -fstack-usage, find the max of these values and this should be your maximum stack usage.

这篇关于如何使用gcc确定嵌入式系统中的最大堆栈使用量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆