Close

Enabling FreeRTOS on the RP2350

A project log for T76 Instrument Core: Pro instruments on Pi Pico 2

A C++ framework for building real-time, pro-grade digital instruments on the RP2350 / Pi Pico 2 platform.

marco-tabiniMarco Tabini 10/16/2025 at 02:380 Comments

Adding FreeRTOS support to IC is relatively simple. First, we add RPi's own branch of FreeRTOS as an external submodule to the repository:

git submodule add https://github.com/raspberrypi/FreeRTOS-Kernel.git

Next, we copy a few files from the FreeRTOS source into the project's main directory; these include a CMake config file, a C include file that provides the actual configuration for FreeRTOS, and a couple small C source files that provide some functionality required by FreeRTOS to run.

We must also define a vApplicationStackOverflowHook() function that is called by FreeRTOS when a task overflows its stack. Right now, our implementation (in freertos/rp2350.c) simply asserts and crashes the core, but in a future iteration we will use it to call our exception handler to give the code an opportunity to place our device in a safe mode before resetting or halting.

FreeRTOS configuration

The stock configuration that comes in the FreeRTOS source sets up the operating system with multi-core support and allows all tasks to run on either core. We, however, want FreeRTOS to only run on core 0 while reserving core 1 for our critical tasks. Therefore, we change the configuration so that FreeRTOS runs in single-core mode:

#define configNUMBER_OF_CORES                   1
#define configNUM_CORES                         configNUMBER_OF_CORES
#define configTICK_CORE                         0
#define configRUN_MULTIPLE_PRIORITIES           1

/* SMP Related config. */
#define configUSE_CORE_AFFINITY                 0
#define configUSE_PASSIVE_IDLE_HOOK             0
#define portSUPPORT_SMP                         0

Making TinyUSB work

Interestingly, this configuration causes TinyUSB to stop working; I haven't really figured out why this is the case, but my bet is that, by default, the SDK attempts to run the TinyUSB task on core 1 if it detects FreeRTOS; since we do not support SMP, this approach fails.

The fix to this problem is pretty simple: We just provide our own TinyUSB task and call tud_task() directly. Eventually, when we add more substantial USB support, we'll move this code into its own class, but for now it's just a simple function inside main.cpp.

Putting it all together

The new version of the source demonstrates that everything works by spawning three tasks:

Discussions