FreeRTOS (Overview)
Overview
FreeRTOS is an open source real-time operating system kernel that acts as the operating system for ESP-IDF applications and is integrated into ESP-IDF as a component. The FreeRTOS component in ESP-IDF contains ports of the FreeRTOS kernel for all the CPU architectures used by ESP targets (i.e., Xtensa and RISC-V). Furthermore, ESP-IDF provides different implementations of FreeRTOS in order to support SMP (Symmetric Multiprocessing) on multi-core ESP targets. This document provides an overview of the FreeRTOS component, the FreeRTOS implementations offered by ESP-IDF, and the common aspects across all implementations.
Implementations
The official FreeRTOS (henceforth referred to as Vanilla FreeRTOS) is a single-core RTOS. In order to support the various multi-core ESP targets, ESP-IDF supports different FreeRTOS implementations, namely ESP-IDF FreeRTOS and Amazon SMP FreeRTOS.
ESP-IDF FreeRTOS
ESP-IDF FreeRTOS is a FreeRTOS implementation based on Vanilla FreeRTOS v10.4.3, but contains significant modifications to support SMP. ESP-IDF FreeRTOS only supports two cores at most (i.e., dual core SMP), but is more optimized for this scenario by design. For more details regarding ESP-IDF FreeRTOS and its modifications, please refer to the FreeRTOS (ESP-IDF) document.
Note
ESP-IDF FreeRTOS is currently the default FreeRTOS implementation for ESP-IDF.
Amazon SMP FreeRTOS
Amazon SMP FreeRTOS is an SMP implementation of FreeRTOS that is officially supported by Amazon. Amazon SMP FreeRTOS is able to support N-cores (i.e., more than two cores). Amazon SMP FreeRTOS can be enabled via the CONFIG_FREERTOS_SMP option. For more details regarding Amazon SMP FreeRTOS, please refer to the official Amazon SMP FreeRTOS documentation.
Warning
The Amazon SMP FreeRTOS implementation (and its port in ESP-IDF) are currently in experimental/beta state. Therefore, significant behavioral changes and breaking API changes can occur.
Configuration
Kernel Configuration
Vanilla FreeRTOS requires that ports and applications configure the kernel by adding various #define config...
macros to FreeRTOSConfig.h
. Vanilla FreeRTOS supports a list of kernel configuration options which allow various kernel behaviors and features to be enabled or disabled.
However, for all FreeRTOS ports in ESP-IDF, the ``FreeRTOSConfig.h`` file is considered private and must not be modified by users. A large number of kernel configuration options in FreeRTOSConfig.h
are hard coded as they are either required or not supported in ESP-IDF. All kernel configuration options that are configurable by the user will be exposed via menuconfig under Component Config/FreeRTOS/Kernel
.
For the full list of user configurable kernel options, see Project Configuration. The list below highlights some commonly used kernel configuration options:
CONFIG_FREERTOS_UNICORE will run FreeRTOS only on CPU0. Note that this is not equivalent to running Vanilla FreeRTOS. Furthermore, this option may affect behavior of components other than freertos. For more details regarding the effects of running FreeRTOS on a single core, refer to ESP-IDF FreeRTOS Single Core (if using ESP-IDF FreeRTOS) or the official Amazon SMP FreeRTOS documentation. Alternatively, users can also search for occurrences of
CONFIG_FREERTOS_UNICORE
in the ESP-IDF components.
CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY enables backward compatibility with some FreeRTOS macros/types/functions that were deprecated from v8.0 onwards.
Port Configuration
All other FreeRTOS related configuration options that are not part of the kernel configuration are exposed via menuconfig under Component Config/FreeRTOS/Port
. These options configure aspects such as:
The FreeRTOS ports themselves (e.g., tick timer selection, ISR stack size)
Additional features added to the FreeRTOS implementation or ports
Using FreeRTOS
Application Entry Point
Unlike Vanilla FreeRTOS, users of FreeRTOS in ESP-IDF must never call vTaskStartScheduler()
and vTaskEndScheduler()
. Instead, ESP-IDF will start FreeRTOS automatically. Users must define a void app_main(void)
function which acts as the entry point for user’s application and is automatically called on ESP-IDF startup.
Typically, users would spawn the rest of their application’s task from
app_main
.The
app_main
function is allowed to return at any point (i.e., before the application terminates).The
app_main
function is called from themain
task.
Background Tasks
During startup, ESP-IDF and FreeRTOS will automatically create multiple tasks that run in the background (listed in the the table below).
Task Name |
Description |
Stack Size |
Affinity |
Priority |
---|---|---|---|---|
Idle Tasks ( |
An idle task ( |
CPUx |
|
|
FreeRTOS Timer Task ( |
FreeRTOS will create the Timer Service/Daemon Task if any FreeRTOS Timer APIs are called by the application. |
CPU0 |
||
Main Task ( |
Task that simply calls |
|
||
IPC Tasks ( |
When CONFIG_FREERTOS_UNICORE is false, an IPC task ( |
CPUx |
|
|
ESP Timer Task ( |
ESP-IDF will create the ESP Timer Task used to process ESP Timer callbacks. |
CPU0 |
|
Note
Note that if an application uses other ESP-IDF features (e.g., WiFi or Bluetooth), those features may create their own background tasks in addition to the tasks listed in the table above.
FreeRTOS Additions
ESP-IDF provides some supplemental features to FreeRTOS such as Ring Buffers, ESP-IDF style Tick and Idle Hooks, and TLSP deletion callbacks. See FreeRTOS (Supplemental Features) for more details.
FreeRTOS Heap
Vanilla FreeRTOS provides its own selection of heap implementations. However, ESP-IDF already implements its own heap (see Heap Memory Allocation), thus ESP-IDF does not make use of the heap implementations provided by Vanilla FreeRTOS. All FreeRTOS ports in ESP-IDF map FreeRTOS memory allocation/free calls (e.g., pvPortMalloc()
and pvPortFree()
) to ESP-IDF heap API (i.e., heap_caps_malloc()
and heap_caps_free()
). However, the FreeRTOS ports ensure that all dynamic memory allocated by FreeRTOS is placed in internal memory.
Note
If users wish to place FreeRTOS objects in external memory, users should allocate those objects manually using heap_caps_malloc()
, then create the object using the object’s ...CreateStatic()
function.