How long does portMAX_DELAY actually wait in FreeRTOS?

Although portMAX_DELAY is listed as value for waiting indefinitely, it will only actually wait indefinitely if INCLUDE_vTaskSuspend is enabled in the FreeRTOS config.

portMAX_DELAY is typically defined as 0xFFFFFFFF i.e. 2^32-1:

#define portMAX_DELAY ( TickType_t ) 0xffffffffUL

(however if 16 bit ticks are enabled using configUSE_16_BIT_TICKS it will be defined as 0xFFFF (2^16-1).

In case INCLUDE_vTaskSuspend is enabled, this is treated as a special value and will actually wait indefinitely. If INCLUDE_vTaskSuspend is not defined, it will only wait for 0xFFFFFFFF ticks (assuming 32-bit system ticks.

In other words, this will wait for only about 7 weeks if FreeRTOS is defined to tick every millisecond.

Posted by Uli Köhler in Embedded, FreeRTOS

FreeRTOS task queue minimal example

This is how you create and use a task queue in FreeRTOS:

Global declaration

Declare the structure of a task (I recommend to use a task type enum class in order to keep the flexibility of using multiple task types:

#include <freertos/queue.h>

enum class I2CTaskType : uint8_t {
    MyTaskType = 0

struct I2CTask {
    I2CTaskType type;
    // Parameters
    int16_t value;
static QueueHandle_t i2cTaskQueue;

Initialization code

Call this once, before using it:

// Create task queue
i2cTaskQueue = xQueueCreate(8 /* Number of queue slots */, sizeof(I2CTask));

In the thread processing the queue

if (xQueueReceive(i2cTaskQueue, (void *)&task, portMAX_DELAY /* Wait infinitely for new tasks */) == pdTRUE) {
    if(task.type == I2CTaskType::MyTaskType) {
        // TODO process task
        Serial.printf("My task type: %d\r\n", task.value);

How to add a task to the queue

void AddTask(int16_t val) {
    I2CTask task;
    task.type = I2CTaskType::MyTaskType;
    task.value = val;
    xQueueSend(i2cTaskQueue, (void*)&task, 10 / portTICK_PERIOD_MS /* timeout */);


Posted by Uli Köhler in C/C++, Embedded, FreeRTOS, PlatformIO

FreeRTOS mutex minimal example

This is how you create and use a mutex in FreeRTOS:


#include <freertos/semphr.h>


Global declaration

SemaphoreHandle_t myMutex;

Initialization code

Call this once, before using it:

myMutex = xSemaphoreCreateMutex();

How to lock & unlock the mutex

// Wait a maximum of 10ms to lock the mutex
if(xSemaphoreTake(myMutex, 10 / portTICK_PERIOD_MS) == pdTRUE) {
   // Success locking the mutex
   // TODO: Your code goes here!
   // Unlock the mutex!
} else {
   // Failed to lock the mutex within timeout
   // DO NOT use the resource protected by the mutex
   // DO NOT unlock (xSemaphoreGive) !


Posted by Uli Köhler in Embedded, FreeRTOS, PlatformIO

How to add FreeRTOS task (“thread”) to any PlatformIO project

Most PlatformIO default configurations already have FreeRTOS enabled – they just don’t use it.

In order to start a new FreeRTOS “thread” (called task in FreeRTOS-speak), first add these includes:

#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

Now add the task function and handle:

TaskHandle_t myTaskHandle;
void MyTask( void * parameter )
       // TODO Task code goes here
    // if you ever exit the loop, this is here to clean up the resources
    vTaskDelete( NULL );

then start the task using this code once, for example in your main function:

// Start MyTask thread
    MyTask, // Task function
    "MyTask", // Name
    10000, // Stack size
    NULL, // Parameter
    1, // Priority


Posted by Uli Köhler in C/C++, Electronics, Embedded, FreeRTOS, PlatformIO

What is the value of portTICK_PERIOD_MS and configTICK_RATE_HZ on the ESP32 using PlatformIO?

When you use PlatformIO with the Arduino framework in its default configuration on the ESP32, configTICK_RATE_HZ is set to 1000. In other words, FreeRTOS has a default tick frequency of 1kHz. This is defined in sdkconfig.h:


Hence portTICK_PERIOD_MS is 1. In my opinion, a tick rate of 1kHz is a sane configuration for most usecases.

I found the value by using the following code on an ESP32:

Serial.println("Timing: ");


Posted by Uli Köhler in Arduino, Electronics, Embedded, ESP8266/ESP32, FreeRTOS, PlatformIO