2023-05-04 06:06 AM
Started learning FREERTOS and ran into a problem.
I showed 3 pieces of code of the same tasks.
All 3 pieces of code work differently.
Code 1
void Task1(void *argument)
{
int j = 0;
for(;;)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
for(j=0; j<10000000; j++);
}
}
void Task2(void *argument)
{
int i = 0;
for(;;)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);
for(i=0; i<10000000; i++);
}
}
Why does the blinking order of the LEDs start to change over time?
For example: first the PB0 LED lights up first, then the PB14. After a few periods, the PB14 LED starts to light up first.
Code 2
void Task1(void *argument)
{
for(;;)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
for(int j=0; j<10000000; j++);
}
}
void Task2(void *argument)
{
for(;;)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);
for(int i=0; i<10000000; i++);
}
}
Then the blinking of the LEDs is strange.
Example: Sometimes the PB0 LED may turn on first, then turn off first.
Code 3. I made the variables j and i global.
void Task1(void *argument)
{
for(;;)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
for(int j=0; j<10000000; j++);
}
}
void Task2(void *argument)
{
for(;;)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);
for(int i=0; i<10000000; i++);
}
}
The work seems to be normal.
The two LEDs flash simultaneously.
Code optimization is disabled.
Why is this happening?
Solved! Go to Solution.
2023-05-04 11:13 AM
I offered you an explanation for what you consider "strange" behavior. As to why the behavior changes depending on how/where you declare the loop variables, that likely generates slightly different code, which causes the loops to count at slightly different speeds. Which interacts with the non-exact timing of the task switching mechanism differently.
If you want to enforce a sequence of events between two tasks you need to use semaphores ad/or mutexes. Plain old spin loops can never do that.
2023-05-04 08:10 AM
I presume both tasks have the same priority, otherwise the lower priority task would never run. If that is true, then FreeRTOS is using round-robin scheduling to run each task. It runs one task for a time slice, then switches to the other task. The amount of time each task gets to run is not EXACTLY the same due to interrupt overhead, etc. That will affect the actual delay provided by your for() loops.
Using for() loops like that for delays is almost always a bad idea. Use osDelay() if using the CMSIS wrapper, or vTaskDelay() for direct FreeRTOS calls.
2023-05-04 10:55 AM
Why does the program work depends on the method of creating variables.
Do not understand why. Very big difference in performance
I think this should not be.
I don't want to accept Delay functions.
My goal is not to blink LEDs, but to understand how tasks work.
2023-05-04 11:13 AM
I offered you an explanation for what you consider "strange" behavior. As to why the behavior changes depending on how/where you declare the loop variables, that likely generates slightly different code, which causes the loops to count at slightly different speeds. Which interacts with the non-exact timing of the task switching mechanism differently.
If you want to enforce a sequence of events between two tasks you need to use semaphores ad/or mutexes. Plain old spin loops can never do that.
2023-05-04 12:39 PM
And rooooot ROOT cause is learn asm and hardware architecture. Every declared in func is placed into regs, irelevant to optimize levels. Then on risc code increment and toggle can be run in parallel usw.
Declaration global change all with add store mem asm ...