The Raspberry Pi Pico series is a range of tiny, fast, and versatile boards built using RP2040, the flagship microcontroller chip designed by Raspberry Pi in the UK
Designed by Raspberry Pi, RP2040 features a dual-core Arm Cortex-M0+ processor with 264kB internal RAM and support for up to 16MB of off-chip flash. A wide range of flexible I/O options includes I2C, SPI, and - uniquely - Programmable I/O (PIO). These support endless possible applications for this small and affordable package.
Specification
21 mm × 51 mm form factor
RP2040 microcontroller chip designed by Raspberry Pi in the UK
Dual-core Arm Cortex-M0+ processor, flexible clock running up to 133 MHz
264kB on-chip SRAM
2MB on-board QSPI flash
2.4GHz 802.11n wireless LAN (Raspberry Pi Pico W and WH only)
Bluetooth 5.2 (Raspberry Pi Pico W and WH only)
26 multifunction GPIO pins, including 3 analogue inputs
1 × USB 1.1 controller and PHY, with host and device support
8 × Programmable I/O (PIO) state machines for custom peripheral support
Supported input voltage 1.8–5.5V DC
Operating temperature -20°C to +85°C (Raspberry Pi Pico and Pico H); -20°C to +70°C (Raspberry Pi Pico W and Pico WH)
Castellated module allows soldering direct to carrier boards (Raspberry Pi Pico and Pico W only)
Drag-and-drop programming using mass storage over USB
Low-power sleep and dormant modes
Accurate on-chip clock
Temperature sensor
Accelerated integer and floating-point libraries on-chip
BUILDING
Get the PICO SDK
Setup the Raspberry Pi Pico SDK build environment by following the instructions for Getting Started With Pico. Ensure that PICO_SDK_PATH is set in your environment, or pass it via -DPICO_SDK_PATH=xxx on the CMake command line.
The Pico Examples repository provides a set of example applications that are written using the SDK. To clone these repositories start by creating a pico directory to keep all pico related checkouts in. These instructions create a pico directory at /home/pi/pico.
$ cd ~/
$ mkdir pico
$ cd pico
Then clone the pico-sdk and pico-examples git repositories.
To build the applications in pico-examples, you’ll need to install some extra tools. To build projects you’ll need CMake, a cross-platform tool used to build the software, and the GNU Embedded Toolchain for Arm. You can install both of these via apt from the command line. Anything you already have installed will be ignored by apt.
Connect the Raspberry Pi Pico to your computer while holding the BOOTSEL button. This will force the board into USB Mass Storage Mode.
Drag-and-drop the .uf2 file for the demo you want to run onto the Mass Storage Device.
RTOS Configuration and Usage Details
Configuration items specific to the blinky and comprehensive demos are in the FreeRTOS/Demo/ThirdParty/Community-Supported-Demos/CORTEX_M0+_RP2040/Standard_smp/FreeRTOSConfig.h file and those specific to the multicore demo are in the FreeRTOS/Demo/Community-Supported-Demos/CORTEX_M0+_RP2040/OnEitherCore/FreeRTOSConfig.h file. The constants defined in these files can be edited to suit your application. The following configuration options are specific to the SMP support in the FreeRTOS Kernel:
configNUMBER_OF_CORES - Set the number of cores.
configRUN_MULTIPLE_PRIORITIES - Enable/Disable simultaneously running tasks with multiple priorities.
configUSE_CORE_AFFINITY - Enable/Disable setting a task's affinity to certain cores.
Source/Portable/MemMang/heap_4.c is included in the project to provide the memory allocation required by the RTOS kernel. Please refer to the Memory Management section of the API documentation for complete information.
vPortEndScheduler() has not been implemented.
Output
Code
/* Kernel includes. */#include"FreeRTOS.h"#include"task.h"#include"semphr.h"/* Library includes. */#include<stdio.h>#include"hardware/gpio.h"/* Priorities at which the tasks are created. */#definemainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY +2 )#definemainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY +1 )/* The rate at which data is sent to the queue. The 200ms value is convertedto ticks using the portTICK_PERIOD_MS constant. */#definemainQUEUE_SEND_FREQUENCY_MS ( 1000/ portTICK_PERIOD_MS )/* The number of items the queue can hold. This is 1 as the receive taskwill remove items as they are added, meaning the send task should always findthe queue empty. */#definemainQUEUE_LENGTH ( 1 )/* The LED toggled by the Rx task. */#definemainTASK_LED ( PICO_DEFAULT_LED_PIN )/*-----------------------------------------------------------*//* * Called by main when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 in * main.c. */voidmain_blinky( void );/* * The tasks as described in the comments at the top of this file. */staticvoidprvQueueReceiveTask( void*pvParameters );staticvoidprvQueueSendTask( void*pvParameters );/*-----------------------------------------------------------*//* The queue used by both tasks. */staticQueueHandle_t xQueue =NULL;/*-----------------------------------------------------------*/voidmain_blinky( void ){printf(" Starting main_blinky.\n"); /* Create the queue. */ xQueue =xQueueCreate( mainQUEUE_LENGTH,sizeof( uint32_t ) );if( xQueue !=NULL ) { /* Start the two tasks as described in the comments at the top of this file. */xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */"Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */NULL, /* The parameter passed to the task - not used in this case. */ mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */NULL ); /* The task handle is not required, so NULL is passed. */xTaskCreate( prvQueueSendTask,"TX", configMINIMAL_STACK_SIZE,NULL, mainQUEUE_SEND_TASK_PRIORITY,NULL ); /* Start the tasks and timer running. */vTaskStartScheduler(); } /* If all is well, the scheduler will now be running, and the following line will never be reached. If the following line does execute, then there was insufficient FreeRTOS heap memory available for the Idle and/or timer tasks to be created. See the memory management section on the FreeRTOS web site for more details on the FreeRTOS heap http://www.freertos.org/a00111.html. */for( ;; );}/*-----------------------------------------------------------*/staticvoidprvQueueSendTask( void*pvParameters ){TickType_t xNextWakeTime;constunsignedlong ulValueToSend =100UL; /* Remove compiler warning about unused parameter. */ ( void ) pvParameters; /* Initialise xNextWakeTime - this only needs to be done once. */ xNextWakeTime =xTaskGetTickCount();for( ;; ) { /* Place this task in the blocked state until it is time to run again. */vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS ); /* Send to the queue - causing the queue receive task to unblock and toggle the LED. 0 is used as the block time so the sending operation will not block - it shouldn't need to block as the queue should always be empty at this point in the code. */xQueueSend( xQueue,&ulValueToSend,0U ); }}/*-----------------------------------------------------------*/staticvoidprvQueueReceiveTask( void*pvParameters ){unsignedlong ulReceivedValue;constunsignedlong ulExpectedValue =100UL; /* Remove compiler warning about unused parameter. */ ( void ) pvParameters;for( ;; ) { /* Wait until something arrives in the queue - this task will block indefinitely provided INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h. */xQueueReceive( xQueue,&ulReceivedValue, portMAX_DELAY ); /* To get here something must have been received from the queue, but is it the expected value? If it is, toggle the LED. */if( ulReceivedValue == ulExpectedValue ) {gpio_xor_mask( 1u<< mainTASK_LED ); ulReceivedValue =0U; } }}/*-----------------------------------------------------------*/