1. Basic Concepts
<span>FreeRTOS</span>
(Free Real-Time Operating System) is a lightweight open-source real-time operating system designed for embedded devices. It was developed by <span>Real Time Engineers Ltd.</span>
and was acquired by Amazon in 2017, becoming part of Amazon FreeRTOS. FreeRTOS supports various architectures such as <span>ARM Cortex-M</span>
, <span>RISC-V</span>
, <span>AVR</span>
, and <span>MIPS</span>
, and is widely used in industrial control, IoT, automotive electronics, and other fields.
2. Why Use FreeRTOS
In a single-task bare-metal program, all functions are executed sequentially, leading to high time uncertainty and poor scalability. By using <span>FreeRTOS</span>
, system functions can be divided into multiple “tasks” that are managed by the <span>RTOS</span>
for unified scheduling, achieving:
- Concurrent execution of multiple tasks
- Task priority control
- Inter-task communication and synchronization
- Timer management
- Low-power idle handling
3. Core Concepts
3.1. Tasks
In <span>FreeRTOS</span>
, a **task** is an independently executing function, which can be understood as a lightweight thread. Each task has its own execution flow, stack space, priority, and state. <span>FreeRTOS</span>
is responsible for scheduling these tasks to make them appear to run “concurrently”.
Task States
<span>Running</span>
: The task currently running<span>Ready</span>
: Can run but has not been scheduled<span>Blocked</span>
: Waiting for resources such as delays, semaphores, queues, etc.<span>Suspended</span>
: Suspended and not participating in scheduling<span>Deleted</span>
: Deleted and waiting for resource recovery
Priority Scheduling
<span>FreeRTOS</span>
uses <span>preemptive scheduling</span>
by default: the system always runs the highest priority Ready task.
- If there are multiple tasks with the same priority, they will
<span>execute in turn</span>
(time-slice scheduling) - The range of task priorities is defined by
<span>configMAX_PRIORITIES</span>
(usually 5 to 10)
When to Switch Tasks
- A higher priority task becomes
<span>Ready</span>
; - The current task calls a blocking
<span>API</span>
(such as<span>vTaskDelay()</span>
,<span>xQueueReceive()</span>
); - The task is suspended or deleted;
<span>Tick</span>
interrupt triggers time-slice rotation (for tasks of the same priority)
3.2. Scheduler
<span>FreeRTOS</span>
scheduler is a task scheduling kernel module that controls which task can run in the system and when.
In simple terms:
- Multiple tasks are “arranged” by the scheduler to run on the MCU;
- Although the MCU is single-core, the scheduler continuously switches tasks to make them **”appear to execute simultaneously”**.
Scheduling Strategies
<span>FreeRTOS</span>
supports two scheduling methods: cooperative scheduling and preemptive scheduling.
- Cooperative Scheduling: Mainly used on resource-constrained devices, it is rarely used now. For this reason, the FreeRTOS official will no longer maintain this module in the future, but it will be retained.
- Preemptive Scheduling
- Higher priority tasks always execute first;
- Currently running lower priority tasks can be interrupted;
Time-Slice Rotation
- If multiple tasks have the same priority, they execute in turn through time-slice rotation. Each system Tick interrupt, if the current task’s execution time is up, the scheduler will switch to the next ready task.
3.3. Queues
<span>FreeRTOS</span>
queues are one of the most commonly used inter-task communication (<span>IPC</span>
) mechanisms, allowing safe data transfer between tasks and between interrupts and tasks. They not only ensure data synchronization but also enable blocking and scheduling switching.
FreeRTOS queues are a <span>thread-safe circular buffer</span><code><span> used for:</span>
- Data transfer between tasks;
- Synchronizing information between interrupts and tasks;
- Simultaneously serving as both “message buffer + synchronization signal”.
3.4. Semaphores
In FreeRTOS, **semaphores** are one of the core mechanisms for task synchronization and resource management. Unlike queues, they do not transfer data but are used for “sending signals” or “access control”.
Semaphores are objects used for synchronization or mutual exclusion control, and are fundamentally based on queue mechanisms. Their types mainly include:
-
Binary Semaphore: Synchronization between tasks or between interrupts and tasks
- Value range: Only 0 or 1
- Function: Similar to
<span>event flags/signal notifications</span>
- Application: Used for interrupt notifications to tasks or inter-task synchronization
-
Counting Semaphore: Controls the number of resources (e.g., connection pool)
- Value range: 0 to a set maximum value
- Function: Represents “number of available resources”
- Application: Controls access to multiple resources (e.g., fixed number of buffers)
-
Mutex Semaphore: Mutual exclusion protection for critical resources (with priority inheritance)
- Function: Protects critical sections to prevent concurrent access
- Characteristics: Includes a priority inheritance mechanism
- Application: Used to prevent competition for shared resources, such as serial ports, LCDs, etc.
- If a low-priority task holds a mutex semaphore and a high-priority task is waiting, the low-priority task will “temporarily raise its priority” to prevent priority inversion.
3.5. Mutexes
In FreeRTOS, a mutex (<span>Mutex</span>
) is a synchronization mechanism used to protect critical resources from being accessed simultaneously by multiple tasks, functionally similar to a binary semaphore (<span>Binary Semaphore</span>
), but with stronger features, especially the priority inheritance mechanism, designed for preemptive multi-tasking systems.
It is important to note that <span>mutexes should not be used in interrupts</span>
.
Priority Inversion Problem
Assume:
- Task A (low priority) holds a mutex;
- At this time, high-priority task B also wants to acquire this lock but is blocked;
- The system scheduler continues to run other medium-priority tasks, and B can never get the CPU
This leads to the problem of high-priority tasks being blocked by low-priority tasks.
FreeRTOS’s Mutex Built-in “Priority Inheritance Mechanism”
- If task A holds the lock and a higher priority task B is waiting for that lock, A’s priority will be “temporarily raised” to B’s level;
- Only after task A releases the lock will its priority return to normal;
- This ensures that high-priority tasks do not “starve”.
3.6. Time Management
In <span>FreeRTOS</span>
, time is counted in <span>Ticks</span>
, not in milliseconds or seconds.
<span>Tick</span>
is generated by the system tick clock timer periodic interrupt;- Each interrupt increments the internal
<span>Tick</span>
counter of<span>FreeRTOS</span>
by +1; - All time-related operations are based on
<span>Ticks</span>
.
Delay Functions
<span>vTaskDelay()</span>
: Delays the task for a specified number of Ticks, starting from the current time.- During the delay, the task is in a Blocked state, and the CPU will switch to other ready tasks.
<span>vTaskDelayUntil()</span>
: Recommended for periodic tasks, used to maintain a fixed time interval.- Benefit: Even if the previous periodic task runs slowly, the next one will try to compensate for the time difference, keeping the periodicity more accurate.
Timeout Waiting Mechanism
- Many blocking functions (such as
<span>xQueueReceive</span>
,<span>xSemaphoreTake</span>
) support timeout waiting.
Software Timers
- Software timers allow you to automatically execute callback functions at a future point in time without manually creating a task.
Tickless Mode
In low-power applications, FreeRTOS can be configured to operate in Tickless mode, which means:
- When the idle task runs, the system will “pause” the SysTick;
- Save power, suitable for power-sensitive scenarios;
- Upon waking, adjust the global Tick counter based on sleep time.
Previous Recommendations
RECOMMEND
[1]. 【Embedded Layered Design】Streamlined and Efficient Engineering Structure
[2]. 【Embedded Network Development】: Powerful IP Commands
[3]. Mastering the Open-Closed Principle: Building Flexible and Stable Software Architecture
[4]. 【Embedded Layered Design】Streamlined and Efficient Engineering Structure
I am Aike, an embedded software engineer.
Follow me for more embedded insights.
Remember to like, share, and click “see”
Your encouragement is my greatest motivation to continue sharing!
See you next time.
Looking forward to your
sharing
likes
views
NEWS
WeChat ID|aike_eureka
Baijiahao|Mastering Embedded Systems