如何使用gcc确定嵌入式系统中的最大堆栈使用率?
我正在为嵌入式系统编写启动代码——在跳转到main()函数之前加载初始堆栈指针的代码——我需要告诉它我的应用程序将使用多少字节的堆栈(或者一些更大的保守估计) 我被告知gcc编译器现在有一个-fstack usage选项和-fcallgraph info选项,可以以某种方式用于静态地为我计算准确的“最大堆栈使用率”。 (作者:博特卡祖、科马尔和海因克) Nigel Jones说递归在嵌入式系统中是一个非常糟糕的想法(“计算堆栈大小”2009),所以我一直很小心,没有在这段代码中使用任何相互递归的函数 此外,我确保在中断指令最终返回之前,我的中断处理程序都不会重新启用中断,所以我不需要担心重新进入的中断处理程序 如果没有递归或重入中断处理程序,应该可以静态地确定最大堆栈使用量。(因此,大多数答案并不适用)。 我的理解是,当每个中断处理程序没有被更高优先级的中断中断时,我(或者最好是在我的电脑上,每次重建可执行文件时自动运行的一些代码)首先找到最大堆栈深度,当main()函数没有中断时,找到最大堆栈深度。 然后我把它们加起来,找到总的(最坏情况下的)最大堆栈深度。(在我的嵌入式系统中)当main()后台任务被最低优先级的中断中断时处于其最大深度,当被下一个最低优先级的中断中断时,该中断处于其最大深度,依此类推 我正在使用带有GCC4.6.0的YAGARTO为LM3S1968 ARM-M3编译代码 那么,如何在gcc中使用-fstack usage选项和-fcallgraph info选项来计算最大堆栈深度呢?还是有更好的方法来确定最大堆栈使用率如何使用gcc确定嵌入式系统中的最大堆栈使用率?,gcc,embedded,code-analysis,static-analysis,Gcc,Embedded,Code Analysis,Static Analysis,我正在为嵌入式系统编写启动代码——在跳转到main()函数之前加载初始堆栈指针的代码——我需要告诉它我的应用程序将使用多少字节的堆栈(或者一些更大的保守估计) 我被告知gcc编译器现在有一个-fstack usage选项和-fcallgraph info选项,可以以某种方式用于静态地为我计算准确的“最大堆栈使用率”。 (作者:博特卡祖、科马尔和海因克) Nigel Jones说递归在嵌入式系统中是一个非常糟糕的想法(“计算堆栈大小”2009),所以我一直很小心,没有在这段代码中使用任何相互递归的
(有关针对Keil编译器的几乎相同的问题,请参阅。)我不熟悉
-fstack用法
和-fcallgraph info
选项。但是,始终可以通过以下方式计算实际堆栈使用情况:
0xee
- 函数的名称
- 字节数
- 一个或多个限定符:静态、动态、有界
对于-fdump树中优化的每个叶,从-fstack usage中获取其父级并求和它们的堆栈大小数(请记住,该数字适用于任何具有“动态”但非“有界”的函数),找到这些值的最大值,这应该是您的最大堆栈使用量。以防没有人给出更好的答案,我会将我在评论中的内容发布到你的另一个问题上,尽管我没有使用这些选项和工具的经验: GCC 4.6增加了
-fstack usage
选项,该选项提供了基于函数的堆栈使用统计信息
如果您将这些信息与由或类似工具生成的调用图相结合,就可以得到您想要的堆栈深度分析(编写脚本可能非常容易)。让脚本读取堆栈使用信息,并加载函数名与该函数使用的堆栈的映射。然后让脚本遍历cflow
图(这可能是一个易于解析的文本树),为调用图中的每个分支添加与每行相关联的堆栈使用情况
因此,看起来这可以通过GCC实现,但您可能必须拼凑出正确的工具集。已经很晚了,但对于任何关注这一点的人来说,所给出的答案涉及到将fstack用法和调用图工具(如cflow)的输出结合起来,对于任何动态分配,甚至是有界的,因为没有关于动态堆栈分配何时发生的信息。因此,不可能知道应该对哪些函数应用该值。作为人为的例子,如果(简化)
main 1024 dynamic,bounded
functionA 512 static
functionB 16 static
main
functionA
functionB
static unsigned long long max_stack_usage = 0;
void __cyg_profile_func_enter(void * this, void * call) __attribute__((no_instrument_function)) {
// get current stack usage using some hardware facility or intrisic function
// like __get_SP() on ARM with CMSIS
unsigned cur_stack_usage = __GET_CURRENT_STACK_POINTER() - __GET_BEGINNING_OF_STACK();
// use debugger to output current stack pointer
// for example semihosting on ARM
__DEBUGGER_TRANSFER_STACK_POINTER(cur_stack_usage);
// or you could store the max somewhere
// then just run the program
if (max_stack_usage < cur_stack_usage) {
max_stack_usage = max_stack_usage;
}
// you could also manually inspect with debugger
unsigned long long somelimit = 0x2000;
if (cur_stack_usage > somelimit) {
__BREAKPOINT();
}
}
void __cyg_profile_func_exit(void * this, void * call) __attribute__((no_instrument_function)) {
// well, nothing
}