Skip to content

CPU/Boards: Add Raspberry Pi Pico 2 (RP2350) support #21545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions boards/rpi-pico-2/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2025 Tom Hert <[email protected]>
# SPDX-FileCopyrightText: 2025 HAW Hamburg
# SPDX-License-Identifier: LGPL-2.1-only

config BOARD
default "rpi-pico-2" if BOARD_RPI_PICO_2

config BOARD_RPI_PICO_2
bool
default y
select CPU_MODEL_RP2350
3 changes: 3 additions & 0 deletions boards/rpi-pico-2/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE = board

include $(RIOTBASE)/Makefile.base
Empty file added boards/rpi-pico-2/Makefile.dep
Empty file.
1 change: 1 addition & 0 deletions boards/rpi-pico-2/Makefile.features
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CPU := rp2350
7 changes: 7 additions & 0 deletions boards/rpi-pico-2/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CPU_MODEL := RP2350
PORT_LINUX ?= /dev/ttyACM0

# JLink isnt tested yet on RP2350
# ifeq ($(PROGRAMMER),jlink)
# JLINK_DEVICE = RP2350_M33_0
# endif
7 changes: 7 additions & 0 deletions boards/rpi-pico-2/dist/openocd.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
echo "Make sure to use the Raspberry Pi OpenOCD version!"
source [find target/rp2350.cfg]
set USE_CORE 0
set RESCUE 1
$_TARGETNAME_0 configure -rtos auto
adapter speed 5000
rp2350.dap.core1 cortex_m reset_config sysresetreq
86 changes: 86 additions & 0 deletions boards/rpi-pico-2/doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
@defgroup boards_rpi_pico_2 Raspberry Pi Pico 2
@ingroup boards
@brief Support for the RP2350 based Raspberry Pi Pico board

