关于FreeRTOS如何在STM32平台上对任务进行排队的一些困惑

时间:2019-04-11 04:03:37

标签: stm32 freertos

我目前正在为ARM Cortext M4 MCU上的项目开发一些软件,其中需要执行三个总体主要任务:

1) Init_all.c - Must run first and ONLY once at startup
2) Task1.c  - Runs infrequently; Once every 10 seconds
3) Task2.c  - Must run most frequently

我决定尝试使用FreeRTOS,以查看通过简单的无限While(1)循环使用FreeRTOS调度是否有好处

根据我到目前为止从文档中所读的内容(如果我输入错了,请纠正我)

1)FreeRTOS根据优先级运行任务-如果没有将中断或停止条件编码为优先级最高的任务,任何优先级较低的任务将从不排队并运行

2)如果在无限for(;;)循环中未放置任何内容,则该任务将仅运行一次(循环外的代码说一次初始化外围设备)

由于FreeRTOS按优先级选择任务并对其进行排队,所以我在分配和创建任务时想到的最初解决方案是:

1) Init_all.c - Highest priority; for(;;) loop only contains code to trigger LED
2) Task1.c  - Second highest priority **but** I include a 10 second interrupt vTaskDelay( xDelay10000ms ) right at the start of the for(;;) loop
3) Task2.c  - Lowest priority 

对此进行测试,如果遵循FreeRTOS逻辑,我应该期望永远不会看到Task1.c或Task2.c排队,因为Init_all.c任务永远不会结束,因为它具有触发LED的代码在for(;;)循环中。

哪个使我想到了我的问题:实施上述方法时,发现了两个令人费解的发现:

观察1:

1)运行Init_all.c任务

2)跟在Task1.c之后,然后它被中断并立即停止10秒钟。

3)在此期间,Task2.c一直运行到10秒钟为止。然后Task1.c接管vTaskDelay( xDelay6000ms )中断后运行代码。

所有这一切,Init_all.c仍在运行,但idk处于队列的什么位置。 LED确实确实会每秒触发一次,但又一次完全混淆了为什么什至Init_all.c任务还在运行。

Task1.c的代码如下,以提供更好的说明:

// Task1.c
void Task1(void const * argument)
    {
        // Timer interrupt
        const TickType_t xDelay10000ms = pdMS_TO_TICKS( 10000 );

        for( ;; )
        {
            /** Immediately block this task for 10secs upon starting it **/
            vTaskDelay( xDelay10000ms );
           ( code below to execute AFTER the Task1 resumes from the interrupt )

        }

观察2:

Task2需要1秒钟才能运行,因此理论上应该在10秒窗口(由中断指定)中运行10次。

但是,我看到一个奇怪的结果,Task2有时运行9次,然后运行10次。

我误解了FreeRTOS概念吗?谢谢!代码如下:

Init_all.c任务:

void StartDefaultTask(void const * argument)
{

      init_sensor1();
      init_sensor2();
      init_sensor3();
      init_sensor4();

      for( ; ; )
      {
          GREEN_LED_ON();
          osDelay(50);
          GREEN_LED_OFF();
          osDelay(1000);
      }
}

任务1:

void Task1(void const * argument)
{
    // Timer interrupt
    const TickType_t xDelay6000ms = pdMS_TO_TICKS( 6000 );


    // All Initialisation
    for( ;; )
    {
        // Timer interrupt this task to ensure apptasks.c finishes first?
        vTaskDelay( xDelay6000ms );
        takesensor1data();
        takesensor2data();
    }
}

任务2:

void Task2(void const * argument)
{
    // Timer interrupt
    const TickType_t xDelay6000ms = pdMS_TO_TICKS( 6000 );


    // All Initialisation
    for( ;; )
    {
        takesensor3data();
        takesensor4data();
    }
}

2 个答案:

答案 0 :(得分:0)

  

Init_all.c-必须首先运行,并且只能在启动时运行一次

在此页面上搜索“守护程序任务启动挂钩”:https://www.freertos.org/a00016.html

  

2)如果在无限for(;;)循环中没有放置任何内容,则该任务将仅运行一次(循环外的代码说一次初始化外围设备)

如果执行此操作,则必须在执行结束时删除该任务(调用vTaskDelete(NULL))。 https://www.freertos.org/implementing-a-FreeRTOS-task.html

关于您的主要问题-您没有显示init任务的代码,因此无法说明。但是,通常这种系统是由事件驱动的,因此大多数任务大部分时间都处于阻塞状态(不使用任何CPU,因此可以执行优先级较低的任务)。

答案 1 :(得分:0)

我怕你的观察是错误的

  1. 如果较低优先级的任务没有交出控制权,或者中断例程没有唤醒较高优先级的任务,则该任务可能会较新地获得控制权。

  2. 这里的队列中没有类似位置的东西。它不是Linux或Windows。