【问题标题】:FreeRTOS wrong context switch restorationFreeRTOS 错误上下文切换恢复
【发布时间】: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 中完成(除了自动存储的)。您可以在这里进行调试,但是每次上下文切换都会出现在这里,因此在恢复任务时很难捕捉到它。

标签: stm32 freertos


【解决方案1】:

Cortex-M 上的大多数问题归结为不正确的中断优先级分配和堆栈溢出,因此更高版本的 FreeRTOS 对这两个错误都有很多陷阱,以便在它们发生时立即通知您 - 但您必须打开捕获这些常见错误的能力,如下所示:

您是否定义了configASSERT(),您使用的是哪个版本的 FreeRTOS?版本越晚,configASSERT() 就越有用。

您是否将 configCHECK_FOR_STACK_OVERFLOW 设置为 2 并定义了堆栈溢出挂钩?

【讨论】:

  • configASSERT 定义如下: #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} 版本是 8.2.3。是的,我使用堆栈溢出挂钩和 malloc 失败挂钩。他们没有报告任何问题。
  • 也许另一个任务正在压过这个任务堆栈?
【解决方案2】:

我找到了问题的根源。在blockingFunction() 内部有明确填充的缓冲区。缓冲区太小,覆盖了我任务的 TCB。

【讨论】:

    猜你喜欢
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 2011-07-05
    • 2021-12-22
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多