任务在循环调度中表现不正确

scr*_*lli 6 operating-system scheduling round-robin freertos stm32f4discovery

我在 STM32F4DISCOVERY 板上运行 FreeRTOS,我有以下代码:

xTaskCreate( vTask1, "Task 1", 200, NULL, 1, NULL );
xTaskCreate( vTask2, "Task 2", 200, NULL, 1, NULL );
vTaskStartScheduler();
Run Code Online (Sandbox Code Playgroud)

其中 vTask1 是这个函数:

void vTask1( void *pvParameters )
{
volatile unsigned long ul;

    for( ;; )
    {
        LED_On(0);

        for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
        {
        }
        LED_On(2);
        LED_Off(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

vTask2 有几乎相同的代码:

void vTask2( void *pvParameters )
{
const char *pcTaskName = "Task 2 is running\n";
volatile unsigned long ul;

    for( ;; )
    {
        LED_On(3);
        LED_Off(2);
        for( ul = 0; ul < mainDELAY_LOOP_COUNT; ul++ )
        {
        }

        LED_Off(3);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行程序时,我看到 LED0 和 LED3 一直亮着(它们的切换对我的眼睛来说太快了,这很好),而“共享资源”LED2 闪烁得非常快。问题是这样的:当我颠倒顺序时xTaskCreate调用,我遇到了相同的情况,LED2 的闪烁行为不同,但速度要慢得多。为什么会发生这种情况,因为任务应该具有相同的优先级并因此遵循循环调度?他们不应该得到相同的时间吗?为什么他们的行为只是在以不同的顺序创建之后发生变化?

提前致谢。

小智 1

rtos 不会尝试循环执行任务,您不应期望它们按任何特定顺序执行。正如 iama 在评论中指出的那样,您创建的两个任务都没有延迟。不要通过在 for 循环中烧毁无操作来创建延迟,而是使用延迟函数。这将允许 while(1) 循环中的代码执行,然后返回到 RTOS,以便处理器可以运行其他任务,直到等待时间过去。如果您需要同步工作,您可能只想将其保留在单个任务中。如果您的一项任务依赖于另一项任务的完成,您可能需要使用信号量、队列或其他跨线程通信方法。

你的代码让我想起了我从 main 中使用 while(1) 循环过渡到 rtos 的情况。如果您刚开始使用 RTOS,ST 的这份指南看起来会是一个很好的介绍https://www.st.com/resource/en/user_manual/dm00105262-developing-applications-on-stm32cube-with-rtos-意法半导体.pdf

另外,不要依赖延迟函数来进行细粒度定时;请改用定时器驱动的中断。上面的链接应该可以让您更好地理解为什么我可以在这篇文章中进行管理。

ST 还应该在某个地方有示例项目,这对于参考或用作您自己的项目的起点是很好的。