FreeRTOS is generally used in hardware designs where there are certain limitations on RAM size (cost, resources, performance-to-power ratio, etc.). It is one of the most widely used real-time operating systems today. Choosing FreeRTOS for project applications generally considers the following aspects:
-
Real-time (time constraints): Like most RTOS, at each clock tick, ready high-priority tasks will preempt the CPU (FreeRTOS is a real-time scheduler, and projects are built on this kernel to meet hard real-time applications).
-
Determinism (predictability): Tasks are switched between at specified times, completing necessary work within a limited time, and the execution time of low-priority tasks is predictable.
-
Open-source and free: Compared to other paid RTOS, FreeRTOS is open-source and free.
-
RAM usage: FreeRTOS occupies a small amount of RAM (can run with 2K~3K).
-
Task management: Supports both task preemption and time-slicing.
Based on these characteristics, FreeRTOS is widely used in systems with certain real-time requirements and resource limitations, extensively applied in the automotive industry, consumer electronics, network services, and in MCU chips, DSP chips, and customized SOC chips.
2. Task States
Tasks in FreeRTOS are similar to processes in Linux, serving as units for system scheduling and execution in real-time operating systems. For a single-core CPU, at any moment, only one task is executed.
Tasks in FreeRTOS are mainly divided into the following states:
-
Running
-
Ready
-
Blocked
-
Suspended
The relationship between task states in FreeRTOS can be referenced in the following diagram:

3. Task Scheduling
The task scheduling method in FreeRTOS adopts a combination of preemptive scheduling and time-slicing. The system defaults to enabling both methods. Tasks of different priorities use preemptive scheduling, while tasks of equal priority use time-slicing scheduling. By configuring the value of configUSE_TIME_SLICING, one can choose to enable or disable time-slicing. Therefore, FreeRTOS provides a time-sliced preemptive scheduling algorithm when time-slicing is enabled and a non-time-sliced preemptive scheduling algorithm when time-slicing is disabled. Additionally, FreeRTOS provides the taskYIELD() interface for tasks in the running state to enter a blocked state or for running tasks to call for rescheduling.
The task scheduling process in FreeRTOS mainly consists of the task creation phase, the task scheduler startup phase, and the normal operation phase after the task scheduler starts. The following is an example based on the ARM Cortex-M4 series platform.
1. Task Creation Phase
During chip reset, after the BootLoader stage loads the code and enters the main function, after completing the configuration of CPU resources, interrupt resources, and peripheral resources based on the project task planning, FreeRTOS provides two methods for creating tasks and corresponding APIs, for both dynamic task creation and static task creation. Generally, dynamic task creation is most commonly adopted (the explanation here is based on dynamic task creation).
Parameters:
-
pxTaskCode: Task implementation function, usually contains an infinite loop statement and has no return value; this function is the entry point for the task. The specific functionality of the task is called and executed in this function.
-
pcName: Task name (cannot exceed the preset configMAX_TASK_NAME_LEN length)
-
usStackDepth: Task stack size (under default conditions, the actual stack size is 4 times usStackDepth)
-
pvParameters: Parameters passed to the task implementation function
-
xPriority: Task priority, ranging from (0 ~ configMAX_PRIORITIES-1). The task priority level in FreeRTOS can be configured through the macro definition value configMAX_PRIORITIES; the higher the xPriority value, the higher the task’s priority. Generally, when creating tasks, the selection of task priority is planned from 0 to configMAX_PRIORITIES-1. (In other RTOS, a smaller value indicates a higher priority).
-
pxCreatedTask: Task handle (TCB task control block), if created successfully, this handle is valid.
Return values:
-
pdPASS: Task creation successful
-
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: Insufficient stack, task creation failed
2. Task Scheduler Startup Phase
The FreeRTOS task scheduler startup relies on the SVC interrupt and vTaskStartScheduler function. After the Cortex-M4 series chip completes the initialization of CPU, peripherals, and interrupts, it enters the main function, creates the required tasks for project execution, and calls the vTaskStartScheduler function to start the FreeRTOS task scheduling (as shown in the figure below).
During the startup phase of the task scheduler, an idle task is automatically created by default, and the idle task’s priority is set to the system’s lowest priority. The source code will call the prvCheckTasksWaitingTermination function to release the resources of deleted tasks (TCB and task stack) and provide the idle task hook function vApplicationIdleHook for system load calculation. Users can also add monitoring and feedback based on their own projects in this hook function. The entry point for the idle task is portTASK_FUNCTION, with part of the source code shown below:
3. Task Scheduling Running Phase
In the FreeRTOS system based on the ARM Cortex-M4 series platform, the systick interrupt, normal external interrupts, SVC, and pendSV interrupts are generally designed with the following priority:
systick interrupt > normal external interrupt > SVC and pendSV interrupt > task (thread)
The SVC interrupt is mostly used during the task scheduler startup phase or for task preemption, serving as a means to start the task scheduler or preempt tasks. After the task scheduler starts, it relies on the systick interrupt for periodic task scheduling (time-slice polling or preemption) and the pendSV interrupt for task context switching and saving. The following diagram illustrates the scheduling of Task A and Task B, interspersed with systick and normal external interrupts.
4. Task Stack
The total space size of the FreeRTOS task stack can be configured according to the specific project resources. FreeRTOS plans the total space of the task stack based on the RAM size in the specific project, with the macro definition configTOTAL_HEAP_SIZE determining the total size of the task heap. Each time a new task is created, it requests the corresponding stack space for the newly created task in the total task heap, as shown below.
5. Task Monitoring
By configuring both configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS to 1, the functions prvWriteNameToBuffer(), vTaskList(), and vTaskGetRunTimeStats() enable FreeRTOS task monitoring. This feature can provide feedback on the current task status, task priority, and the maximum remaining stack space of each task in FreeRTOS. The source code of FreeRTOS provides printing of these values using sprintf, with part of the source code shown below:
The official demo print result is as follows:
6. Conclusion
The task mechanism of FreeRTOS provides excellent real-time capabilities, while the various configurable options in the native system offer tailored adaptations for different embedded applications. What attracts many manufacturers is that the system is commercially free and open-source. In embedded applications, factors such as power consumption, resources, and cost are often crucial criteria for manufacturers when choosing a system. Currently, in consumer electronics applications, considering power consumption, resources, and costs, some manufacturers adopt a big-core CPU + small-core CPU architecture. The big core often runs general-purpose operating systems (Linux, Android, iOS, etc.), while more and more manufacturers consider deploying FreeRTOS on the small core, adapting it based on different application scenarios. FreeRTOS, being free, open-source, easy to trim, and resource-efficient, presents competitive advantages comparable to other RTOS.
References:
FreeRTOS Official Documentation: https://www.freertos.org/features.html
FreeRTOS Official Code: https://www.freertos.org/a00104.html