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

问题描述 投票:0回答:2

我目前正在为ARM Cortex 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任务永远不会结束,因为它有代码来触发for(;;)循环中的LED。

这引出了我的问题:当我实施上述内容时,我们看到了两个令人费解的观察结果:

观察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();
    }
}
stm32 freertos
2个回答
0
投票

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

在此页面上搜索“Daemon Task Startup Hook”:https://www.freertos.org/a00016.html

2)如果在(;;)循环的无限中没有放置任何内容,那么该任务将只运行一次(循环外的代码,比如初始化外设一次)

如果您这样做,那么您必须在其实现结束时删除该任务(调用vTaskDelete(NULL))。 https://www.freertos.org/implementing-a-FreeRTOS-task.html

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


0
投票

我担心你的观察是错误的

  1. 如果优先级较低的任务没有给出控制权或者中断例程没有唤醒优先级较高的任务 - 任务可能会更新获得控制权。
  2. 这里队列中没有任何类似位置的东西。它不是Linux或Windows。
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.