FreeRTOS Deep Dive · Part 1 of 8
Scheduler, Priorities & Context Switch
55:30
Part 1 / 8
🧠 FreeRTOS Deep Dive Series · 8 Parts
Part 1 of 8
Part 01
Scheduler, Priorities & Context Switch
55:30
Part 02
Task Notifications vs Event Groups
38:15
Part 03
Software Timers & Idle Hook Patterns
29:44
Part 04
Queues, Semaphores & Mutexes
42:18
Part 05
Memory Management & Heap Models
36:50
Part 06
Stack Sizing & Overflow Detection
31:20
Part 07
Low-Power RTOS & Tickless Idle
44:05
Part 08
Debugging & Trace with Tracealyzer
50:40
01
Overview
This is the foundation of the entire FreeRTOS series. Before you can use queues, mutexes, or timers you need to understand how the scheduler works, how tasks are created, and exactly what happens during a context switch on ARM Cortex-M. Everything else builds on this.
- Create and delete FreeRTOS tasks using
xTaskCreate() - Understand priorities, the ready list, and how the preemptive scheduler selects tasks
- Measure context switch overhead on real hardware with an oscilloscope
- Know when to use
vTaskDelay()vsvTaskDelayUntil()for jitter-free periodic tasks
02
How the Scheduler Works
FreeRTOS uses a fixed-priority preemptive scheduler. At every tick interrupt (typically every 1ms), it checks whether a higher-priority task has become ready. If one has, it immediately context-switches to it. Equal-priority tasks share the CPU in round-robin.
Running
The one task executing on the CPU right now. Only one runs at a time on single-core.
eRunning
Ready
Able to run, waiting for the CPU. Scheduler picks the highest-priority ready task.
eReady
Blocked
Waiting for a delay, queue item, or semaphore. Zero CPU usage while blocked.
eBlocked
03
Code
01
Creating tasks with prioritiesmain.c
C
void vHighTask(void *pv), vLowTask(void *pv); int main(void) { HAL_Init(); SystemClock_Config(); // xTaskCreate(func, name, stack_words, param, priority, handle) xTaskCreate(vHighTask, "High", 256, NULL, 3, NULL); xTaskCreate(vLowTask, "Low", 256, NULL, 1, NULL); vTaskStartScheduler(); while(1); } void vHighTask(void *pv) { TickType_t xLast = xTaskGetTickCount(); while(1) { HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12); // Exact 100ms period — compensates for execution time vTaskDelayUntil(&xLast, pdMS_TO_TICKS(100)); } } void vLowTask(void *pv) { while(1) { DoBackgroundWork(); // 500ms AFTER execution — period drifts vTaskDelay(pdMS_TO_TICKS(500)); } }
vTaskDelayUntil vs vTaskDelay
Use
vTaskDelayUntil() for periodic tasks — it absorbs execution time to maintain a fixed period. vTaskDelay() adds delay after the current run, so period drifts under load.Continue the Series
Work through all 8 parts of the FreeRTOS Deep Dive to master real-time embedded systems programming.