堆栈是嵌入式系统中非常基础但又特别重要的概念。正确设置堆栈的大小对于嵌入式系统的稳定性和可靠性非常重要。如果堆栈设置过小,可能会引起堆栈溢出,从而导致系统运行异常。反之,如果堆栈设置过大,则会造成宝贵RAM资源的浪费。由于堆栈需要开发人员指定分配,因此开发人员需要知道堆栈的使用情况,从而正确设置堆栈的大小。
本文主要介绍如何在IAR Embedded Workbench中分析和监控堆栈的使用,帮助开发人员正确设置堆栈的大小,提高系统的稳定性和可靠性,同时最大程度地减小RAM资源的使用。
关于堆栈的基本介绍,请参考之前的文章:掌控堆栈,确保系统稳定。
在正确的情况下,链接器可以准确地计算出每个根函数(根函数是一个不被任何其他函数调用的函数,包括程序启动函数,中断函数和RTOS任务函数等)的最大堆栈使用。当在IAR Embedded Workbench 使能堆栈分析之后,堆栈使用将被添加到链接器生成的map文件中,列出每个根函数的最大堆栈深度。
在Project>Options>Linker>Advanced中,选中Enable stack usage analysis来使能堆栈使用分析功能:
由于堆栈使用分析的结果将会包含在链接器生成的map文件中,需要在Project>Options>Linker> List选项卡中选中Generate Linker map file:
在下面的例子中,程序入口根函数 (__iar_program_start) 的最大堆栈深度为 288 字节,中断根函数 (__interrupt_170 and _default_handler) 的最大堆栈深度为 120 字节。
*************************************************************************
*** STACK USAGE
***
Call Graph Root Category Max Use Total Use
------------------------ ------- ---------
interrupt 120 120
Program entry 288 288
Program entry
"__iar_program_start": 0xffffb14c
Maximum call chain 288 bytes
"__iar_program_start" 4
"_main" 8
"_printf" 8
"__PrintfFullNoMb" 152
"__LdtobFullNoMb" in xprintffull_nomb.o [4] 80
"__GenldFullNoMb" in xprintffull_nomb.o [4] 36
interrupt
"__interrupt_170": 0xffffaa22
Maximum call chain 52 bytes
"__interrupt_170" 52
interrupt
"_default_handler": 0xffff98cb
Maximum call chain 68 bytes
"_default_handler" 52
"_abort" 4
"__exit" 12
静态堆栈使用分析在构建时计算出理论上的最大堆栈深度。然而在程序运行过程中,实际的堆栈消耗一般很难到静态堆栈使用分析计算出的理论上的最大深度。IAR Embedded Workbench提供了一种方法来监控程序运行时的堆栈使用,由 C-SPY 调试器实现。C-SPY 调试器可以在应用程序开始执行前用一个特殊数值模式,例如 0xCD 来填充整个堆栈区域。在程序运行一段时间后(最好是在某些测试条件下),堆栈内存可以从其末端向上检查,直到找到一个与 0xCD 不同的值,这可以被认为是 SP 曾经到达的最大位置。由于堆栈内存中仍然包含 0xCD 的部分从未被覆盖过,因此将堆栈的大小减少到这个数量是安全的。当然,最好保留一点额外的空间,以防您的测试没有持续足够长的时间,或者没有准确地反映所有可能的运行情况。
在IDE Options> Stack选项中勾选Enable graphical stack display and stack usage tracking以启用运行时堆栈使用跟踪:
调试时,可通过View>Stack打开Stack窗口,每当执行停止时,C-SPY 会在Stack窗口中更新堆栈的使用情况:
图形显示堆栈条的左端代表堆栈的底部,即堆栈为空时 SP 的位置。右端代表为堆栈保留的内存空间的末端。深灰色区域代表已使用的堆栈内存,浅灰色区域代表未使用的堆栈内存。当堆栈使用超过阈值(可在“IDE Options”对话框中设置)时,图形堆栈条会变成红色。
调试时就会有对应的RTOS插件的选项,暂停之后,就可以查看对应RTOS的任务堆栈使用情况:
正确设置堆栈的大小对于嵌入式系统的稳定性和可靠性非常重要,本文主要介绍了如何在IAR Embedded Workbench中进行静态堆栈使用分析和运行时堆栈使用监控,帮助开发人员知道应用程序中的堆栈使用情况,提高系统的稳定性和可靠性。
参考文献: