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();
}
}
Task1
is not enough information to determine what's actually happening in your system. – Jacek Ślimok