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

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

问题描述

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



我被告知gcc编译器现在有一个-fstack-usage选项和-fcallgraph-info选项,可以以某种方式被使用以静态计算我的确切的最大堆叠使用量。
与GCC的编译时栈需求分析由Botcazou,Comar和Hainque提供)



Nigel Jones表示递归在嵌入式系统中是一个非常糟糕的想法(计算您的堆栈大小2009),所以我在这段代码中,我们一直小心不要做任何相互递归的函数。



此外,我确保我的中断处理程序中没有一个重新启用中断,直到最终返回从中断指令,所以我不需要担心重入中断处理程序。



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



我正在使用YAGARTO与gcc 4.6.0来编译LM3S1968 ARM Cortex-M3的代码。



那么如何使用-fstack-usage选项和-fcallgraph-info选项与gcc来计算最大堆栈深度?还是有更好的方法来确定最大堆栈使用率?



(请参阅如何确定嵌入式系统中的最大堆栈使用率,针对Keil编译器几乎相同的问题。)

解决方案

GCC文档:


-fstack-usage



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




  • 该函数的名称。

  • 一个数字的字节。

  • 一个或多个限定符:静态,动态,有界。



限定符静态意味着该函数静态地操作堆栈:为功能条目上的帧分配固定数量的字节,并释放功能退出;在功能中不进行堆栈调整。第二个字段是这个固定数量的字节。



限定符动态意味着该函数动态地操作堆栈:除了上述静态分配之外,进行堆栈调整在函数的正文中,例如在函数调用周围推/ pop参数。如果限定符界限也存在,则这些调整的数量在编译时是有界的,第二个字段是该函数使用的堆栈总量的上限。如果不存在,则这些调整的数量在编译时不受约束,第二个字段仅表示有界部分。


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



您可以通过-fstack-usage和-fdump-tree优化来创建您需要的信息。



对于-fdump-tree优化的每个叶子,可以获取父母和总结他们的堆栈大小号码(请记住,这个数字适用于任何具有动态但不是有界)的功能,而不是使用-fstack-usage,找到这些值的最大值,这应该是您的最大堆栈使用量。 >

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).

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 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.

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.

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

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?

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

解决方案

GCC docs:

-fstack-usage

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:

  • The name of the function.
  • A number of bytes.
  • One or more qualifiers: static, dynamic, bounded.

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.

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.

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

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

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天全站免登陆