10

当我为 Keil 编译器提供“--callgraph”选项时,它会为我静态计算确切的“最大堆栈使用量”。

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

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

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

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

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

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

那么如何使用“框架指令”来告诉处理“--callgraph”的软件这些函数使用了多少堆栈呢?还是有更好的方法来确定最大堆栈使用量?

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

4

2 回答 2

3

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

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

此处描述了适用于 Keil 和更一般性的此技术和其他技术

于 2011-06-17T20:43:47.627 回答
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”文档中。)

于 2011-06-18T16:33:44.280 回答