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.
379 380 381 382 383 |
PRIVILEGED_DATA static TaskHandle_t xIdleTaskHandle = NULL; /*< Holds the handle of the idle task. The idle task is created automatically when the scheduler is started. */ #if ( configTICKS_PER_TIMESLICE > 1) PRIVILEGED_DATA static volatile TickType_t xTicksInTimeSlice = 0; #endif |
2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 |
#if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) #if ( configTICKS_PER_TIMESLICE > 1) { if( xTicksInTimeSlice == 0) { xTicksInTimeSlice = configTICKS_PER_TIMESLICE; if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 ) { xSwitchRequired = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } xTicksInTimeSlice--; } #else /* ( configTICKS_PER_TIMESLICE > 1) */ { if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB->uxPriority ] ) ) > ( UBaseType_t ) 1 ) { xSwitchRequired = pdTRUE; } else { mtCOVERAGE_TEST_MARKER(); } } #endif /* ( configTICKS_PER_TIMESLICE > 1) */ |