以下为常见问题节选
此外,我们提供以下两个在线资源:
虽然我不了解您的应用程序的具体情况,但以下是一些常见的解决方案:
如果您创建的项目正在编译中,并且至少执行到 调度器已启动的状态, 但是 调用 vTaskStartScheduler() 后,只有一个任务在执行,甚至没有任何任务在执行, 那么这可能是因为中断向量表不正确。
所有 FreeRTOS 端口都使用定时器中断,一些 FreeRTOS 端口使用 多个中断。 使用提供的演示项目作为示例。
针对 ARM Cortex-M 用户的特别提示: ARM Cortex-M3、ARM Cortex-M4 和 ARM Cortex-M4F 端口要求 FreeRTOS 处理程序 安装在 SysTick、 PendSV 和 SVCCall 中断向量上。 可以 将 FreeRTOS 定义的 xPortSysTickHandler(), xPortPendSVHandler() 和 vPortSVCHandler() 函数直接填入向量表的对应位置,或者如果 中断向量表与 CMSIS 相容,可以将以下三行 添加到 FreeRTOSConfig.h,用于将 FreeRTOS 函数名称映射到 其对应的 CMSIS 名称。
#define vPortSVCHandler SVC_Handler #define xPortPendSVHandler PendSV_Handler #define xPortSysTickHandler SysTick_Handler
目前,栈溢出是最常见的支持请求原因。 任务可用堆栈 的大小是使用 xTaskCreate() 的 usStackDepth 参数 或 xTaskCreateStatic() API 函数来设置的。
对于造成问题的任务, 尝试增加为它分配的堆栈大小,或减少它利用的堆栈数量。 请不要编写需要大量堆栈的 中断服务程序。
调用任何字符串格式化函数的任务可能需要很多堆栈,尤其是在使用 GCC 编译器时。 这种任务很容易产生栈溢出。
创建任务时,任务堆栈的每个字节都被设置为 0xa5,因此比较容易发现是否产生了栈溢出。 此外,task.c 中的函数 usTaskCheckFreeStackSpace() 演示了 如何在运行时检查堆栈使用情况(不过这个函数效率较低,因此应当仅用于调试)。
如果在启动调度器之前调用了一个 FreeRTOS API 函数, 那么中断将维持在禁用状态,直到第一个任务开始执行 才重新启用。 这是为了保护系统。因为在系统初始化期间、调度器启动之前、启动器处于不一致状态时, 中断试图使用 FreeRTOS API 函数 可能导致故障, 从而对系统产生影响。
更改微控制器中断启用位或优先级标志时, 请不要使用除调用 taskENTER_CRITICAL() 和 TASKEXIT_CRITICAL() 以外的任何方法。 这些宏对它们的调用嵌套深度进行计数, 以确保只有在调用嵌套已完全展开后 才重新启用中断。 请注意,某些库函数本身可能会启用和禁用 中断。
要纠正这一点,需增加堆空间,或删除一些演示应用程序任务。
ARM Cortex-M3、ARM Cortex-M4 和 ARM Cortex-M7 用户,请注意: 这是 ARM Cortex-M 设备 95% 的支持请求的原因:
[还提供了一个单独的页面,解释了 ARM Cortex-M 的中断优先级, 并提供了关于设置 ARM Cortex-M 中断优先级 以用于强大的 FreeRTOS 中断嵌套模型的全部信息]。
如果中断的优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY 的设置, 那么就无法从此中断中调用 API 函数。 设置中断优先级时,请注意以下几点:
如果在启动调度器之前调用了一个 FreeRTOS API 函数, 那么大部分 FreeRTOS 端口将禁用中断,直到第一个任务开始执行 才重新启用。 这是为了保护系统。 因为在系统初始化期间、调度器启动之前, 中断试图使用 FreeRTOS API 函数可能导致故障, 从而对系统产生影响。
在 RTOS 调度器启动之前,许多 API 函数都无法调用。 这种做法最好仅用于创建那些 在 RTOS 调度器开始运行后立即被使用的任务、队列和信号量。