大家好,
我在运行 FreeRTOS 的S32K358上遇到了随机硬故障问题。
应用程序长时间正常运行后突然卡死。系统停止运行后,软件看门狗(SWT)得不到服务,最终导致控制器重置。
故障并非立即发生,而是在连续执行约1 至 2 小时后出现。
故障停止后,调用堆栈显示:
PendSV_Handler()
↓
HardFault_Handler()
寄存器值:
LR = 0xA5A5A5A5
PC = 0x00407BD9
其他登记簿:
R0 = 0x204011A8
R3 = 0x2040012C
R12 = 0x20400010
任何建议或调试技巧都将不胜感激。
看起来在 FreeRTOS 上下文切换期间保存的任务上下文已损坏。
PendSV 被 FreeRTOS 用于上下文切换,因此,如果在 PendSV_Handler() 内部发生 HardFault,通常意味着调度程序正在尝试恢复无效的任务上下文。
一个可能的根本原因是任务堆栈溢出。我建议增加任务的堆栈大小并启用 FreeRTOS 堆栈溢出检测:
configCHECK_FOR_STACK_OVERFLOW
实现: vApplicationStackOverflowHook()。
此外,您可以使用 uxTaskGetStackHighWaterMark() 定期监测每个任务的剩余堆栈空间。这有助于在故障发生之前识别出接近堆栈限制运行的任务。
此致,
丹尼尔
你好@danielmartynek ,
感谢您的回复。
我已经尝试过增加堆栈大小,启用堆栈溢出钩子。
我在溢出钩子中添加了调试 CAN 消息,但发生故障时没有收到该消息。
同时监控uxTaskGetStackHighWaterMark(),当发生故障时
任务 1:1977 × 4 ≈ 7908 字节可用空间
任务 2:1971 × 4 ≈ 7884 字节可用空间
任务 3:3988 × 4 ≈ 15952 字节可用空间
因此,我们大概可以排除堆栈溢出是根本原因的可能性。
然而,任务上下文仍然会遭到破坏。处理器正在恢复 LR = 0xA5A5A5A5,这导致了 UsageFault。0xA5A5A5A5 是由 tskSTACK_FILL_BYTE (0xA5U) 生成的模式,FreeRTOS 使用该模式在创建任务堆栈时填充任务堆栈。
因此,如果 LR 变为 0xA5A5A5A5,则上下文将从仍然包含原始堆栈填充模式的位置恢复,而不是从有效的寄存器值恢复。
如果存储过程损坏,就可能发生这种情况。在这种情况下,PendSV_Handler() 会从 RAM 中的错误位置恢复任务上下文。
你应该能够根据堆栈指针地址识别出 SRAM 区域。
我建议您使用 MPU 和 XRDC 对该区域进行适当保护。
另外,是否有任何中断调用 FreeRTOS API?如果是这样,他们是否使用了 FromISR() 变体,并且他们的优先级是否根据 configMAX_SYSCALL_INTERRUPT_PRIORITY 正确配置?
此致,
丹尼尔