|嵌入式开发:执行最坏情况堆栈分析的3种方法

|嵌入式开发:执行最坏情况堆栈分析的3种方法

文章图片


弄清楚如何为嵌入式应用程序和其中的任务确定堆栈的大小可能具有挑战性 。 在许多情况下 , 开发人员会选择一个他们认为应该足够的值 , 这些估计有时有点短 , 大部分时间是粗略估计 , 很少出现 。 虽然嵌入式开发人员在整个开发周期中应该监控他们的堆栈使用情况 , 但有时开发人员应该执行最坏情况的堆栈分析 , 例如:

它们在 RAM 上运行得非常危险
需要提交新的代码版本
他们正在最终确定用于生产的固件
在这篇文章中 , 我将讨论开发人员可以执行最坏情况堆栈分析的三种不同方式 。
技巧 1 – 手工计算
在过去 , 嵌入式软件开发人员过去不得不手动计算他们的堆栈使用情况 , 这可能是一项棘手的工作 。 为了手动计算堆栈使用量 , 开发人员需要知道:
他们要进行多少次函数调用
在每个函数中将存储在堆栈中的局部变量
将存储在堆栈中的返回地址的大小将存储在堆栈中的局部变量的大小
如果在执行期间发生中断 , 中断帧将有多大
可能发生的嵌套中断数
正如你可以想象的那样 , 找到所有这些值并在进行更改时继续跟踪它们可能非常耗时且容易出错 , 这就是为什么不再推荐这种方法的原因 , 但嵌入式开发人员尝试一次以更深入地了解其他技术正在做什么仍然很有用 。

技巧 2 – 使用静态代码分析器
许多静态代码分析器可用于估计最坏情况下的堆栈使用情况 。 在代码分析期间 , 该工具将确定函数深度以及我们之前列出的许多项目 。 使用静态分析器的好处在于它不仅执行堆栈分析 , 而且还检查代码的潜在问题 。 它在几秒钟内运行 , 这使开发人员无需手动计算堆栈使用情况 。
虽然使用静态代码分析器来获取最坏情况下的堆栈使用情况是一个不错的方法 , 但开发人员需要注意几个潜在问题 。 这些包括:
取消引用函数指针不计为函数调用
不考虑中断帧
了解你的工具如何处理这些项目非常重要 。 为了获得准确的结果 , 在静态代码分析期间 , 必须经常使用宏或编译器符号有条件地将函数指针编译成函数调用 。 然后 , 你还必须添加你认为的中断堆栈使用情况 。 小问题 , 但在任何分析中都需要理解 。
技术#3 – 测试和测量
对于最坏情况堆栈分析 , 嵌入式开发人员经常提倡的技术是测试和测量系统 。 许多开发环境现在都有执行OS-Aware调试的工具 , 这些工具将密切监视RTOS性能 , 包括应用程序运行时的最大堆栈使用量 。 下图中可以看到一个很好的示例 , 该示例来自使用ThreadX的Renesas Synergy平台的e2 Studio 。

如你所见 , 每个线程(任务)都与内存位置、堆栈指针和最大堆栈使用量一起列出 。 我们甚至可以看到堆栈分配了多少内存 。 这不仅为开发人员提供了一种很好的方式来密切关注他们的堆栈使用情况 , 而且还可以确定他们的最大堆栈使用量是多少 。
开发人员确实需要小心呈现给他们的最大值 。 重要的是 , 在他们的系统处于最大压力下时进行读数 。 对于基于RTOS的应用程序 , 中断帧通常存储在系统堆栈中 , 因此我们无需考虑调整每个线程的大小以有足够的内存来应对中断风暴 。
结论
无论你使用哪种技术来确定你的堆栈使用情况 , 稍微加大堆栈大小仍然是一个好习惯 。 有可能在测试期间从未实现过最坏的情况 , 这可能会在系统在现场时将系统设置为堆栈溢出 。