如何确定嵌入式系统中的最大堆栈使用量?

时间:2011-06-16 17:01:55

标签: embedded code-analysis static-analysis keil

当我给Keil编译器提供“--callgraph”选项时, 它静态地为我计算了“最大堆栈使用率”。

唉,今天它给了我一个“最大堆栈使用率= 284字节+未知(没有堆栈大小的函数......)”消息,以及“没有堆栈信息的函数”列表。

奈杰尔·琼斯说,递归在嵌入式系统中是一个非常糟糕的主意 ("Computing your stack size" 2009), 所以我一直小心不要在这段代码中做任何相互递归的函数。

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

如果没有递归或重入中断处理程序,它应该能够静态地确定最大堆栈使用量。 (以及大多数答案 How to determine maximum stack usage? 请勿应用)。 我的理解是处理“--callgraph”选项的软件 首先查找每个中断处理程序在没有被优先级较高的中断中断时的最大堆栈深度,以及main()函数在没有中断时的最大堆栈深度。 然后它将它们全部加起来以找到总(最坏情况)最大堆栈深度。 当main()后台任务在被最低优先级中断中断时处于最大深度时会发生这种情况,并且当该中断被下一个最低优先级中断中断时,该中断处于其最大深度,依此类推。

我怀疑处理--callgraph的软件对“无堆栈信息的函数”列表中的小型汇编语言函数感到困惑。 --callgraph documentation似乎暗示我需要手动计算(或做出保守估计)他们使用多少堆栈 - 它们非常短,所以应该很简单 - 然后“在汇编中使用帧指令用于描述代码如何使用堆栈的语言代码。“ 其中之一是初始启动代码,在跳转到main()之前将堆栈重置为零 - 因此,实际上,这会消耗零堆栈。 另一个是“故障”中断处理程序,它在无限循环中锁定,直到我循环上电 - 可以安全地假设它消耗零堆栈。

我正在使用Keil uVision V4.20.03.0编译LM3S1968 ARM Cortex-M3的代码。

那么如何使用“frame directives”来告诉处理“--callgraph”的软件这些函数使用了多少堆栈? 或者是否有更好的方法来确定最大堆栈使用量?

(请参阅How to determine maximum stack usage in embedded system with gcc?了解与gcc编译器相同的问题。)

2 个答案:

答案 0 :(得分:3)

在链接器选项中使用--info = stack。然后,映射文件将包含具有外部链接的所有函数的堆栈用法。

在单一任务环境中,main()的堆栈使用情况将为您提供总需求。如果您正在使用RTX等RTOS,其中每个任务都有自己的堆栈,那么您需要查看所有任务入口点的堆栈使用情况,然后为任务上下文添加更多(在RTX的情况下为64字节)存储

适用于Keil的这种和其他技术以及更一般地描述here

答案 1 :(得分:3)

犹他大学的John Regehr在http://www.embedded.com/design/prototyping-and-development/4025013/Say-no-to-stack-overflow对嵌入式系统中的堆栈使用情况进行了很好的讨论,但请注意到ftp.embedded.com的链接是陈旧的,并且有一次“没有中断禁用” “应该将第一个或最后一个词否定。在商业领域,Coverity有一个可配置的堆栈溢出检查器,CodeWarrior的某些版本有一个半文档的warn_stack_usage pragma。 (在我的编译器文档版本中没有提到,但是在MetroWerks的“Targeting Palm OS”文档中。)