ES: Introduction to FreeRTOS

FreeRTOS is one of the most widely used real-time operating systems in the embedded world. If you are building firmware for microcontrollers like ARM Cortex-M, ESP32, STM32, NXP, or Microchip devices, chances are you will either use FreeRTOS directly or a vendor SDK built on top of it.

From a security and system architecture perspective, understanding FreeRTOS is not just about creating tasks and queues. It is about understanding determinism, memory control, scheduling behavior, and how the kernel integrates with hardware and middleware layers.

The Origin and Evolution of FreeRTOS

FreeRTOS was originally developed by Richard Barry in 2003 as a lightweight, portable, and open-source real-time kernel for microcontrollers.

The goal was simple:

  • Small footprint
  • Deterministic real-time behavior
  • Portable across architectures
  • Easy to integrate

Over the years, it became one of the most adopted RTOS kernels in the embedded ecosystem. In 2017, it was acquired and extended by:

  • Amazon

Amazon expanded it into Amazon FreeRTOS, adding:

  • Secure connectivity (TLS, MQTT)
  • OTA update support
  • IoT cloud integration
  • Secure boot and device provisioning concepts

But here is an important architectural distinction:

txt
+---------------------------+
|      Amazon IoT Layer     |
|  (MQTT, TLS, OTA, etc.)   |
+---------------------------+
|        FreeRTOS Kernel    |
| (Tasks, Queues, Timers)   |
+---------------------------+
|     Hardware Abstraction  |
+---------------------------+
|       Microcontroller     |
+---------------------------+

The FreeRTOS Kernel itself remains small and hardware-focused. Everything else is middleware.

As an embedded security engineer, you must clearly separate:

  • Kernel
  • Middleware
  • Application
  • Hardware layer

Because vulnerabilities often occur at the boundaries.


Why the Name "FreeRTOS"?

The name has two meanings:

  • “Free” as in open-source (MIT license)
  • “Free” as in free to use in commercial products

It is not “free” as in zero cost only — it is also free in flexibility.

RTOS means:

Real-Time Operating System

Meaning:

  • Deterministic scheduling
  • Bounded latency
  • Predictable response time

Unlike general-purpose OS such as Linux or Windows, which optimize throughput and fairness, FreeRTOS optimizes deterministic response.


The Kernel Architecture

FreeRTOS is a preemptive, priority-based scheduler.

Core kernel components:

  • Tasks
  • Scheduler
  • Queues
  • Semaphores
  • Mutexes
  • Software Timers
  • Event Groups
  • Memory Management

Basic conceptual view:

txt
                 +----------------+
                 |   Scheduler    |
                 +--------+-------+
                          |
        -------------------------------------
        |         |          |             |
     Task A    Task B     Task C       Idle Task
   (High P)   (Med P)    (Low P)       (Lowest)

Scheduler selects:

  • Highest priority READY task
  • Can preempt lower priority task
  • Optional time slicing between equal priorities

This leads us naturally to naming conventions — because FreeRTOS enforces strong conventions for clarity.


FreeRTOS Naming Convention – A Discipline

FreeRTOS uses consistent naming to improve portability and readability.

  • TickType_t: to count the system ticks
  • The size depends on the configuration and settings uint16_t or uint32_t
  • BaseType_t: for variables where the size depends on the architecture of the system
  • uint16_t or uint32_t
  • used to ensure portability across different architectures

Prefix conventions:

PrefixMeaning
vFunction returns void
xFunction returns BaseType_t or status
pvPointer to void
uxUnsigned BaseType
pcPointer to char
ulUnsigned long
pxPointer to struct

Example:

cpp
BaseType_t xTaskCreate(
    TaskFunction_t pxTaskCode,
    const char * const pcName,
    configSTACK_DEPTH_TYPE usStackDepth,
    void *pvParameters,
    UBaseType_t uxPriority,
    TaskHandle_t *pxCreatedTask
);

Notice how the prefix tells you:

  • pxTaskCode → pointer to task function
  • pcName → pointer to char
  • uxPriority → unsigned base type

This convention is critical in large embedded systems because:

  • It reduces ambiguity
  • It improves static analysis readability
  • It helps during security auditing

The Role of Macros in FreeRTOS

FreeRTOS relies heavily on macros for portability and configuration.

Why?

Because the kernel must compile on:

  • ARM Cortex-M
  • RISC-V
  • AVR
  • Xtensa
  • PIC32
  • Many others

Instead of hardcoding architecture behavior, FreeRTOS uses macros that map to port-specific implementations.

Example:

cpp
portENTER_CRITICAL()
portEXIT_CRITICAL()
portYIELD()

These macros expand differently depending on the MCU port.

On ARM Cortex-M:

code
portENTER_CRITICAL()
    ↓
