Multitasking on Raspberry Pico

Using the Raspberry Pi Pico SDK

The Raspberry Pico has two cores. This means you can run two tasks in parallel. They even can communicate to each other using a FIFO. Example sdk_multitasking on the github page shows how to run a task on each of the two core.

The Pico starts by default on core0. In your main function, which is executed on core0, you must tell it which function to execute on core1 by using

multicore_launch_core1(core1Blink);

In the given example, core1 sends data to core0 using the FIFO. To send data you call function

multicore_fifo_push_blocking(fromCore0);

To read from the FIFO you need to call function

multicore_fifo_push_blocking(fromCore1);

Using FreeRTOS

If you want to split a complex application into different parts you sould use an operating system which helps managing the resources. A widely used OS on embedded systems is FreeRTOS. Example freertos_single_core runs two tasks on one core (core0). Both tasks use a queue to exchange data.

A task in FreeRTOS is created by function

xTaskCreate(eventGenerator, "eventGenerator", 256, nullptr, 1, &tskHdnl_evGen);

where eventGenerator is the name of the function which should be executed as task. The second parameter is the name of the task. The stack size to be allocated for the task is given as third parameter. Please note that the size is not given in bytes, but in words. If you want to pass values to the task you can use the fourth parameter. In my example I do not want to use it, so I set it to nullptr. Next param is the priority of the task. In my case 1. A bigger value means higher priority. The last parameter is a pointer to a task handle so you can change the config later in your programm.

The two tasks in my example use a globally defined queue to communicate to each other. The queue is initialized in the main function using

eventQueue = xQueueCreate(5, sizeof(uint8_t) );

where the first parameter is the number of items to be stored in the queue. The second parameter is the size in bytes of each item in the queue. To send data to the queue please use

xQueueSend(eventQueue, &EVENT_PIN_HIGH, 0);

with the first parameter being the queue handle. The second parameter is a pointer to the data to send. The last parameter are the ticks to wait. For receiving you should use

xQueueReceive(eventQueue, &i, portMAX_DELAY)

The parameter are the same as for sending.

Using FreeRTOS AND the Raspberry Pi Pico SDK

Example freertos_multi_core runs one task on core1 and three FreeRTOS tasks (including main) on core0. The FreeRTOS tasks use a queue to exchange data. One of the FreeRTOS tasks uses SDK's FIFO to exchange data with core1.

Using FreeRTOS AND the Raspberry Pi Pico SDK (inverted)

This example is the same as the one above, but with inverted task execution: Core0 runs one SDK task and Core1 runs three FreeRTOS tasks. The FreeRTOS tasks use a queue to exchange data. One of the FreeRTOS tsks uses SDK's FIFO to exchange data with core1.

Last edit: 2022-11-22

Source code