FreeRTOS Symmetric Multiprocessing (SMP) is a version of the RTOS that can schedule tasks across multiple controller cores.
It's a very simple example - on purpose. With a few lines of code, we can make jobs run on either Pico ARM core. |
Download and install FreeRTOS
Clone FreeRTOS if you don't have it yet. The SMP part is recently added to FreeRTOS proper. The version that comes with Pico C SDK 1.5 doesn't have it yet.
git clone https://github.com/FreeRTOS/FreeRTOS.git -
-recurse-submodules
We'll tell our project later where it can find the RTOS.
The Double Blinky example
Goal: run two FreeRTOS tasks. Both on a different core.
The base for my code is the CORTEX_M0+_RP2040 SMP blinky demo code. You can find it in the FreeRTOS\FreeRTOS\Demo\ThirdParty\Community-Supported-Demos\CORTEX_M0+_RP2040\Standard_smp folder.
I added support for controlling what core to run a task on (instead of letting the scheduler decide).
FreeRTOSConfig.h is set up to use 2 cores, and to allow "core affinity"
#define configNUMBER_OF_CORES 2 #define configTICK_CORE 0 #define configRUN_MULTIPLE_PRIORITIES 0 // ... /* RP2040 specific */ #define configSUPPORT_PICO_SYNC_INTEROP 1 #define configSUPPORT_PICO_TIME_INTEROP 1 // ... /* SMP Related config. */ #define configUSE_PASSIVE_IDLE_HOOK 0 #define portSUPPORT_SMP 1 #define configUSE_CORE_AFFINITY 1
The LED blink task is virtually the same as the one from the demo. I used the parameter to tell which LED to blink
static void prvLedTask(void *pvParameters) { TickType_t xNextWakeTime; xNextWakeTime = xTaskGetTickCount(); for( ;; ) { vTaskDelayUntil( &xNextWakeTime, mainLED_FREQUENCY_MS ); gpio_xor_mask(1u << (uint32_t)pvParameters); } }
The main code schedules two of those tasks. Tells each of them to blink a different LED, and run on a different core:
TaskHandle_t xHandle; xTaskCreate(prvLedTask, "LED", configMINIMAL_STACK_SIZE, (void *)mainTASK_LED1, mainLED_TASK_PRIORITY, &(xHandle) ); // Define the core affinity mask such that this task can only run on core 0 vTaskCoreAffinitySet(xHandle, (1 << 0)); xTaskCreate(prvLedTask, "LED2", configMINIMAL_STACK_SIZE, (void *)mainTASK_LED2, mainLED_TASK_PRIORITY, &(xHandle) ); // Define the core affinity mask such that this task can only run on core 1 vTaskCoreAffinitySet(xHandle, (1 << 1)); vTaskStartScheduler();
Result:
"Hey, my code can't find (the right) FreeRTOS on my disk?"
The project includes a file in the CMake script that 'll help you to find the RTOS: FreeRTOS_Kernel_import.cmake.
Define a variable FREERTOS_KERNEL_PATH that points to the install (in my case, C:/Users/jancu/Documents/git/git_freertos/FreeRTOS/FreeRTOS/Source).
You can set it as an OS variable, or use the functionality of your IDE. Here's how I did that in VSCode:
Enjoy the FreeRTOS SMP double blinky. The download below includes the .uf2 file, that can be copied directly onto the Pico. LEDs will flash after you flash the firmware.
Top Comments