@warning The support for the Raspberry Pi Pico 2 is still in a very early stage! See [Known Issues](#rpi_pico_2_known_issues).

## Overview

The Raspberry Pi Pico 2 is a microcontroller board based on the RP2350 chip, featuring dual-core Arm Cortex-M0+ processors and RISC-V Hazard secondary architecture. It is designed for a wide range of applications, from hobbyist projects to professional embedded systems for a fairly affordable price.

![The Raspberry Pi Pico 2 Board](https://www.raspberrypi.com/documentation/microcontrollers/images/pico-2.png)

## Hardware

| MCU | RP2350 |
|:-----------|:------------------------------------------------------------|
| Family | Dual Cortex-M33 or Hazard3 (RISC-V) |
| Vendor | Raspberry Pi |
| RAM | 520 kB on-chip SRAM (10 independent banks) |
| Flash | Up to 16 MB external QSPI flash (expandable to 32 MB) |
| Frequency | up to 150 MHz (Set to 125 MHz in RIOT) |
| Security | Boot signing, key storage, SHA-256 accelerator |
| PIOs | 12 state machines |
| UARTs | 2 |
| SPIs | 2 |
| I2Cs | 2 |
| PWM | 24 channels |
| USB | USB 1.1 controller with host and device support |
| Power | On-chip switched-mode power supply with LDO sleep mode |
| OTP | 8 kB of one-time-programmable storage |
| Datasheet | [RP2350 Datasheet](https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf) |

## User Interfaces

| Interface | Description |
|:-----------|:-------------------------------------------------------------|
| LED0 | User LED (GPIO 0 at Pin 25) |
| SW0 | Button used in flash process, can be accessed using registers but difficult |

## Pinout

![Pinout Diagram](https://www.raspberrypi.com/documentation/microcontrollers/images/pico-2-r4-pinout.svg)

## Flashing the Board

The Raspberry Pi Pico 2 has a built-in bootloader that allows flashing via USB. However, you can also use OpenOCD for flashing the board.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a few words on how the bootselect works?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With that, do you mean how to get into the flashing state via the bootselect button?


### Flashing using OpenOCD

If you have two Raspberry Pi Pico boards, you can utilize one as a programmer to program the other board.
Please refer to the [Debugprobe documentation](https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html#getting-started) for more details.

Note that Raspberry Pi actually uses their own OpenOCD fork, which is available in the [RP2040 OpenOCD repository](https://github.com/raspberrypi/openocd). While technically you can use the standard OpenOCD, it is recommended to use the Raspberry Pi fork for better compatibility with the RP2350, as its still fairly "new" and under development, which is why even their own Pico SDK Extension uses the Raspberry Pi fork of OpenOCD, instead of the standard one.

To do this, you need to connect the board to your computer and use the following command:

```bash
PROGRAMMER=openocd BOARD=rpi-pico-2 make flash
```

You can then debug your application using GDB with the following command:

```bash
PROGRAMMER=openocd BOARD=rpi-pico-2 make debug
```

### Flashing using Picotool

Simply connect the board to your computer via USB and use the following command:

```bash
BOARD=rpi-pico-2 make flash
```

This is the default method for flashing the Raspberry Pi Pico 2. However, it does not allow for debugging using GDB.

@note When programming the board with the Picotool for the first time, RIOT will download and install the Picotool locally in the RIOT folder. This process will take some minutes to complete.

## Known Issues {#rpi_pico_2_known_issues}

Currently RP2350 support is rather minimal, as such peripheral support is extremely limited. The following peripherals are supported:
- GPIO
- Non-configurable write-only UART (UART0 using Pin 0 and 1)
- The UART Baudrate is set to 115200.

More peripherals will be added in the future. It should also be noted that we currently only support the Cortex M33 cores, not the RISC-V Hazard cores.
33 changes: 33 additions & 0 deletions boards/rpi-pico-2/include/board.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2025 Tom Hert <[email protected]>
* SPDX-FileCopyrightText: 2025 HAW Hamburg
* SPDX-License-Identifier: LGPL-2.1-only
*/

#pragma once

/**
* @ingroup boards_rpi_pico_2
* @{
*
* @file
* @brief Board specific definitions for the Raspberry Pi Pico 2
*
* @author Tom Hert <[email protected]>
*/

#include "RP2350.h"
#include "cpu.h"
#include "cpu_conf.h"
#include "periph_conf.h"
#include "periph_cpu.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

/** @} */
18 changes: 18 additions & 0 deletions boards/rpi-pico-2/include/gpio_params.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2025 Tom Hert <[email protected]>
* SPDX-FileCopyrightText: 2025 HAW Hamburg
* SPDX-License-Identifier: LGPL-2.1-only
*/

#pragma once

#include "board.h"
#include "saul/periph.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif
20 changes: 20 additions & 0 deletions boards/rpi-pico-2/include/periph_conf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2025 Tom Hert <[email protected]>
* SPDX-FileCopyrightText: 2025 HAW Hamburg
* SPDX-License-Identifier: LGPL-2.1-only
*/

#pragma once

#include <stdint.h>

#include "RP2350.h"
#include "periph_cpu.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif
1 change: 1 addition & 0 deletions cpu/cortexm_common/ldscripts/cortexm_base.ld
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ SECTIONS
_sfixed = .;
_isr_vectors = DEFINED(_isr_vectors) ? _isr_vectors : . ;
KEEP(*(SORT(.vectors*)))
KEEP(*(SORT(.picobin_block*))) /* Keep picobin block used by RP2350 */
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
Expand Down
23 changes: 23 additions & 0 deletions cpu/rp2350/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# SPDX-FileCopyrightText: 2025 Tom Hert <[email protected]>
# SPDX-FileCopyrightText: 2025 HAW Hamburg
# SPDX-License-Identifier: LGPL-2.1-only

config CPU_FAM_RP2350
bool
select CPU_CORE_CORTEX_M33

config CPU_FAM
default "RP2350" if CPU_FAM_RP2350

config CPU_MODEL_RP2350
bool
select CPU_FAM_RP2350

config CPU_MODEL
default "RP2350" if CPU_MODEL_RP2350

config CPU
default "rp2350" if CPU_FAM_RP2350


source "$(RIOTCPU)/cortexm_common/Kconfig"
8 changes: 8 additions & 0 deletions cpu/rp2350/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MODULE = cpu

USEPKG += picosdk

DIRS += $(RIOTCPU)/cortexm_common
DIRS += periph

include $(RIOTBASE)/Makefile.base
1 change: 1 addition & 0 deletions cpu/rp2350/Makefile.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include $(RIOTCPU)/cortexm_common/Makefile.dep
9 changes: 9 additions & 0 deletions cpu/rp2350/Makefile.features
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CPU_CORE := cortex-m33
CPU_FAM := RP2350
CPU_ARCH = armv8m
CPU_MODEL = rp2350

include $(RIOTCPU)/cortexm_common/Makefile.features

FEATURES_PROVIDED += periph_gpio
FEATURES_PROVIDED += periph_uart
33 changes: 33 additions & 0 deletions cpu/rp2350/Makefile.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
ROM_LEN ?= 2097152 # = 2 MiB used in the RPi Pico
ROM_OFFSET := 0 # bootloader size
RAM_LEN := 0x82000 # 520kB = 532479 used in the RPi Pico 2350
ROM_START_ADDR := 0x10000000 # XIP Non-Secure address for rp2350
RAM_START_ADDR := 0x20000000 # Non-Secure RAM address for rp2350

# CPU and architecture specific flags
CFLAGS += -D$(CPU_MODEL)
CFLAGS += -DROM_START_ADDR=$(ROM_START_ADDR)
CFLAGS += -DRAM_START_ADDR=$(RAM_START_ADDR)
CFLAGS += -Wno-error

# Include paths
INCLUDES += -I$(RIOTCPU)/rp2350/include
INCLUDES += -isystem$(RIOTBASE)/dist/tools/picosdk/picosdk/src/rp2_common/cmsis/stub/CMSIS/Core/Include
INCLUDES += -isystem$(RIOTBASE)/dist/tools/picosdk/picosdk/src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include

# Linker flags
LINKFLAGS += -mcpu=$(CPU_ARCH) -mthumb
LINKFLAGS += -Wl,--gc-sections
LINKFLAGS += -Wl,--start-group -lc -lm -Wl,--end-group

# Vector table configuration
VECTORS_O ?= $(BINDIR)/cpu/vectors.o
VECTORS_FILE := $(RIOTCPU)/rp2350/vectors.c

# Supported programmers and debuggers
PROGRAMMERS_SUPPORTED := picotool openocd jlink
PROGRAMMER ?= picotool
OPENOCD_DEBUG_ADAPTER ?= dap

# Include the base Cortex-M makefile
include $(RIOTMAKE)/arch/cortexm.inc.mk
71 changes: 71 additions & 0 deletions cpu/rp2350/clock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* SPDX-FileCopyrightText: 2025 Tom Hert <[email protected]>
* SPDX-FileCopyrightText: 2025 HAW Hamburg
* SPDX-License-Identifier: LGPL-2.1-only
*/

/**
* @ingroup cpu_rp2350
* @{
*
* @file
* @brief Clock configuration implementation for the RP2350
*
* @author Tom Hert <[email protected]>
*/

#include "periph_cpu.h"

void clock_reset(void) {
/* Reset the clock system */
reset_component(RESET_PLL_SYS, RESET_PLL_SYS);
}

/**
* @brief Configures the XOSC and then sets CLK_SYS, PLL_SYS and CLK_PERI to it
* @warning Make sure to call clock_reset() before this function to reset the
* clock system
* @see RP2350 Docs Chapter 8, mostly 8.2 for more details
*/
void cpu_clock_init(void) {
/* Enable the XOSC */
xosc_start();

/* Setup the PLL using the XOSC as the reference clock. */
PLL_SYS->FBDIV_INT =
PLL_FEEDBACK_DIVIDER_VALUE; /* Set the feedback divider */

/* Set the post-dividers for the PLL output.*/
PLL_SYS->PRIM = PDIV;
/* Turn on PLL */
atomic_clear(&PLL_SYS->PWR,
PLL_PWR_PD_BITS | PLL_PWR_VCOPD_BITS | PLL_PWR_POSTDIVPD_BITS);

/* sleep 10ms to allow the PLL to stabilize */
xosc_sleep(10);

/* Based on the description in chapter 8 this is something that should be done
* However, it appears to cause issues and is not done by other examples on the
* internet. This needs to be investigated further. */

/* Wait for lock */
/* while (!(PLL_SYS->CS & PLL_CS_LOCK_BITS)) { */
/* Wait for the PLL to lock */
/* } */

/* AUXSRC = 0x0 7:5 && SRC == 0x0 0 */
CLOCKS->CLK_SYS_CTRL = CLK_SYS_PERI_CTRL_ENABLE_BIT;

/* This register contains one decoded bit for each of the clock sources
* enumerated in the CTRL SRC field. The bit does not directly correlate with
* the value of the SRC field For example 0x0 is the first bit while 0x1 is
* the second bit. In some way this makes sense, in some way I lost too much
* time on this. */
while (CLOCKS->CLK_SYS_SELECTED != CLK_SYS_SELECTED_PERI_FIELD_VALUE) {
}

/* AUXSRC = 0x0 -> CLK_SYS Indirectly through lower line */
CLOCKS->CLK_PERI_CTRL = CLK_PERI_CTRL_ENABLE_BIT;
}

/** @} */
Loading
Loading