Disable interrupts (BASEPRI manipulation)

On another architecture:

Disable global interrupt flag

This is defined inside:

portable/[compiler]/[architecture]/portmacro.h

So the portability layer looks like:

code
Application
     |
FreeRTOS API
     |
FreeRTOS Kernel
     |
Port Layer (port.c / portmacro.h)
     |
Hardware (CPU Registers)

From a security perspective:

Critical section macros are extremely sensitive.

Misuse can lead to:

  • Deadlocks
  • Priority inversion
  • Interrupt latency issues

FreeRTOS Configuration via Macros

FreeRTOS is configured through:

FreeRTOSConfig.h

This file defines:

  • configUSE_PREEMPTION
  • configUSE_TIME_SLICING
  • configMAX_PRIORITIES
  • configTOTAL_HEAP_SIZE
  • configUSE_MUTEXES
  • configUSE_TIMERS

Example:

cpp
#define configUSE_PREEMPTION            1
#define configMAX_PRIORITIES            5
#define configTOTAL_HEAP_SIZE           (10 * 1024)

This means:

  • Preemptive scheduler enabled
  • 5 priority levels
  • 10 KB RTOS heap

The configuration file shapes kernel behavior at compile time.

This design avoids runtime overhead and makes the kernel deterministic.


What is FreeRTOS.h and Why Is It Important?

FreeRTOS.h is the primary include header of the kernel.

When you include: #include "FreeRTOS.h"

You get:

  • Core type definitions
  • Configuration linkage
  • API prototypes
  • Kernel macros

It includes:

  • projdefs.h
  • portable.h
  • FreeRTOSConfig.h
  • Basic type definitions like BaseType_t, TickType_t

Internally, structure:

code
FreeRTOS.h
   |
   +-- includes FreeRTOSConfig.h
   +-- includes portable.h
   +-- defines BaseType_t
   +-- defines TickType_t

Without including FreeRTOS.h first, other headers may fail.

This is why FreeRTOS documentation states:

FreeRTOS.h must be included before any other FreeRTOS header.

Because configuration macros must be known first.


CMSIS-OS – The Abstraction Layer

In ARM-based systems, especially STM32 projects, you often see:

cmsis_os.h

CMSIS stands for:

Cortex Microcontroller Software Interface Standard

It is defined by:

  • Arm Ltd.

CMSIS-OS provides a generic RTOS API that can map to:

  • FreeRTOS
  • RTX
  • Other RTOS kernels

Layered view:

txt
Application Code
      |
CMSIS-OS API
      |
FreeRTOS Implementation
      |
FreeRTOS Kernel
      |
ARM Cortex-M

Example:

CMSIS style:

cpp
osThreadNew(myTask, NULL, &attr);

FreeRTOS native style:

cpp
xTaskCreate(myTask, "Task", 256, NULL, 2, NULL);

CMSIS-OS improves portability between ARM projects.

But:

From a professional embedded standpoint:

  • Native FreeRTOS API gives more control
  • CMSIS adds abstraction overhead
  • Debugging may be harder through CMSIS

Security engineers often prefer native APIs to fully control:

  • Stack sizes
  • Memory
  • Scheduling
  • Critical sections

Memory Management in FreeRTOS

FreeRTOS provides multiple heap implementations:

  • heap_1 → static, no free
  • heap_2 → simple free
  • heap_3 → wrapper around malloc/free
  • heap_4 → coalescing allocator
  • heap_5 → multiple regions

This is extremely important in embedded security.

Example of heap_4 fragmentation model:

txt
+-----------------------------+
|  Block A | Block B | Block C|
+-----------------------------+

Free B

+-----------------------------+
|  Block A |   FREE   | Block C|
+-----------------------------+

If A and C are freed:

txt
+-----------------------------+
|          FREE               |
+-----------------------------+

heap_4 merges adjacent blocks.

Deterministic memory control is critical in:

  • Medical
  • Automotive
  • Industrial

Putting It All Together

FreeRTOS is:

  • A portable real-time kernel
  • Configurable at compile time
  • Architected around priority preemptive scheduling
  • Macro-driven for portability
  • Integrated via FreeRTOS.h
  • Optionally abstracted via CMSIS-OS
  • Extended by Amazon for IoT

Complete stack view in production embedded device:

txt
+------------------------------------+
| Application Tasks                  |
| (Sensors, Control, Communication)  |
+------------------------------------+
| FreeRTOS API (xTaskCreate, etc.)   |
+------------------------------------+
| FreeRTOS Kernel (Scheduler, IPC)   |
+------------------------------------+
| Port Layer (Cortex-M, RISC-V)      |
+------------------------------------+
| Hardware (MCU, Interrupts, Timer)  |
+------------------------------------+