First, What Is It
- RTOS (Real-Time Operating System): an operating system that makes several "tasks" appear to run at the same time; FreeRTOS is the most popular one in embedded systems.
- Task: an independent piece of functionality (e.g., "read sensor", "handle button", "send network data"), each with its own stack.
- Scheduler: the referee deciding "who gets the CPU now", switching tasks by priority and time slice.
- Why it matters: task state machines, priorities, and "semaphore vs mutex" are nearly guaranteed exam/interview topics, and the path from bare-metal loops to complex projects runs through RTOS.
Breaking Down the Principle
1. Task State Machine
| State | Meaning | Uses CPU? |
|---|---|---|
| Running | Executing now | Yes |
| Ready | Queued, waiting for the scheduler | No |
| Blocked | Waiting for event/delay/queue | No (no busy wait) |
| Suspended | Suspended; must be resumed manually | No |
Blocked is the key to low power: a waiting task yields the CPU instead of spinning.
2. Preemptive Scheduling: Higher Priority First
FreeRTOS is preemptive by default: when a higher-priority task becomes ready, it immediately preempts the running lower-priority task. Therefore:
- A larger priority number means higher priority (the opposite of some other RTOSes — mind the convention).
- Tasks of the same priority share the CPU by time slicing (each runs one tick, then switches).
- Scheduling happens at switch points: task blocks/exits, time slice expires, or a higher-priority task becomes ready (including scheduling from an ISR).
3. Inter-Task Communication and Synchronization
Tasks cannot simply "share a global variable and be done" — synchronization mechanisms are needed:
| Mechanism | Essence | Typical use |
|---|---|---|
| Queue | Data pipe; producer puts, consumer takes | UART data to a processing task |
| Semaphore | Counter; Give/Take | Event notification, resource counting |
| Mutex | Only one task holds it at a time | Protecting shared resources (e.g., same Flash) |
| Event group / task notification | Bit flags / direct notify | Multi-condition triggers, lightweight wake-up |
Semaphore vs mutex (a top interview question):
- A semaphore is a "counter + notification"; it does not care who gives/takes, good for "event happened" notifications.
- A mutex has ownership (whoever takes it must release it) and supports priority inheritance, for protecting critical resources.
- Misuse (using a mutex as a semaphore or vice versa) can cause deadlocks or logic errors.
4. Critical Sections and Priority Inversion
- Critical section: code accessing shared resources, protected by disabling interrupts or holding a lock, to prevent task switches from corrupting data.
- Priority inversion: a low-priority task holds a lock while a high-priority task waits — the high-priority task is effectively "held back" by the low one. FreeRTOS mutexes mitigate this with priority inheritance (temporarily raising the lock holder to the waiter's priority so it releases quickly).
- Deadlock: two tasks each hold a lock and wait for the other's. Prevention: consistent lock order, timeouts, avoid nested locks.
How the SDK Implements It
- Related pages: FreeRTOS OS, Shell
The SDK example skeleton is a typical RTOS program: main() creates a task and starts the scheduler, which never returns:
xTaskCreate(app_start_task, "app_start", 1024, NULL,
configMAX_PRIORITIES - 2, &app_start_handle);
/* Start the scheduler; tasks begin running and this never returns */
vTaskStartScheduler();Communicating with queues/semaphores and yielding with vTaskDelay is the basic "taskified" style.
Common Exam & Interview Questions
In FreeRTOS, does a larger priority number mean higher or lower priority?
Larger number = higher priority (opposite of some RTOSes); same-priority tasks use time slicing.
Difference between Blocked and busy-waiting?
A blocked task yields the CPU so the scheduler runs other tasks (and the system can sleep); a busy while-loop keeps spinning and wastes CPU.
Difference between a semaphore and a mutex?
A semaphore is a counting/notification mechanism without ownership; a mutex has ownership, supports priority inheritance, and is meant to protect critical resources against priority inversion.
What is priority inversion and how does FreeRTOS mitigate it?
A low-priority task holding a lock blocks a high-priority task. FreeRTOS mutexes use priority inheritance — temporarily raising the holder's priority to the waiter's so it releases quickly.
Why disable interrupts in a critical section?
If a task switch or interrupt occurs while sharing variables, data can be corrupted. Entering a critical section (disabling interrupts) makes the code atomic; mutexes protect shared resources similarly.
Have questions?
For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

