Core Specifications
The RP2040 is a dual-core Arm Cortex-M0+ microcontroller designed for embedded applications requiring flexible digital I/O, deterministic peripheral timing and programmable hardware interfaces.
It contains 264 KB of on-chip SRAM but no internal programme flash. Firmware is normally stored in external QSPI flash and executed through the XIP (execute-in-place) interface.
| Parameter | Specification |
|---|---|
| Manufacturer | Raspberry Pi |
| Processor | 2 × Arm Cortex-M0+ |
| Architecture | Armv6-M |
| Maximum specified system clock | 133 MHz |
| On-chip SRAM | 264 KB |
| Internal programme flash | None |
| External flash interface | QSPI |
| GPIO | 30 user-bank GPIO signals |
| ADC | 12-bit SAR, 5 inputs including temperature sensor |
| UART | 2 |
| SPI | 2 |
| I2C | 2 |
| PWM | 8 slices, 16 channels |
| PIO | 2 blocks, 8 state machines |
| DMA | 12 channels |
| USB | USB 1.1 controller and PHY |
| Hardware timers | 64-bit timer with 4 alarms |
| Watchdog | Hardware watchdog |
| Package | 56-pin QFN |
| Core supply | 1.1 V nominal |
| I/O supply | 1.8–3.3 V operating range |
The RP2040 is used on the Raspberry Pi Pico and Pico W, but the microcontroller and development board are not interchangeable specifications. The Pico provides external flash, power regulation, USB connectivity and a subset of the RP2040’s GPIO signals on its headers.
Processor and Multicore Architecture
Both Cortex-M0+ cores can execute independently and share access to SRAM and peripherals.
| Resource | Configuration |
|---|---|
| Core 0 | Cortex-M0+ |
| Core 1 | Cortex-M0+ |
| Instruction set | Arm Thumb |
| Floating-point unit | None |
| NVIC | Per core |
| SRAM | Shared |
| Hardware spinlocks | 32 |
| Inter-core FIFOs | Supported |
| Inter-core interrupts | Supported |
| DMA | Shared peripheral |
| SIO | Single-cycle I/O subsystem |
Floating-point operations are implemented in software unless replaced by application-specific optimisations.
Multicore Considerations
The second core does not automatically execute application code. It must be started explicitly by the firmware.
Both cores can access shared memory, but concurrent access requires appropriate synchronisation.
A volatile declaration does not provide mutual exclusion or make a compound operation atomic.
Use hardware spinlocks, SDK synchronisation primitives or carefully designed atomic operations when sharing mutable data.
Pico SDK Multicore Example
#include "pico/stdlib.h"
#include "pico/multicore.h"
void core1_entry(void) {
while (true) {
multicore_fifo_push_blocking(0x12345678);
sleep_ms(1000);
}
}
int main(void) {
stdio_init_all();
multicore_launch_core1(core1_entry);
while (true) {
uint32_t value = multicore_fifo_pop_blocking();
printf("Received: 0x%08lx\n",
(unsigned long)value);
}
}
The example uses the SDK’s inter-core FIFO. In larger applications, account for any SDK facilities that also use inter-core communication resources.
Memory Architecture
RP2040 contains six independently accessible SRAM banks.
| Memory resource | Size |
|---|---|
| SRAM0 | 64 KB |
| SRAM1 | 64 KB |
| SRAM2 | 64 KB |
| SRAM3 | 64 KB |
| SRAM4 | 4 KB |
| SRAM5 | 4 KB |
| Total | 264 KB |
The four main banks support striped access through the bus fabric. The two smaller banks are useful for code, stacks or data requiring more predictable access characteristics.
Common Address Regions
| Address | Region |
|---|---|
| 0x00000000 | Boot ROM |
| 0x10000000 | XIP flash address space |
| 0x20000000 | SRAM striped alias |
| 0x20040000 | SRAM4 |
| 0x20041000 | SRAM5 |
| 0x40000000 | APB peripheral region |
| 0x50000000 | AHB peripheral region |
| 0xD0000000 | SIO registers |
The four main SRAM banks also have non-striped aliases. Use the SDK memory layout and linker configuration rather than assuming that every SRAM allocation has identical access characteristics.
External Flash
The RP2040 boots from external QSPI flash in conventional flash-based designs.
Important restrictions:
- Flash erase operations work on erase sectors.
- Flash programming has page-alignment requirements.
- XIP access may be unavailable during flash programming.
- Interrupt handlers executing from flash can cause problems during flash operations.
- The second processor core must be considered when modifying flash contents.
The Pico SDK provides flash programming functions and mechanisms for coordinating flash operations.
Persistent configuration should be stored in a reserved flash region outside the firmware image.
Clock System
The RP2040 has multiple clock sources and clock domains.
| Clock source | Purpose |
|---|---|
| ROSC | Internal ring oscillator |
| XOSC | External crystal oscillator |
| PLL_SYS | System clock generation |
| PLL_USB | USB-related clock generation |
| CLK_SYS | Processor and system bus clock |
| CLK_PERI | Peripheral clock |
| CLK_USB | USB clock |
| CLK_ADC | ADC clock |
| CLK_RTC | RTC clock |
The standard Raspberry Pi Pico uses a 12 MHz crystal.
A common SDK configuration produces a 125 MHz system clock, although the RP2040’s specified maximum is 133 MHz.
Do not assume every RP2040 board uses the same crystal or default clock configuration.
Clock-Dependent Peripherals
Changing the system clock can affect:
- PWM frequency.
- PIO timing.
- UART baud-rate generation.
- SPI timing.
- Software delay calibration.
- Peripheral clock dividers.
The Pico SDK provides clock-management functions through hardware/clocks.h.
#include "hardware/clocks.h" uint32_t frequency = clock_get_hz(clk_sys);
Use the actual configured clock frequency in timing calculations rather than relying on a fixed board default.
GPIO Architecture
RP2040 provides 30 user-bank GPIO signals, numbered GP0–GP29.
| Feature | Description |
|---|---|
| GPIO direction | Input or output |
| Pull-up | Software configurable |
| Pull-down | Software configurable |
| Drive strength | 2, 4, 8 or 12 mA settings |
| Slew-rate control | Supported |
| Schmitt trigger | Supported |
| Interrupts | Rising, falling, high and low |
| Alternate functions | Peripheral multiplexing |
| Fast GPIO access | SIO subsystem |
GPIO electrical levels are determined by the I/O supply.
The GPIO pins are not 5 V tolerant.
GPIO Function Selection
The GPIOx_CTRL registers select peripheral functions for individual pins.
Common function selections include:
| Function | Use |
|---|---|
| SPI | Serial peripheral interface |
| UART | Asynchronous serial interface |
| I2C | Two-wire serial interface |
| PWM | Hardware pulse-width modulation |
| SIO | Software-controlled GPIO |
| PIO0 | Programmable I/O block 0 |
| PIO1 | Programmable I/O block 1 |
| NULL | No selected peripheral output |
The function-selection value is hardware-defined. Use the SDK constants rather than inserting unverified numerical function codes.
Pico SDK GPIO Example
#include "pico/stdlib.h"
int main(void) {
const uint pin = 15;
gpio_init(pin);
gpio_set_dir(pin, GPIO_OUT);
while (true) {
gpio_put(pin, 1);
sleep_ms(250);
gpio_put(pin, 0);
sleep_ms(250);
}
}
GPIO Register Reference
The SIO peripheral provides direct GPIO access.
| Register | Purpose |
|---|---|
| GPIO_IN | Read GPIO input states |
| GPIO_OUT | Read/write output values |
| GPIO_OUT_SET | Atomically set output bits |
| GPIO_OUT_CLR | Atomically clear output bits |
| GPIO_OUT_XOR | Atomically toggle output bits |
| GPIO_OE | Output-enable state |
| GPIO_OE_SET | Enable selected outputs |
| GPIO_OE_CLR | Disable selected outputs |
| GPIO_OE_XOR | Toggle output-enable bits |
The set, clear and XOR registers avoid read-modify-write sequences for the corresponding operations.
Direct GPIO Toggle
The following fragment assumes GP15 has already been configured as an SIO output.
#include "hardware/structs/sio.h" sio_hw->gpio_togl = 1u << 15;
The SDK register structure exposes the GPIO XOR alias as gpio_togl.
Direct register access is useful for time-sensitive operations, although SDK functions are generally preferable where performance requirements permit.
UART, SPI and I2C
| Peripheral | Quantity | Typical use |
|---|---|---|
| UART | 2 | Serial communication |
| SPI | 2 | Displays, sensors and flash peripherals |
| I2C | 2 | Sensors and control devices |
Peripheral signals are routed through the GPIO function multiplexer.
UART Reference
| Parameter | Description |
|---|---|
| Controllers | UART0, UART1 |
| Data width | 5–8 bits |
| Parity | Optional |
| Stop bits | Configurable |
| FIFO | Supported |
| Hardware flow control | RTS/CTS support |
| DMA | Supported |
The RP2040 UART uses 3.3 V-compatible logic when the I/O supply is 3.3 V. It is not an RS-232 electrical interface.
SPI Reference
| Parameter | Description |
|---|---|
| Controllers | SPI0, SPI1 |
| Operating role | Controller/master and peripheral/slave |
| Clock polarity | Configurable |
| Clock phase | Configurable |
| Data width | 4–16 bits |
| FIFO | Supported |
| DMA | Supported |
SPI throughput depends on the peripheral clock, divider configuration, bus loading and application overhead.
I2C Reference
| Parameter | Description |
|---|---|
| Controllers | I2C0, I2C1 |
| Standard mode | 100 kbit/s |
| Fast mode | 400 kbit/s |
| Fast-mode Plus | Supported by controller |
| Addressing | 7-bit and 10-bit capabilities |
| FIFO | Supported |
| DMA | Supported |
The RP2040 I2C controllers support controller and target operation.
SDA and SCL require suitable pull-up resistors. The correct resistance depends on bus capacitance, voltage and timing requirements.
Analogue-to-Digital Converter
The RP2040 contains a 12-bit successive-approximation ADC.
| Parameter | Specification |
|---|---|
| Resolution | 12 bits |
| Channels | 5 |
| External analogue inputs | 4 at silicon level |
| Internal temperature sensor | 1 |
| Maximum documented conversion rate | 500 ksample/s |
| FIFO | 4 samples |
| DMA support | Yes |
The four external ADC inputs correspond to GPIO26–GPIO29.
On the Raspberry Pi Pico, GPIO29 is used internally for VSYS measurement, leaving three ADC inputs on the main header.
ADC Conversion
For an ideal 12-bit conversion:
Voltage ≈ ADC_code × VREF / 4095
At a 3.3 V reference:
LSB size = 3.3 V / 4096
≈ 0.806 mV
This represents ideal quantisation, not guaranteed measurement accuracy.
RP2040 ADC measurements can be affected by differential non-linearity, reference noise, input impedance and supply disturbances.
Pico SDK ADC Example
#include "pico/stdlib.h"
#include "hardware/adc.h"
int main(void) {
stdio_init_all();
adc_init();
adc_gpio_init(26);
adc_select_input(0);
while (true) {
uint16_t value = adc_read();
printf("ADC: %u\n", value);
sleep_ms(500);
}
}
PWM Hardware
The RP2040 provides eight PWM slices, each containing channels A and B.
| Parameter | Specification |
|---|---|
| PWM slices | 8 |
| Channels per slice | 2 |
| Total channels | 16 |
| Counter width | 16-bit |
| Clock divider | Fractional |
| Edge-aligned mode | Supported |
| Phase-correct mode | Supported |
| Interrupt generation | Supported |
For edge-aligned PWM:
PWM_frequency = f_sys / (divider × (TOP + 1))
Where f_sys is the PWM source clock frequency.
At a 125 MHz clock, divider 1 and TOP 12499:
PWM_frequency = 125000000 / 12500
= 10000 Hz
Channels A and B of the same slice share the counter frequency.
GPIO pins mapped to the same PWM slice and channel also share that channel’s waveform.
Programmable I/O
The RP2040 contains two PIO blocks.
| Resource | Quantity |
|---|---|
| PIO blocks | 2 |
| State machines per block | 4 |
| Total state machines | 8 |
| Instruction memory | 32 instructions per block |
| TX FIFO | 4 words per state machine |
| RX FIFO | 4 words per state machine |
| FIFO joining | Supported |
| DMA interface | Supported |
PIO state machines execute small instruction programmes independently of the Cortex-M0+ processors.
PIO Instruction Set
| Instruction | Purpose |
|---|---|
| JMP | Branch |
| WAIT | Wait for condition |
| IN | Shift input data |
| OUT | Shift output data |
| PUSH | Push input shift register to FIFO |
| PULL | Load output shift register from FIFO |
| MOV | Move data between supported destinations |
| IRQ | Interrupt flag operations |
| SET | Set immediate value |
PIO instruction timing is controlled by the state-machine clock divider and optional instruction delay fields.
PIO is suitable for custom digital protocols, precise pulse timing, signal capture and hardware-assisted serial interfaces.
PIO Resource Restriction
All four state machines within one PIO block share its 32-word instruction memory.
Different programmes may coexist if their combined instruction-memory requirements fit.
PIO0 and PIO1 have separate instruction memories.
DMA Controller
RP2040 provides 12 DMA channels.
| Feature | Description |
|---|---|
| Channels | 12 |
| Transfer width | 8, 16 or 32 bits |
| Incrementing addresses | Supported |
| Peripheral pacing | DREQ |
| Channel chaining | Supported |
| Ring addressing | Supported |
| Interrupts | Supported |
DMA can transfer data between memory and peripherals without requiring the processor to perform every individual transfer.
Common applications include:
- ADC sample capture.
- SPI transmit and receive buffers.
- UART transfers.
- PIO data streaming.
- Memory-to-memory transfers.
DMA Configuration Sequence
- Claim an available DMA channel.
- Select transfer width.
- Configure read and write address incrementing.
- Select the peripheral DREQ if required.
- Configure source, destination and transfer count.
- Start the channel.
- Wait for completion or handle its interrupt.
DMA does not automatically prevent concurrent access conflicts. Buffer ownership and synchronisation remain application responsibilities.
Timer and Watchdog
The RP2040 contains a hardware timer and watchdog.
Hardware Timer
| Feature | Description |
|---|---|
| Counter | 64-bit |
| Time base | Microseconds in normal SDK configuration |
| Hardware alarms | 4 |
| Alarm interrupts | Supported |
Common Pico SDK timing functions include:
| Function | Purpose |
|---|---|
| time_us_64() | Read microsecond timer |
| time_us_32() | Read lower 32 bits |
| sleep_us() | Microsecond delay |
| sleep_ms() | Millisecond delay |
| add_alarm_in_us() | Schedule alarm |
| add_repeating_timer_ms() | Configure repeating callback |
The 32-bit microsecond counter wraps after approximately 71.6 minutes.
Use 64-bit timing values or wrap-safe arithmetic for long-duration measurements.
Watchdog
The hardware watchdog can reset the microcontroller when software fails to service it within the configured timeout.
#include "hardware/watchdog.h" watchdog_enable(2000, true);
The example requests a 2000 ms watchdog timeout, with the second argument enabling the SDK’s pause-on-debug behaviour.
The application must periodically call:
watchdog_update();
Watchdog timing and debugger behaviour should be checked against the installed SDK and application requirements.
USB Controller
The RP2040 contains a USB 1.1 controller and integrated PHY.
| Feature | Description |
|---|---|
| USB version | USB 1.1 |
| Maximum signalling speed | Full-speed, 12 Mbit/s |
| Device mode | Supported |
| Host mode | Supported |
| PHY | Integrated |
| Endpoint buffering | Dedicated USB DPRAM |
The USB controller supports device and host operation, but USB host applications require suitable external power and connector arrangements.
USB full-speed signalling does not imply an application data throughput of 12 Mbit/s. Protocol overhead, endpoint configuration and firmware processing reduce achievable payload throughput.
Boot Process and External Flash
The RP2040 contains a factory-programmed boot ROM.
A typical flash boot sequence is:
- Reset releases the processor.
- Boot ROM executes.
- Boot ROM loads the second-stage bootloader from external flash.
- The second-stage bootloader configures the external flash interface.
- Application firmware executes through XIP.
The second-stage bootloader is commonly referred to as boot2.
BOOTSEL Mode
The RP2040 ROM supports USB bootloader operation. On Raspberry Pi Pico boards, holding BOOTSEL while connecting USB enters this mode.
The USB mass-storage device normally appears as RPI-RP2.
A compatible UF2 firmware image can then be copied to the device.
The BOOTSEL button is a board feature associated with the external flash chip-select arrangement, not a dedicated general-purpose RP2040 GPIO.
Common Pico SDK Headers
| Header | Purpose |
|---|---|
| pico/stdlib.h | Standard functions |
| pico/multicore.h | Multicore control |
| pico/sync.h | Synchronisation primitives |
| hardware/gpio.h | GPIO |
| hardware/adc.h | ADC |
| hardware/pwm.h | PWM |
| hardware/pio.h | PIO |
| hardware/dma.h | DMA |
| hardware/uart.h | UART |
| hardware/spi.h | SPI |
| hardware/i2c.h | I2C |
| hardware/clocks.h | Clock configuration |
| hardware/timer.h | Hardware timer |
| hardware/watchdog.h | Watchdog |
| hardware/irq.h | Interrupt handling |
| hardware/flash.h | Flash operations |
Debugging and Diagnostics
RP2040 supports Serial Wire Debug through SWCLK and SWDIO.
| Interface | Purpose |
|---|---|
| SWD | Hardware debugging |
| USB serial | Runtime diagnostic output |
| UART | External serial diagnostics |
| Watchdog | Recovery from software lock-up |
| Hardware timer | Timing measurements |
| DMA interrupts | Transfer diagnostics |
| PIO FIFOs | Interface status and data transfer |
A compatible SWD probe can inspect registers, set breakpoints and examine memory.
The RP2040 Cortex-M0+ cores do not provide the same advanced trace facilities as some higher-end Arm microcontrollers.
Common Engineering Problems
| Symptom | Likely cause | Corrective action |
|---|---|---|
| Firmware fails to boot | Incorrect boot stage or flash configuration | Check flash support and linker configuration |
| Core 1 does not run | Core not launched | Check multicore startup |
| Shared data becomes corrupted | Missing synchronisation | Use locks or appropriate atomic operations |
| GPIO output inactive | Incorrect function or direction | Check SIO selection and output enable |
| Peripheral cannot access pin | Incorrect GPIO mux setting | Check alternate-function assignment |
| UART baud rate incorrect | Peripheral clock mismatch | Verify clock configuration |
| ADC readings unstable | Reference noise or source impedance | Improve analogue signal conditioning |
| PWM frequency incorrect | Divider or TOP calculation error | Recalculate from actual clock |
| PIO programme fails to load | Insufficient instruction memory | Check block allocation |
| DMA transfer stalls | Incorrect DREQ or configuration | Inspect channel setup |
| Flash programming causes crash | XIP or multicore conflict | Use flash-safe programming procedures |
| Watchdog resets unexpectedly | Timeout too short or update omitted | Inspect watchdog servicing |
| USB device not detected | Clock, firmware or wiring issue | Check USB clock and device initialisation |
Hardware Design Restrictions
- RP2040 GPIO is not 5 V tolerant.
- External flash is required for normal flash-based firmware execution.
- The RP2040 has no internal programme flash.
- GPIO alternate functions must be selected explicitly.
- PWM channels can share slices and compare resources.
- PIO instruction memory is shared within each PIO block.
- DMA transfers require correct pacing and buffer management.
- ADC resolution does not guarantee equivalent measurement accuracy.
- Both processor cores share SRAM and peripheral resources.
- Flash programming can interfere with execute-in-place instruction fetching.
- USB host operation requires appropriate external power circuitry.
- The RP2040 has no hardware floating-point unit.
- The watchdog must be serviced within its configured timeout.
- Board-level pin availability depends on the hardware design.
The RP2040’s two processor cores, PIO state machines and DMA channels can operate concurrently, but memory access, clock configuration, peripheral ownership and shared hardware resources must be managed explicitly.