Using FreeRTOS with the Raspberry Pi Pico

By Daniel Gross

Senior Developer Advocate

Amazon Web Services

October 19, 2022


Using FreeRTOS with the Raspberry Pi Pico

In this blog series, we will explore writing embedded applications for the Raspberry Pi Pico using FreeRTOS. We will highlight some of the key features of FreeRTOS with sample code. We will also dive into the multicore capabilities of the Raspberry Pi Pico, which we can take advantage of with FreeRTOS. This is the first blog in a series in which we will discuss various aspects of FreeRTOS.

First off, what is FreeRTOS? As the name suggests, FreeRTOS is a real-time operating system (RTOS) that is free to use. It is entirely open source with a permissive MIT license, and is intended for embedded applications that run on microcontrollers such as the one on the Raspberry Pi Pico, and small microprocessors. FreeRTOS has been available for over 18 years with a strong community of partners and embedded developers utilizing it for their products and services.

The Raspberry Pi Pico is a small development board built around the RP2040 microcontroller, which was designed by Raspberry Pi. The RP2040 is a dual-core Arm Cortex-M0+ processor running up to 133 MHz with 264kB on-chip SRAM. The Pico board has 2MB flash with 26 multifunctional GPIO pins. These hardware specs give us a range of capabilities for creating embedded applications with FreeRTOS, including the dual-core processor. Raspberry Pi also provides a C/C++ SDK for the Pico, which we will be using later on.

So, why do we need an RTOS such as FreeRTOS for a microcontroller-based board like the Raspberry Pi Pico? The short answer is, technically, you do not need an RTOS in all cases. Some embedded applications can be really simple such as reading values from a sensor and sending those values to an output. An RTOS is not required in this case and you can find examples illustrating that. However, as microcontrollers have become more capable devices and embedded applications have become increasingly more complex to take advantage of the hardware, the benefits of using an RTOS have grown.

Multitasking is one of the important reasons for using an RTOS, and is a key feature of FreeRTOS. What is multitasking? It is a way to run multiple tasks in your embedded application so that those tasks can execute independently of one another while still sharing the same processor. Task execution is managed by what is known as a scheduler. In the case of a single-core microcontroller, it is the job of the scheduler to give tasks execution time based on specified priorities and other factors. This can give the impression that multiple tasks are executing simultaneously even though the scheduler is actually managing execution by switching between tasks in quick succession at the millisecond level.

With the sample code shown later in this blog, we demonstrate how to create and run tasks with FreeRTOS on the Raspberry Pi Pico. First, however, we will cover how to setup a development environment.

There are different ways to setup a development environment for FreeRTOS and the Raspberry Pi Pico. This particular setup is agnostic to a specific editor or IDE, and it aims to be simple and flexible. The essential tools needed are: Git, CMake, Make, and the GNU Arm Embedded Toolchain. Below are installation instructions for Windows, Linux, and MacOS.



All the tools we need, including Git and Make, should be available after installing these packages:

$ sudo apt install cmake

$ sudo apt install gcc-arm-none-eabi

$ sudo apt install build-essential


For MacOS, ensure that Homebrew is installed and then follow these steps in the Terminal:

$ brew install cmake

$ brew tap ArmMbed/homebrew-formulae

$ brew install arm-none-eabi-gcc

Once you have completed the OS-specific setup, launch your terminal (Git Bash on Windows) and complete the steps below to setup the Blink project from the command line:

$ mkdir freertos-pico

$ cd freertos-pico

$ git clone --recurse-submodules

$ git clone -b smp --recurse-submodules

$ export PICO_SDK_PATH=$PWD/pico-sdk


$ mkdir blink

$ cd blink

Now we are ready for the code. Below is a simple FreeRTOS application written in C that you can run on the Raspberry Pi Pico. It creates a task to blink the LED on the board. Create a file in the ‘blink’ directory and name it ‘main.c’ using any code editor you wish. Notepad++, vi, Sublime Text, Atom, and VSCode are some examples.

#include "pico/stdlib.h"

#include "FreeRTOS.h"

#include "task.h"

void vBlinkTask() {

   for (;;) {

      gpio_put(PICO_DEFAULT_LED_PIN, 1);


      gpio_put(PICO_DEFAULT_LED_PIN, 0);




void main() {


   gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);

   xTaskCreate(vBlinkTask, "Blink Task", 128, NULL, 1, NULL);



Once we have the C file in place, we need to build the project. We will use CMake to build our project, which requires a ‘CMakeLists.txt’ file. Copy this pre-made ‘CMakeLists.txt’ file into the blink directory.

In addition to the ‘main.c’ and ‘CMakeLists.txt’ files, we also need a ‘FreeRTOSConfig.h’ file to configure FreeRTOS for our project.  Copy this pre-made ‘FreeRTOSConfig.h’ file into the ‘blink’ directory. Next, build the project by following the steps below from the ‘blink’ directory:

$ mkdir build

$ cd build

For Windows only:

$ cmake -G "MinGW Makefiles" ..

For Linux or MacOS:

$ cmake ..

Finally, from any environment:

$ make

Once the project successfully builds, there should now be a ‘blink.uf2’ in the ‘build’ directory. This file is the binary we will flash to the Pico. In order to flash this file, first hold down the BOOTSEL button on the Pico board while plugging it in to the USB interface. This will mount the Pico as a drive. Then copy the ‘blink.uf2’ file to the drive location and the Pico will automatically reboot and run the application. For example, if your drive location is D:, here is how to copy from the command line:

$ cp blink.uf2 /d/

Now that you have flashed the application, the LED on the Raspberry Pi Pico should be blinking. Congratulations, you are now executing a task with FreeRTOS!

For the next blog in this series, we will describe how and when the scheduler decides which task to run, then extend the Blink demo to demonstrate FreeRTOS features like Queues and Stream Buffers while exploring event-driven designs.

Click to access the complete CMakeLists.txt and FreeRTOSConfig.h files.

Daniel Gross is a Senior Developer Advocate at Amazon Web Services (AWS). Focused on FreeRTOS and embedded devices interacting with cloud services, Daniel is passionate about delivering a great developer experience for IoT builders.

More from Daniel