Loading...
Searching...
No Matches
FreeRTOS

Tools > Operating System > FreeRTOS (SMP): tasks, queues and semaphores on both cores.

Tools > Operating System > FreeRTOS (SMP): tasks, queues and semaphores on both cores.

Choosing FreeRTOS (SMP) in Tools > Operating System builds the sketch with the FreeRTOS kernel (ADR 009). A sketch then includes the FreeRTOS headers it uses: FreeRTOS.h first, then task.h, queue.h, semphr.h, event_groups.h, timers.h, stream_buffer.h or message_buffer.h. The functions are described in the FreeRTOS kernel API reference. Without the menu option, including FreeRTOS.h stops the build with a message naming the menu. FreeRTOS (SMP) + CMSIS-RTOS2 gives the same kernel and settings, plus ARM's CMSIS-RTOS2 API (CMSIS-RTOS2).

setup()/loop() and setup1()/loop1() become tasks (see Multicore). One scheduler runs tasks on both cores; xTaskCreate() lets a task run on either, xTaskCreateAffinitySet() or vTaskCoreAffinitySet() pins it to one.

Setting Value
Cores 2 (SMP); the tick runs on core 0
Tick 1 ms (configTICK_RATE_HZ 1000), so pdMS_TO_TICKS(ms) is ms
Priorities 0 (idle) to 55 (configMAX_PRIORITIES 56, the number CMSIS-RTOS2 needs); loop() and loop1() run at 1 (23 with CMSIS-RTOS2), the timer task at 55
Pre-emption On, with time slicing between tasks of equal priority
Stack sizes In 4-byte words: xTaskCreate(f, "name", 1024, ...) gives 4 KB; minimum 256
Memory heap_3: tasks and queues come from the same heap as new, malloc() and String (rp2040.getFreeHeap())
Static allocation Also available (xTaskCreateStatic())
Kernel objects Mutexes, recursive mutexes, counting semaphores, queue sets, task notifications (3 per task), software timers, event groups, stream and message buffers
Diagnostics uxTaskGetStackHighWaterMark(), vTaskListTasks(), uxTaskGetSystemState()

The configuration is built into the package (FreeRTOSConfig.h in sdk-builder/freertos/); a sketch cannot change it.

What changes in the Arduino functions:

  • delay() blocks the calling task, so other tasks run; delayMicroseconds() still busy-waits.
  • The default yield() lets other tasks of the same priority run.
  • pico-sdk mutexes, semaphores, queues and sleep_ms() block the task instead of spinning.
  • A task that never waits (no delay(), vTaskDelay() or blocking queue call) keeps lower-priority tasks on its core from running.

Errors stop the board (USB Serial disconnects): a task overflowing its stack, running out of heap memory, or a failed kernel check. A sketch can define its own vApplicationStackOverflowHook(TaskHandle_t, char*) and vApplicationMallocFailedHook() (both extern "C") to do something else.