
Raspberry Pi Pico2
- 52 installs
- 154 repo stars
- Updated July 30, 2026
- sammcj/agentic-coding
Helps with ai & agent building tasks.
About
raspberry-pi-pico2 is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- raspberry-pi-pico2
- AI & Agent Building
- AI-coding skill
Raspberry Pi Pico2 by the numbers
- 52 all-time installs (skills.sh)
- +4 installs in the week ending Jul 26, 2026 (Skillselion tracking)
- Ranked #7,034 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/sammcj/agentic-coding --skill raspberry-pi-pico2Add your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 52 |
|---|---|
| repo stars | ★ 154 |
| Last updated | July 30, 2026 |
| Repository | sammcj/agentic-coding ↗ |
What it does
Helps with ai & agent building tasks.
Files
Raspberry Pi Pico 2 and Debug Probe
This skill covers development with Raspberry Pi Pico 2 (RP2350) boards and the Raspberry Pi Debug Probe. It includes hardware specs, SDK setup, build configuration, debugging workflows, and common pitfalls.
Reference Files
Consult these for detailed technical content. Read only the file relevant to the current task:
references/pico2-hardware.md- RP2350 specs, RP2040 vs RP2350 comparison, pin layout, wireless variant, security features, chip variantsreferences/debug-probe.md- Debug Probe hardware, wiring diagrams, OpenOCD setup, GDB workflow, UART serial, RTT, VS Code integration, rescue mode, troubleshootingreferences/sdk-toolchain.md- pico-sdk setup, CMake configuration, ARM vs RISC-V builds, picotool commands, MicroPython/CircuitPython, project structure
Quick Reference
Board Selection (CMake)
| Board | CMake Flag | Platform |
|---|---|---|
| Pico 1 | -DPICO_BOARD=pico (default) | rp2040 |
| Pico 1 W | -DPICO_BOARD=pico_w | rp2040 |
| Pico 2 | -DPICO_BOARD=pico2 | rp2350-arm-s |
| Pico 2 W | -DPICO_BOARD=pico2_w | rp2350-arm-s |
| Pico 2 RISC-V | -DPICO_BOARD=pico2 -DPICO_PLATFORM=rp2350-riscv | rp2350-riscv |
Debug Probe Wiring (SWD)
| Debug Probe "D" Pin | Wire Colour | Pico 2 SWD Pad |
|---|---|---|
| SC | Orange | SWCLK |
| GND | Black | GND |
| SD | Yellow | SWDIO |
Debug Probe Wiring (UART)
| Debug Probe "U" Pin | Wire Colour | Pico 2 Pin | GPIO |
|---|---|---|---|
| TX | Orange | Pin 2 | GP1 (RX) |
| RX | Yellow | Pin 1 | GP0 (TX) |
| GND | Black | Pin 3 | GND |
Note the crossover: probe TX to Pico RX, probe RX to Pico TX.
OpenOCD Target Configs
| Target | Config File |
|---|---|
| Pico 1 (RP2040) | target/rp2040.cfg |
| Pico 2 (RP2350) | target/rp2350.cfg |
| Pico 2 RISC-V | target/rp2350.cfg with -c "set USE_CORE { rv0 rv1 }" |
| Rescue (RP2350) | target/rp2350.cfg with -c "set RESCUE 1" |
Typical Debug Session
# Terminal 1: OpenOCD
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000"
# Terminal 2: GDB
arm-none-eabi-gdb my_app.elf
(gdb) target remote localhost:3333
(gdb) monitor reset init
(gdb) load
(gdb) break main
(gdb) continueFlash via SWD
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
-c "adapter speed 5000" \
-c "program my_app.elf verify reset exit"Use the .elf file for SWD flashing, not .uf2.
Gotchas
These are the most common mistakes and non-obvious behaviours. Pay close attention.
1. SDK defaults to Pico 1. You must explicitly pass -DPICO_BOARD=pico2 to target RP2350. Forgetting this builds for RP2040 and the binary will not run on a Pico 2.
2. Use the Raspberry Pi fork of OpenOCD. Upstream OpenOCD (0.12.0) lacks full RP2350 support. Clone from https://github.com/raspberrypi/openocd.git branch rpi-common.
3. Wrong target config = failed connection. Using rp2040.cfg with a Pico 2 silently fails. Always match the target config to the chip.
4. SWD uses .elf, BOOTSEL uses .uf2. These are different formats for different flashing methods. Do not try to flash a .uf2 via OpenOCD/SWD.
5. Debug builds required for meaningful debugging. Always pass -DCMAKE_BUILD_TYPE=Debug to cmake. Release builds optimise away variable state and reorder code, making breakpoints unreliable.
6. RISC-V mode has no FPU. The hardware floating-point unit is only available on Cortex-M33. RISC-V mode uses software float, which is significantly slower for float-heavy code.
7. RISC-V requires a clean build directory. When switching between ARM and RISC-V, delete the build directory and re-run cmake. In-place switching does not work.
8. RISC-V debugging requires pre-selection. The RP2350 boots into Cortex-M33 by default. To debug RISC-V: picotool reboot -u -c riscv, then use OpenOCD with set USE_CORE { rv0 rv1 }.
9. Debug Probe does not power the target. The Pico 2 must be powered via its own USB or VSYS. The SWD connector carries no power.
10. LED pin differs on wireless models. Non-wireless Pico 2 uses GP25 for the onboard LED. Pico 2 W uses WL_GPIO0 through the CYW43439 wireless chip. Code must be conditional.
11. Git submodules are required. The pico-sdk needs git submodule update --init to pull tinyusb, cyw43-driver, lwip, btstack, and mbedtls. Missing submodules cause cryptic build failures.
12. OTP is irreversible. Writing OTP bits is permanent. Misconfiguring secure boot (setting SECURE_BOOT_ENABLE without a boot key and with PICOBOOT disabled) permanently bricks the device.
13. Wireless SPI pin sharing. On Pico 2 W, the VSYS ADC reading and CYW43439 IRQ checking are blocked during SPI transactions to the wireless chip.
14. Connect GND first. When the Pico 2 is powered from a separate source, connect GND between the target and Debug Probe before any signal lines. Voltage differences can damage the probe.
15. macOS: OpenOCD needs hidapi and libusb. Install via brew install hidapi libusb. If OpenOCD cannot find the probe, check no other process (VS Code, another OpenOCD instance) holds the USB device.
16. Multiple debug probes. If multiple CMSIS-DAP devices are connected, specify the serial number: adapter serial <serial_number> in your OpenOCD config.
Raspberry Pi Debug Probe Reference
Table of Contents
- Hardware Overview
- Wiring to Pico 2
- Software Installation
- OpenOCD Configuration
- GDB Debugging Workflow
- Flashing via SWD
- UART Serial Console
- RTT (Real-Time Transfer)
- VS Code Integration
- Debug Probe Firmware
- Using a Pico as Debug Probe
- Rescue Mode
- Troubleshooting
Hardware Overview
The Debug Probe is a USB device (built on RP2040) providing:
- USB to SWD (CMSIS-DAP compatible)
- USB to UART bridge (CDC serial)
Operates at 3.3V nominal I/O voltage.
Connectors
| Connector | Label | Type | Purpose |
|---|---|---|---|
| USB Micro-B | (top) | USB | Power and data to host |
| SWD port | "D" | 3-pin JST-SH (1.0mm) | Serial Wire Debug |
| UART port | "U" | 3-pin JST-SH (1.0mm) | Serial UART bridge |
Cable Colour Coding
| Colour | Signal |
|---|---|
| Orange | TX/SC (output from probe) |
| Black | GND |
| Yellow | RX/SD (input to probe or I/O) |
Included Cables
1. JST-SH to JST-SH (for boards with JST connector) 2. JST-SH to 0.1-inch female header (for soldered pin headers) 3. JST-SH to 0.1-inch male header (for breadboard use)
Wiring to Pico 2
SWD Connection (Port "D")
The Pico 2 must be powered separately (USB or VSYS). The SWD connector carries no power.
Boards with JST connector (Pico 2 with headers): Connect Debug Probe "D" port directly to Pico 2 SWD JST-SH with the JST-to-JST cable.
Boards with castellated pads (standard Pico 2): Solder headers to the three SWD pads, then use the JST-SH to 0.1-inch female cable:
| Debug Probe "D" | Wire | Pico 2 SWD Pad |
|---|---|---|
| SC | Orange | SWCLK |
| GND | Black | GND |
| SD | Yellow | SWDIO |
UART Connection (Port "U")
| Debug Probe "U" | Wire | Pico 2 Pin | GPIO |
|---|---|---|---|
| TX | Orange | Pin 2 | GP1 (UART0 RX) |
| RX | Yellow | Pin 1 | GP0 (UART0 TX) |
| GND | Black | Pin 3 | GND |
Crossover: probe TX to Pico RX, probe RX to Pico TX.
Safety
When the Pico 2 is powered from a separate source, connect GND between target and probe first before any signal lines. Voltage differences can damage the probe.
Software Installation
Option A: VS Code Extension (Recommended)
Install raspberry-pi.raspberry-pi-pico from the VS Code marketplace. It bundles OpenOCD, ARM toolchain, GDB, and Cortex-Debug integration.
Option B: Manual Installation
OpenOCD (Raspberry Pi Fork)
The RPi fork is required for full RP2350 support. Upstream OpenOCD 0.12.0 is insufficient.
macOS:
brew install libusb hidapi libftdi capstone pkgconf
git clone https://github.com/raspberrypi/openocd.git --branch rpi-common --depth=1
cd openocd
./bootstrap
./configure --enable-cmsis-dap
make -j$(sysctl -n hw.logicalcpu)
sudo make installLinux (Debian/Ubuntu):
sudo apt install automake autoconf build-essential texinfo libtool \
libftdi-dev libusb-1.0-0-dev libhidapi-dev pkg-config
git clone https://github.com/raspberrypi/openocd.git --branch rpi-common --depth=1
cd openocd
./bootstrap
./configure --enable-cmsis-dap
make -j$(nproc)
sudo make installGDB
- ARM builds:
arm-none-eabi-gdb(from Arm GNU Toolchain) - RISC-V builds:
riscv32-unknown-elf-gdborgdb-multiarch - Linux alternative:
sudo apt install gdb-multiarch
picotool
macOS: brew install picotool Linux: Build from source at https://github.com/raspberrypi/picotool
OpenOCD Configuration
Target Config Files
| File | Purpose |
|---|---|
target/rp2040.cfg | RP2040 (Pico 1) dual Cortex-M0+ |
target/rp2350.cfg | RP2350 (Pico 2) dual Cortex-M33 and/or Hazard3 RISC-V |
target/rp2350-riscv.cfg | RP2350 RISC-V only |
target/rp2350-rescue.cfg | RP2350 rescue mode |
RP2040 vs RP2350 in OpenOCD
| Aspect | RP2040 | RP2350 |
|---|---|---|
| Target config | target/rp2040.cfg | target/rp2350.cfg |
| DAP protocol | ADIv5 with multidrop SWD | ADIv6 with SWD |
| Flash driver | rp2040 | rp2xxx |
| CPUTAPID | 0x01002927 | 0x00004927 |
USE_CORE Options (RP2350)
Controls which cores OpenOCD connects to:
| Value | Effect |
|---|---|
{ cm0 cm1 } | Both Cortex-M33 cores (default) |
cm0 | Cortex-M33 core 0 only |
rv0 | RISC-V Hazard3 core 0 only |
{ rv0 rv1 } | Both RISC-V cores |
{ cm0 cm1 rv0 rv1 } | All four core slots |
For RISC-V debugging, pre-select RISC-V mode first:
picotool reboot -u -c riscvOpenOCD Ports
| Port | Purpose |
|---|---|
| 3333 | GDB connections |
| 4444 | Telnet (OpenOCD commands) |
| 6666 | TCL scripting |
GDB Debugging Workflow
Step 1: Build with Debug Symbols
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DPICO_BOARD=pico2 ..
make -j$(nproc)-DCMAKE_BUILD_TYPE=Debug is critical. Without it, optimisations make breakpoints unreliable.
Step 2: Start OpenOCD
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000"Step 3: Connect GDB
arm-none-eabi-gdb my_app.elf(gdb) target remote localhost:3333
(gdb) monitor reset init
(gdb) load
(gdb) break main
(gdb) continueCommon GDB Commands
| Command | Effect |
|---|---|
target remote localhost:3333 | Connect to OpenOCD |
monitor reset init | Reset and halt at entry |
load | Flash ELF to target |
break main | Breakpoint at main() |
continue / c | Resume |
step / s | Step into |
next / n | Step over |
print var | Print variable |
info registers | Register state |
monitor reset halt | Reset and halt |
backtrace / bt | Call stack |
Flashing via SWD
Using OpenOCD
# Pico 2
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
-c "adapter speed 5000" \
-c "program my_app.elf verify reset exit"
# Pico 1
openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg \
-c "adapter speed 5000" \
-c "program my_app.elf verify reset exit"Use the .elf file for SWD. The .uf2 format is only for BOOTSEL drag-and-drop.
Using picotool
picotool load my_app.elf
picotool rebootUART Serial Console
The Debug Probe "U" port exposes a CDC serial device on the host.
Device Paths
| OS | Path |
|---|---|
| Linux | /dev/ttyACM0 or /dev/ttyACM1 |
| macOS | /dev/cu.usbmodemXXXX |
| Windows | COMx |
Connecting
# Linux
minicom -b 115200 -o -D /dev/ttyACM0
# macOS
ls /dev/cu.usbmodem*
screen /dev/cu.usbmodemXXXX 115200
# or
minicom -b 115200 -o -D /dev/cu.usbmodemXXXXDefault baud rate for SDK examples: 115200. Debug Probe firmware v2.3.0 supports opt-in autobaud.
Exit minicom: CTRL-A then X. Exit screen: CTRL-A then K, then Y.
RTT (Real-Time Transfer)
RTT uses the SWD debug channel for printf-style output. Faster than UART, no extra wiring needed.
VS Code (Cortex-Debug)
Add to launch.json:
"rttConfig": {
"enabled": true,
"address": "auto",
"decoders": [
{
"label": "",
"port": 0,
"type": "console"
}
]
}Output appears in the TERMINAL tab under RTT Ch:0 console.
Standalone GDB
(gdb) target remote localhost:3333
(gdb) monitor reset init
(gdb) monitor rtt setup 0x20000000 2048 "SEGGER RTT"
(gdb) monitor rtt start
(gdb) monitor rtt server start 60000 0
(gdb) continueThen in another terminal: nc localhost 60000
SDK Setup
Enable pico_stdio_rtt as the stdio driver in CMakeLists.txt instead of (or alongside) UART/USB.
VS Code Integration
Raspberry Pi Pico Extension
Extension ID: raspberry-pi.raspberry-pi-pico
Provides: project scaffolding, CMake build integration, bundled OpenOCD/GCC/GDB, one-click debug, register viewer, RTT support.
Cortex-Debug Extension
Extension ID: marus25.cortex-debug
For manual configuration, a launch.json entry uses:
"servertype": "openocd""configFiles": ["interface/cmsis-dap.cfg", "target/rp2350.cfg"]"device": "RP2350"(or"RP2040")- The ELF file as
"executable"
Debug Probe Firmware
Current version: 2.3.0 (released 2025-02-11). Source: https://github.com/raspberrypi/debugprobe
Check Version (Linux)
lsusb -v -d 2e8a:000c | grep bcdDevice
# Reports bcdDevice 2.30 for v2.3.0The Info : CMSIS-DAP: FW Version = 2.0.0 from OpenOCD is the CMSIS-DAP protocol version, not the firmware version.
Update Procedure
1. Download debugprobe.uf2 from https://github.com/raspberrypi/debugprobe/releases/latest 2. Remove the Debug Probe enclosure top (pinch to open) 3. Hold BOOTSEL while plugging into USB. "RPI-RP2" volume mounts. 4. Copy debugprobe.uf2 onto the volume. 5. Probe reboots with new firmware.
Using a Pico as Debug Probe
The debugprobe firmware can run on a regular Pico or Pico 2.
Pico 1: Download debugprobe_on_pico.uf2 from releases, or build with cmake -DDEBUG_ON_PICO=ON ..
Pico 2:
git clone https://github.com/raspberrypi/debugprobe
cd debugprobe
git submodule update --init --recursive
mkdir build-pico2 && cd build-pico2
export PICO_SDK_PATH=/path/to/pico-sdk # SDK v2.0.0+
cmake -DDEBUG_ON_PICO=1 -DPICO_BOARD=pico2 ../
makeDownload debugprobe_on_pico2.uf2 from releases page.
Rescue Mode
Recover bricked Pico 2 devices (bad firmware causes crash loop):
# RP2350 rescue
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "set RESCUE 1"
# RP2040 rescue
openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "set RESCUE 1"RP2350 uses the RP_AP CTRL register RESCUE_RESTART bit. Both cores stop in the bootrom after rescue. Restart OpenOCD without the RESCUE flag and load fresh code.
Troubleshooting
Linux Permissions (udev rules)
# Debug Probe (VID:PID 2e8a:000c)
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="2e8a", ATTR{idProduct}=="000c", MODE="0666"' | \
sudo tee /etc/udev/rules.d/99-debug-probe.rules
# Pico in BOOTSEL mode
# RP2040: 2e8a:0003, RP2350: 2e8a:000f
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="2e8a", ATTR{idProduct}=="0003", MODE="0666"' | \
sudo tee -a /etc/udev/rules.d/99-debug-probe.rules
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="2e8a", ATTR{idProduct}=="000f", MODE="0666"' | \
sudo tee -a /etc/udev/rules.d/99-debug-probe.rules
sudo udevadm control --reload-rules
sudo udevadm triggerUSB VID:PID Reference
| Device | VID:PID |
|---|---|
| Debug Probe | 2e8a:000c |
| RP2040 BOOTSEL | 2e8a:0003 |
| RP2350 BOOTSEL | 2e8a:000f |
macOS
- Install
hidapiandlibusbvia Homebrew - No special driver needed for CMSIS-DAP
- If probe not found: check no other process holds the USB device
Common Issues
| Symptom | Cause | Fix |
|---|---|---|
| OpenOCD cannot find probe | Another process using it | Close VS Code debug / other OpenOCD |
| Connection timeout | Wrong target config | Match rp2040.cfg or rp2350.cfg to your chip |
| Unreliable breakpoints | Release build | Rebuild with -DCMAKE_BUILD_TYPE=Debug |
| SWD not working | No power to target | Power Pico 2 via USB or VSYS |
| Garbled UART output | Wrong baud rate | Check code matches 115200 (or configure) |
| Multiple probes, wrong one selected | Ambiguous device | Use adapter serial <serial> |
| Slow/unstable SWD | Cable too long / speed too high | Reduce to adapter speed 1000 |
Pico 2 (RP2350) Hardware Reference
Table of Contents
- RP2350 Specifications
- Chip Variants
- RP2040 vs RP2350 Comparison
- Pin Compatibility
- Architecture Switching
- Pico 2 W Wireless
- Security Features
- Board Layout
RP2350 Specifications
| Attribute | Value |
|---|---|
| CPU (ARM) | Dual-core Arm Cortex-M33, up to 150 MHz |
| CPU (RISC-V) | Dual-core Hazard3 (open-hardware RISC-V), up to 150 MHz |
| SRAM | 520 kB in 10 independent banks |
| On-board flash (Pico 2) | 4 MB external QSPI |
| Max external flash | Up to 32 MB via QSPI XIP |
| PSRAM support | Yes, via QMI memory interface |
| GPIO (Pico 2 board) | 26 multi-function pins exposed (chip has 30; 4 used internally) |
| ADC | 4 analogue inputs + internal temperature sensor, 500 kS/s, 12-bit |
| PIO | 3 blocks x 4 state machines = 12 total |
| DMA | 16 channels |
| PWM | 16 channels (RP2350A) / 24 channels (RP2350B) |
| HSTX | High-speed serial transmit peripheral (DVI video output) |
| USB | USB 1.1 controller and PHY, host and device |
| UART | 2x |
| SPI | 2x |
| I2C | 2x |
| Timers | 2 timers with 4 alarms each + Always-On (AON) timer |
| FPU | Hardware single + double precision (ARM mode only) |
| Core voltage | On-chip buck converter (SMPS) + optional LDO for sleep |
| AHB crossbar | AHB5 (upgraded from AHB-Lite on RP2040) |
Chip Variants
| Variant | GPIO | ADC Channels | Flash | PWM |
|---|---|---|---|---|
| RP2350A | 30 | 4 | External QSPI only | 16 |
| RP2350B | 48 | 8 | External QSPI only | 24 |
| RP2354A | 30 | 4 | 2 MB stacked on-chip | 16 |
| RP2354B | 48 | 8 | 2 MB stacked on-chip | 24 |
The Pico 2 board uses the RP2350A variant.
RP2040 vs RP2350 Comparison
| Feature | Pico 1 / RP2040 | Pico 2 / RP2350 |
|---|---|---|
| CPU | Dual Cortex-M0+ | Dual Cortex-M33 or Dual Hazard3 RISC-V |
| Clock | Up to 133 MHz | Up to 150 MHz |
| SRAM | 264 kB (6 banks) | 520 kB (10 banks) |
| On-board flash | 2 MB | 4 MB |
| Max external flash | 16 MB | 32 MB |
| PSRAM | Not supported | Supported via QMI |
| PIO | 2 blocks, 8 state machines | 3 blocks, 12 state machines |
| DMA channels | 12 | 16 |
| HSTX | No | Yes |
| FPU | Software float | Hardware single+double (ARM only) |
| Integer divider | Dedicated hardware block | In-CPU native division |
| Security | None | TrustZone, signed boot, OTP, SHA-256, TRNG, glitch detectors |
| Timers | 1 timer, 4 alarms | 2 timers, 4 alarms each, + AON timer |
| AHB | AHB-Lite | AHB5 |
| Core voltage | On-chip LDO | On-chip SMPS + optional LDO |
Performance: M33 core is roughly 2x faster than M0+ at comparable tasks.
Migration Notes
- Pico 2 is a drop-in hardware replacement for Pico 1 (same 40-pin form factor, same pin layout).
- Code targeting RP2040 needs recompilation with
-DPICO_BOARD=pico2but most SDK code is portable. - Code using the RP2040 dedicated hardware integer divider directly (not via SDK) needs adjustment; RP2350 uses in-CPU division.
- For DVI/video output, prefer the HSTX peripheral on RP2350 instead of pushing PIO to its limits.
Pin Compatibility
Pico 2 maintains full pin compatibility with Pico 1:
- Same 40-pin form factor and castellated pads
- Same 26 user GPIO pins at the same positions
- Same pin numbering
- Same power pin positions: 3V3, VSYS, VBUS, 3V3_EN, ADC_VREF, AGND, RUN
- Same peripheral pin mapping (SPI, I2C, UART, ADC on the same GPIOs)
- LED on GP25 (non-wireless) or WL_GPIO0 (wireless models)
No breaking pin changes between generations.
Architecture Switching (ARM vs RISC-V)
RP2350 contains both dual Cortex-M33 and dual Hazard3 RISC-V cores. One architecture is selected at build time; they cannot run simultaneously.
The boot ROM auto-detects ARM vs RISC-V from the binary and switches automatically.
Build for ARM (default)
cmake -DPICO_BOARD=pico2 ..Build for RISC-V
export PICO_TOOLCHAIN_PATH=/opt/riscv/riscv-toolchain-14/
export PICO_PLATFORM=rp2350-riscv
cmake -DPICO_BOARD=pico2 ..Prebuilt RISC-V toolchains: https://github.com/raspberrypi/pico-sdk-tools/releases
RISC-V Limitations
- No double-precision FPU (software float only)
- Some security features unavailable (TrustZone is ARM-specific)
- Must delete build directory and re-run cmake when switching architectures
Pico 2 W Wireless
| Feature | Detail |
|---|---|
| Wireless chip | Infineon CYW43439, SPI at up to 33 MHz |
| Antenna | On-board, licensed from ABRACON |
| Wi-Fi | 802.11n, 2.4 GHz, WPA3, soft AP (up to 4 clients) |
| Bluetooth | BT 5.2: BLE Central + Peripheral, Classic |
| LED | Via WL_GPIO0 (not GP25) |
SDK Libraries for Wireless
pico_cyw43_driver/pico_cyw43_arch- Wi-Fi driverpico_lwip- TCP/IP networkingpico_btstack- Bluetooth (BlueKitchen BTStack)pico_mbedtls- TLS/crypto
Wireless Pin Sharing
The SPI CLK to CYW43439 is shared with the VSYS voltage monitor. You can only read VSYS via ADC when no SPI transaction to the wireless chip is in progress. Similarly, CYW43439 DIN/OUT and IRQ share a pin.
Antenna Placement
Keep the antenna area free of metal. Grounded metal along the sides can improve bandwidth, but metal near or under the antenna degrades gain.
Security Features (RP2350 Only)
RP2040 has no security features. RP2350 adds:
| Feature | Detail |
|---|---|
| Arm TrustZone | Secure/non-secure world isolation (Cortex-M33 only) |
| Signed boot | Boot ROM verifies binary signatures |
| Encrypted boot | AES-256 encrypted code in flash |
| OTP memory | 8 kB antifuse one-time-programmable for key storage |
| SHA-256 | Hardware acceleration (pico_sha256 SDK library) |
| TRNG | Hardware true random number generator |
| Glitch detectors | Fault injection protection |
Secure Boot with picotool
# Sign a binary
picotool seal --sign app.elf app.signed.elf private.pem otp.json
# Encrypt a binary (self-decrypting)
picotool encrypt --embed --sign app.elf app.enc.elf aes_key.bin iv_salt.bin private.pem otp.json
# Program OTP
picotool otp load otp.jsonOTP Warnings
- OTP bits go from 0 to 1 and cannot be reversed. Permanent.
- Setting SECURE_BOOT_ENABLE without a boot key and with PICOBOOT disabled permanently bricks the device.
- Errata RP2350-E15: OTP permissions require running a small binary on-device. If secure boot is active, that binary must be signed. picotool handles this automatically.
Board Layout
SWD Debug Connector Location
| Board | Location | Type |
|---|---|---|
| Pico 2 | Bottom edge | Three castellated through-hole pads |
| Pico 2 with headers | Bottom edge | Keyed 3-pin JST-SH connector |
| Pico 2 W | Central, below MCU | Three through-hole pads |
| Pico 2 W with headers | Central, below MCU | Keyed 3-pin JST-SH connector |
Power Pins (40-pin edges)
- Pin 36: 3V3(OUT)
- Pin 37: 3V3_EN (pull to GND to turn off board)
- Pin 39: VSYS
- Pin 40: VBUS
- Pin 35: ADC_VREF
- Pin 33: AGND (analogue ground)
- Pin 30: RUN (active low reset)
Pico SDK and Toolchain Reference
Table of Contents
- Current Versions
- SDK Setup
- CMake Configuration
- Project Structure
- Toolchain Requirements
- picotool
- SDK Libraries
- stdio Configuration
- MicroPython
- CircuitPython
- BOOTSEL and UF2 Flashing
- Key References
Current Versions
| Tool | Version |
|---|---|
| pico-sdk | 2.2.0 |
| picotool | 2.2.0 |
| Debug Probe firmware | 2.3.0 |
| CircuitPython (Pico 2) | 10.1.4 stable |
SDK Setup
Clone and Configure
git clone https://github.com/raspberrypi/pico-sdk.git
cd pico-sdk
git submodule update --init
export PICO_SDK_PATH=$(pwd)Submodules pull: tinyusb, cyw43-driver, lwip, btstack, mbedtls. Missing submodules cause build failures for USB and wireless features.
System Dependencies
Debian/Ubuntu:
sudo apt install cmake python3 build-essential gcc-arm-none-eabi \
libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlibmacOS (Homebrew):
brew install cmake python arm-none-eabi-gccSDK Integration Methods
1. Cloned locally (most common): Copy external/pico_sdk_import.cmake into your project. Set PICO_SDK_PATH env var or pass -DPICO_SDK_PATH=... to cmake. 2. Git submodule: Include pico-sdk/pico_sdk_init.cmake directly. 3. Auto-download: Set PICO_SDK_FETCH_FROM_GIT=on before including pico_sdk_import.cmake.
CMake Configuration
Key Variables
| Variable | Purpose | Values |
|---|---|---|
PICO_BOARD | Board definition (sets pin defaults, enables libs) | pico, pico_w, pico2, pico2_w |
PICO_PLATFORM | Chip platform and architecture | rp2040, rp2350-arm-s, rp2350-riscv |
PICO_SDK_PATH | Path to cloned SDK | Absolute path |
PICO_TOOLCHAIN_PATH | Override toolchain location | Path to compiler prefix |
CMAKE_BUILD_TYPE | Build type | Debug, Release, MinSizeRel, RelWithDebInfo |
Setting PICO_BOARD=pico2 automatically sets PICO_PLATFORM=rp2350-arm-s. Only set PICO_PLATFORM explicitly for RISC-V override.
Board definitions live in pico-sdk/src/boards/include/boards/ as header files.
Minimal CMakeLists.txt
cmake_minimum_required(VERSION 3.13...3.27)
include(pico_sdk_import.cmake)
project(my_project C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
add_executable(my_app src/main.c)
target_link_libraries(my_app pico_stdlib)
pico_add_extra_outputs(my_app) # generates .uf2, .bin, .hex, .mapBuild Commands
# Pico 2 (ARM, default)
mkdir build && cd build
cmake -DPICO_BOARD=pico2 ..
make -j$(nproc)
# Pico 2 (RISC-V)
export PICO_TOOLCHAIN_PATH=/opt/riscv/riscv-toolchain-14/
mkdir build-riscv && cd build-riscv
cmake -DPICO_BOARD=pico2 -DPICO_PLATFORM=rp2350-riscv ..
make -j$(nproc)
# Pico 2 W
cmake -DPICO_BOARD=pico2_w ..
# Pico 1 (default if PICO_BOARD not set)
cmake ..
# or explicitly:
cmake -DPICO_BOARD=pico ..
# Debug build (for GDB debugging)
cmake -DPICO_BOARD=pico2 -DCMAKE_BUILD_TYPE=Debug ..Project Structure
my_project/
CMakeLists.txt
pico_sdk_import.cmake # copied from pico-sdk/external/
src/
main.c
include/
config.hFull Example CMakeLists.txt (Pico 2 with USB stdio)
cmake_minimum_required(VERSION 3.13...3.27)
include(pico_sdk_import.cmake)
project(my_project C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
add_executable(my_app
src/main.c
)
target_include_directories(my_app PRIVATE include)
target_link_libraries(my_app
pico_stdlib
hardware_gpio
hardware_i2c
hardware_pio
hardware_adc
)
# Enable USB output, disable UART output
pico_enable_stdio_usb(my_app 1)
pico_enable_stdio_uart(my_app 0)
pico_add_extra_outputs(my_app)Toolchain Requirements
| Target | Compiler | Package (Debian) |
|---|---|---|
| RP2040 (Cortex-M0+) | arm-none-eabi-gcc | gcc-arm-none-eabi, libnewlib-arm-none-eabi, libstdc++-arm-none-eabi-newlib |
| RP2350 ARM (Cortex-M33) | arm-none-eabi-gcc | Same as above |
| RP2350 RISC-V (Hazard3) | RISC-V GCC | Prebuilt from pico-sdk-tools releases |
Also requires: CMake >= 3.13, Python 3, native C compiler (for SDK build tools).
RISC-V Toolchain Setup
# Download (example for aarch64 Linux)
wget https://github.com/raspberrypi/pico-sdk-tools/releases/download/v2.0.0-5/riscv-toolchain-14-aarch64-lin.tar.gz
sudo mkdir -p /opt/riscv/riscv-toolchain-14
tar xvf riscv-toolchain-14-aarch64-lin.tar.gz -C /opt/riscv/riscv-toolchain-14
export PICO_TOOLCHAIN_PATH=/opt/riscv/riscv-toolchain-14/picotool
CLI tool for working with RP2040/RP2350 devices and binaries.
Installation
macOS: brew install picotool
Linux (from source):
git clone https://github.com/raspberrypi/picotool.git
cd picotool && mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make installPrebuilt: Download from https://github.com/raspberrypi/pico-sdk-tools/releases. Set picotool_DIR env var to the extracted path.
Commands
| Command | Purpose |
|---|---|
picotool info | Display connected device or binary info |
picotool info -a | Show all available info |
picotool load <file> | Flash binary to device |
picotool load -x <file> | Flash and immediately execute |
picotool reboot | Reboot into application mode |
picotool reboot -u | Reboot into BOOTSEL mode |
picotool reboot -u -c riscv | Reboot into BOOTSEL, pre-select RISC-V |
picotool config | Read/write device configuration |
picotool partition info | Display partition table |
picotool seal | Sign a binary (RP2350 only) |
picotool encrypt | Encrypt and sign (RP2350 only) |
picotool otp load | Load data into OTP rows |
picotool otp dump | Dump OTP contents |
picotool otp permissions | Set OTP access permissions |
SDK Libraries
| Library | Header | Purpose |
|---|---|---|
pico_stdlib | pico/stdlib.h | Aggregates GPIO, UART, time |
hardware_gpio | hardware/gpio.h | GPIO control |
hardware_i2c | hardware/i2c.h | I2C controller |
hardware_spi | hardware/spi.h | SPI controller |
hardware_pio | hardware/pio.h | Programmable I/O |
hardware_adc | hardware/adc.h | ADC |
hardware_pwm | hardware/pwm.h | PWM |
hardware_timer | hardware/timer.h | Hardware timers |
pico_multicore | pico/multicore.h | Dual-core programming |
pico_cyw43_arch | pico/cyw43_arch.h | Wi-Fi/BT (Pico W / Pico 2 W) |
pico_sha256 | SHA-256 hardware accel (RP2350 only) | |
pico_stdio_rtt | RTT stdio driver |
stdio Configuration
The SDK supports three stdio backends, selectable per-target in CMakeLists.txt:
# USB CDC (appears as serial port on host)
pico_enable_stdio_usb(my_app 1)
pico_enable_stdio_uart(my_app 0)
# UART (default UART0 on GP0/GP1)
pico_enable_stdio_usb(my_app 0)
pico_enable_stdio_uart(my_app 1)
# Both simultaneously
pico_enable_stdio_usb(my_app 1)
pico_enable_stdio_uart(my_app 1)
# RTT (via SWD debug channel, needs pico_stdio_rtt linked)UART stdio is useful with the Debug Probe's UART bridge. USB stdio is convenient for standalone development without a Debug Probe.
MicroPython
UF2 Downloads
- Pico 2:
https://micropython.org/download/RPI_PICO2/RPI_PICO2-latest.uf2 - Pico 2 W:
https://micropython.org/download/RPI_PICO2_W/RPI_PICO2_W-latest.uf2
Differences from Pico 1
- Separate firmware builds (RPI_PICO2 vs rp2-pico)
- 520 kB SRAM available (vs 264 kB)
- Third PIO block (PIO2) accessible
- Cortex-M33 FPU for floating-point
- Wi-Fi/BT on Pico 2 W (CYW43439)
Workflow
Hold BOOTSEL, plug USB, device mounts as "RP2350", drag UF2 onto it. Use Thonny IDE or mpremote for interactive development.
CircuitPython
Fully supported on Pico 2. Current stable: 10.1.4. Download: https://circuitpython.org/board/raspberry_pi_pico2/
Benefits from Pico 2's 4 MB flash (larger filesystem), extra SRAM, and third PIO block.
BOOTSEL and UF2 Flashing
1. Hold BOOTSEL button while connecting Pico to USB 2. Device mounts as USB mass storage "RPI-RP2" 3. Drag and drop .uf2 file onto the drive 4. Pico reboots and runs new firmware
BOOTSEL is in read-only ROM and cannot be overwritten. It always works regardless of firmware state.
Flash Erase
Copy nuke.uf2 onto the device while in BOOTSEL to wipe external flash. Source: pico-examples/flash/nuke/nuke.c.
Partition Tables (RP2350)
RP2350 supports A/B partition tables in flash. picotool partition info shows the layout. UF2 family IDs: rp2350-arm-s (ARM) and rp2350-riscv (RISC-V).
Key References
| Resource | URL |
|---|---|
| pico-sdk | https://github.com/raspberrypi/pico-sdk |
| pico-examples | https://github.com/raspberrypi/pico-examples |
| pico-extras | https://github.com/raspberrypi/pico-extras |
| picotool | https://github.com/raspberrypi/picotool |
| C/C++ SDK docs | https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html |
| RP2350 datasheet | https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf |
| Pico 2 datasheet | https://datasheets.raspberrypi.com/pico/pico-2-datasheet.pdf |
| Getting Started PDF | https://rptl.io/pico-get-started |
| SDK API reference | https://rptl.io/pico-c-sdk |
| Doxygen API docs | https://rptl.io/pico-doxygen |
| MicroPython docs | https://www.raspberrypi.com/documentation/microcontrollers/micropython.html |
| CircuitPython Pico 2 | https://circuitpython.org/board/raspberry_pi_pico2/ |
| VS Code extension | raspberry-pi.raspberry-pi-pico |
| RISC-V toolchains | https://github.com/raspberrypi/pico-sdk-tools/releases |
| Board definitions | pico-sdk/src/boards/include/boards/ |
| Pico W networking | https://rptl.io/picow-connect |