I am retaking my learning of FreeRTOS and I realized something while I was writing my program, I am triggering tasks using timestamps and global variables shared between them, I think this is not a good practice because it makes no sense to have notifications and delay functions and not use them, but what is the technical reason to consider this a bad practice?, is because I am wasting CPU cycles in a task that should be blocked instead running waiting for data that may takes minutes or hours to be updated? or there is something else I am missing?
this is an example of my program:
case A: shared variable
task a ()
if (water_flow >= 800)//could take some minutes to get this value
task b ()
water_flow = read_adc();
case B: timestamp
same as case A but with a periodic task, the task c improved is the correct way because I am saving CPU cycles ?
task c ()
if ((HalGetTick() - timestamp) >= 1800000)//wait for 30 min
timestamp = HalGetTick();
task c improved()
vTaskDelay(pdMS_TO_TICKS(1800000));//blocked for 30 min
Running all tasks not giving up the CPU polling for something relies on preemption by the scheduler at time slice intervals and requires that all tasks have the same priority.
This makes your task far less responsive (worst case: 1 time slice), since they don’t react on events when they occur and getting signaled.
Also you can’t prioritize tasks resp. functionality but that’s often the case. Some functions are more important than others and could require an immediate response/handling.
This design is not optimal as you can easily see and doesn’t scale well when applications getting more complex.
As Hartmut says, tasks that “spin wait” and not block will just consume CPU time and prevent ANY task of a lower priority from running, and other tasks of the same priority will need to wait for the next Tick interrupt to get switched (if you have enabled the Round-Robin scheduler).
A basic rule, tasks MUST “Block” (wait on some FreeRTOS primitive, or be in a vTaskDelay) when they don’t have something to do. The two possible exceptions are:
Tasks at Idle priority, can sometimes be allowed to continually run, if round-robin execution is enabled, or they periodically yield.
a spin-wait that will be very short, like of the order of a task-switch operation, can be allowed.
It is just barely acceptable for a task to do a check a value, and if not ok, delay a short bit then check again, as this wastes a lot of computer resources switching to the task just to need to switch away, but sometimes that is all that can be done.
It isn’t just “wasting” the cycles, but that the task may be taking them from some other operation that really wanted to get done. If you really have the cycles to waste, it might have been better to not use a RTOS at all, but just use a big ol loop method, which can be simpler if the requirements allow it.