0
votes

I'm currently working on developing some software for a project on a ARM Cortext M4 MCU, where three overall main tasks need to be executed:

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

I've decided to experiment around with the usage of FreeRTOS to see if there's any benefits in using FreeRTOS scheduling over a simple infinite While(1) loop

Based on what I've read from the documentation so far (correct me if I'm wrong),

1) FreeRTOS runs tasks based on priority - if no interrupts or stop conditions are coded into the highest priority task, any task of lower priority will never get queued and run

2) If nothing is placed in the infinite for(;;) loop, that task will only run once (the code outside the loop, say to initialise the peripherals once)

Since FreeRTOS selects and queues tasks by priority, the initial solution i came up with in assigning and creating tasks was this:

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 

Upon testing this, if FreeRTOS logic follows, I should expect to never see Task1.c nor Task2.c queued, since Init_all.c task will never end as it has code to trigger the LED within the for(;;) loop.

Which leads me to my question: Two puzzling observations were seen when I implemented the above:

Observation 1:

1) Init_all.c task runs

2) Followed by Task1.c which then gets interrupted and stopped immediately for 10 seconds.

3) During which, Task2.c runs till the 10 seconds are up. Then Task1.c takes over and runs the code after the vTaskDelay( xDelay6000ms ) interrupt.

All this while, Init_all.c is still running, but idk at what position of the queue it is at all. The LED does indeed trigger every second, but again, pure confusion on why Init_all.c task is even running.

The code for Task1.c is as below to provide a better illustration:

// 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 )

        }

Observation 2:

Task2 takes 1 second to run, so it should theoretically run 10 times in the 10 seconds window it is given by the interrupt.

However, I'd see a strange result where Task2 sometimes ran 9 times, then 10 times.

Am i understanding the FreeRTOS concepts wrongly? Thanks! Code is below:

Init_all.c task:

void StartDefaultTask(void const * argument)
{

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

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

Task1:

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();
    }
}

Task 2:

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


    // All Initialisation
    for( ;; )
    {
        takesensor3data();
        takesensor4data();
    }
}
2
You'd have to provide all code that configures tasks and code of each task. Code of just Task1 is not enough information to determine what's actually happening in your system.Jacek Ślimok
Sorry bout that, code's been updatedMack

2 Answers

0
votes

Init_all.c - Must run first and ONLY once at startup

Search for "Daemon Task Startup Hook" on this page: https://www.freertos.org/a00016.html

2) If nothing is placed in the infinite for(;;) loop, that task will only run once (the code outside the loop, say to initialise the peripherals once)

If you do that then you must delete the task (call vTaskDelete(NULL)) at the end of its implementation. https://www.freertos.org/implementing-a-FreeRTOS-task.html

As to your main question - you don't show the code of the init task so its impossible to say. However generally this kind of system is implemented to be event driven, so most tasks spend most of their time in the blocked state (not using any cpu so lower priority tasks can execute).

0
votes

I afraid your observations are wrong

  1. If lower priority task is not giving back control or the interrupt routine is not waking up the higher priority task - the task may newer get the control.

  2. There is no anything like position in the queue here. It is not Linux or Windows.