26. April 2021 · Categories: Software

Typically, freeRTOS uses preemptive multitasking, which can lead you to needing to guard anything shared between the tasks. That is prone to mistakes, and thus I prefer to use cooperative multitasking instead.

There is an option, configUSE_TIME_SLICING, that can disable time slicing, but it only prevents the scheduler from interrupting the current task with another task of the same priority. The kernel still switches to another task of the same priority when a higher priority tasks interrupts, and then returns to another task. So the option does not provide protection from getting interrupted, it just removes some overhead. A better implementation would allow to set the number of ticks per time slice, in case you want high precision in the timers, but also avoid the overhead of very short slices.

We can provide correct cooperative multitasking in the following ways:

  • Timers: They all run in one task, but then a long task could block.

  • Event task: You have one central event queue, and the main program just processes these events. This is also recommended for timers, use the timer tasks to post to the event queue, and so prevent blocking from longer processing.

  • Global Mutex: a mutex protects the main data structures, and all tasks just take it when doing work. You then must yield regularly to allow the other tasks to proceed. That would be a sequence of xSemaphoreGive( xLock); vTaskDelay( 0); xSemaphoreTake( xLock, portMAX_DELAY);

To reduce time slicing, add an option configTICKS_PER_TIMESLICE that defaults to 1, and the following code to tasks.c. I modified version 10.4.3.