TASKING TriCore工程中的栈主要包括用户栈和中断栈,多核AURIX还会为不同TriCore核心分别保留对应栈空间。函数局部变量、参数、中间计算结果以及中断处理都会产生栈占用。程序出现随机Trap、运行一段时间后跑飞、进入深层函数后异常时,可以先查看链接器给出的栈使用估算,再结合A10栈指针和运行时检查判断是否已经发生栈越界。
一、TASKING怎么查看栈使用情况
TASKING编译器会生成函数调用和栈占用信息,链接器再根据调用关系计算Estimated stack usage。这个结果可以直接在Map文件中查看,适合先判断当前预留空间是否明显不足。
1、在Map文件中查看栈估算值
①选中工程,执行【Project】→【Rebuild Project】。
②打开工程输出目录。
③找到生成的【.map】或【.mapxml】文件。
④双击【.mapxml】进入图形化Map查看器。
⑤在【Select table】中选择【Used Resources:Estimated stack usage】。
⑥查看【Stack Name】中的【ustack_tc0】【istack_tc0】。
⑦多核工程继续检查【ustack_tc1】【ustack_tc2】等对应栈。
⑧重点查看【Used】数值,并与当前实际分配的栈大小比较。
⑨查看【Recursive】是否显示递归调用。
⑩检查【Entry points】是否包含当前核心真正的程序入口。
【Used】是链接器根据调用关系计算出的估算值,并不是程序运行期间测出的峰值。项目存在递归、函数指针或复杂中断嵌套时,还需要保留额外空间。
2、通过Call Graph找出高栈占用函数
①保持打开【.mapxml】。
②切换到Call Graph相关视图。
③从程序入口或核心入口展开函数调用树。
④查看各函数节点对应的自身栈占用。
⑤继续查看包含被调用函数后的累计占用。
⑥找到累计数值较高的调用链。
⑦检查对应函数是否定义了较大的局部数组或结构体。
⑧发现递归函数时,单独估算允许的递归层数。
这种方法适合定位“到底是哪条调用路径吃掉了栈”,比单纯扩大栈空间更容易找到程序结构中的问题。
3、Map中栈使用量显示为0怎么检查
①打开【Estimated stack usage】。
②如果【Used】显示【0x0】,先查看【Entry points】是否为空。
③打开当前工程使用的【.lsl】文件。
④检查【__USTACK0_ENTRY_POINTS】或对应核心的Entry Points设置。
⑤TC1、TC2独立运行程序时,分别检查【__USTACK1_ENTRY_POINTS】【__USTACK2_ENTRY_POINTS】。
⑥把实际启动入口加入对应栈的计算范围。
⑦重新Build工程。
⑧再次检查【Estimated stack usage】。
使用较早工程中的自定义LSL时,升级工具链后可能缺少Entry Points配置,这时Map里的零值不能代表程序真的没有使用栈。
二、TASKING栈空间不足导致运行异常如何判断
TriCore使用A10作为运行时栈指针。栈越界后可能覆盖附近RAM,随后才出现Trap或变量异常,因此故障位置不一定就是实际发生栈耗尽的位置。
1、异常发生后检查A10
①在容易出现异常的代码路径设置断点。
②进入TASKING Debugger运行程序。
③打开寄存器窗口。
④记录【A10】当前值。
⑤打开Map文件找到当前核心【ustack】的起止地址。
⑥确认A10仍位于合法栈范围。
⑦程序进入Trap后再次记录【A10】。
⑧同时检查Trap状态和当前【PC】。
⑨如果A10已经越过栈边界,就可以继续按栈溢出方向排查。
TASKING列出的TriCore栈溢出现象包括程序行为异常、程序失控以及随后进入Trap。故障后的A10和Trap现场都很有参考价值。
2、开启运行时栈溢出检查
TASKING编译器还可以在函数建立栈帧时加入边界检查,用于直接捕获栈越界。
①进入【Project】→【Properties】。
②打开【C/C++Build】→【Settings】。
③进入【C/C++Compiler】→【Debugging】。
④找到运行时错误检查相关设置。
⑤启用【Generate code for stack overflow checks】。
⑥重新编译工程。
⑦运行原来容易触发异常的功能。
⑧发生越界时检查是否进入【__runtime_stack_overflow】。
⑨根据调用位置返回对应函数检查局部变量和调用深度。
该功能会增加额外检查代码,更适合故障定位阶段使用,完成排查后再根据项目要求决定是否保留。
三、确认栈不足后怎么调整和验证
已经确认栈空间接近边界后,可以增大对应核心的栈,同时继续检查大局部变量、递归和中断调用,避免只靠增加RAM掩盖问题。
1、修改用户栈大小
①打开工程使用的【.lsl】文件。
②找到【USTACK】或【USTACK_TC0】定义。
③多核工程检查对应的【USTACK_TC1】【USTACK_TC2】。
④增加发生问题核心的用户栈空间。
⑤确认新的栈区域没有和其他Section重叠。
⑥重新Build工程。
⑦打开Map文件检查新的栈分配结果。
⑧确认【Estimated stack usage】小于实际预留空间,并保留适量余量。
2、用运行数据再次验证
①重新运行容易触发故障的完整业务路径。
②覆盖深层函数调用和高负载场景。
③再次观察A10。
④需要测运行峰值时,可以预先用固定数据填充栈区域。
⑤程序运行后检查填充值被覆盖到的位置。
⑥根据实际高水位估算运行期间的栈峰值。
⑦结果仍接近边界时,继续检查大局部变量和递归调用。
使用RTOS的工程还要另外检查各任务自己的Task Stack,不能只依赖TASKING链接器给出的主程序栈估算。
总结
TASKING查看栈使用情况时,可以先利用Map文件中的Estimated stack usage和Call Graph定位高占用调用链,再通过A10、Trap现场以及运行时栈溢出检查确认程序是否真正越界。调整栈大小后还应重新跑完整业务路径,并给递归、中断和运行波动保留空间。如需进一步了解TASKING栈空间配置、栈使用分析与运行异常排查方法,欢迎联系咨询。