【发布时间】:2017-08-11 16:58:58
【问题描述】:
我正在使用带有 STM32F407 的 FreeRTOS。我有错误的上下文切换恢复问题。代码在任务代码中是这样的:
char *ptr = pvPortMalloc(sizeof(char) * size);
memcpy(ptr, buf, size);
...
log("Before:");
logItoa((int)ptr);
blockingFunction(); // Here preemption will occur
log("After:");
logItoa((int)ptr);
blockingFunction() 不使用ptr。
当我调试时,我可以看到,ptr 指向的地址与指令一起存储:
STR R0, [R7, #24]
于是我检查了数据内存中地址 (R7 + 24)(^1) 下的值,发现动态分配数据的地址已成功保存。
上下文恢复后,我检查变量ptr,发现它没有指向我新分配的数据,所以我检查地址 (^1) 下的值,发现值保持不变,但 R7 中的值寄存器(用于地址计数)与抢占前不同。
这会导致我的每个局部变量都不相同的情况,因为它们是从数据内存中错误地获取的。
如果是堆栈溢出问题,我该如何调试?
【问题讨论】:
-
最快的方法是增加任务堆栈大小,看看问题是否消失。您也可以尝试增加系统堆栈大小,以防它太小。你用的是什么工具链?另外我假设 malloc 不在任务循环内?
-
我为 FreeRTOS 堆大小分配了几乎整个 RAM,xPortGetMinimumEverFreeHeapSize() 返回大约 50MB 的空闲空间。我还为我的每个任务分配了两倍的堆栈大小。对于我的每个任务,uxTaskGetStackHighWaterMark 返回的值表明不可能发生堆栈溢出。我没有检查的唯一任务是 LWiP 线程,但我认为这不会造成问题。我正在使用 gcc-arm-none-eabi-5_4-2016q3。它在任务循环内,但循环以:xQueueReceive() 开始,每小时畅通一次。当然最后内存被释放了。
-
这听起来不像是堆栈溢出问题。寄存器的存储和恢复在 xPortPendSVHandler 中完成(除了自动存储的)。您可以在这里进行调试,但是每次上下文切换都会出现在这里,因此在恢复任务时很难捕捉到它。