RP2040 / Pico Platform Guide¶
Xylolabs SDK integration for the Raspberry Pi Pico (RP2040). The RP2040 is a cost-effective sensor-only target.
RP2040 Specifications¶
| Resource | Specification | Notes |
|---|---|---|
| CPU | Dual Cortex-M0+ @ 133 MHz | ~266 MIPS total; no DSP, no FPU |
| SRAM | 264 KB | Static allocation, no heap |
| Flash | External QSPI (2-16 MB typical) | Firmware + log storage |
| UART | 2 channels | LTE-M1 modem AT commands |
| ADC | 4 channels, 12-bit, 500 ksps | Sensor inputs (GPIO26-29) |
| SPI | 2 channels | External sensors, SD card |
| I2C | 2 channels | Temperature, humidity, pressure sensors |
| PIO | 8 state machines (2 blocks x 4) | Flexible I/O protocols |
| DMA | 12 channels | Zero-copy data transfers |
| WDT | Hardware watchdog | Long-term unattended operation |
| GPIO | 30 pins | Sensors, modem control, status LEDs |
Key Differences from RP2350¶
The RP2040 uses the same Pico SDK as the RP2350, but has important hardware differences:
| Feature | RP2040 (Pico) | RP2350 (Pico 2) |
|---|---|---|
| Core | Cortex-M0+ | Cortex-M33 |
| Clock | 133 MHz | 150 MHz |
| SRAM | 264 KB | 520 KB |
| FPU | None | Single-precision |
| DSP extensions | None | SIMD MAC, saturating |
| XAP audio | Not feasible | Full support (4ch @96kHz) |
| ADPCM audio | 1-2ch optional | 4ch supported |
| Pico SDK board | pico |
pico2 |
| Price | ~$4 | ~$5 |
XAP is not feasible on RP2040. The Cortex-M0+ lacks a hardware FPU, so all floating-point operations are software-emulated. XAP encoding requires ~10 MIPS/channel with FPU, but ~40+ MIPS/channel with software float -- exceeding the RP2040's budget for multi-channel audio.
Use Cases¶
The RP2040 is recommended for:
- Environmental monitoring: Temperature, humidity, pressure, CO2
- Simple vibration monitoring: Single-axis accelerometer via ADC
- Power monitoring: Current and voltage sensors
- Low-cost sensor networks: Where audio is not needed
For audio streaming, use the RP2350 (Pico 2) instead.
Hardware Setup¶
LTE Modem (UART0) -- BG770A¶
RP2040 GPIO LTE Modem
------------------ ------------------
GPIO0 (UART0_TX) ----- RXD
GPIO1 (UART0_RX) ----- TXD
GPIO2 (GPIO) ----- PWRKEY
GPIO3 (GPIO) ----- RESET_N
VSYS (5V) ----- VCC (via LDO)
GND ----- GND
Sensor Inputs (ADC)¶
| GPIO | ADC Channel | Typical Use |
|---|---|---|
| GPIO26 | ADC0 | Temperature sensor |
| GPIO27 | ADC1 | Humidity sensor |
| GPIO28 | ADC2 | Pressure sensor |
| GPIO29 | ADC3 | Vibration / current |
I2C Sensors¶
| Bus | GPIO | Typical Devices |
|---|---|---|
| I2C0 | GPIO4 (SDA), GPIO5 (SCL) | CHT832X (temp/humidity), BME280 |
| I2C1 | GPIO6 (SDA), GPIO7 (SCL) | LIS3DH (accelerometer) |
Rust Build (Recommended)¶
# Install dependencies
rustup target add thumbv6m-none-eabi
cargo install probe-rs-tools
# Build
cd sdk/examples/rp2040-sensor
cargo build --release
# Flash
cargo run --release # Uses probe-rs via .cargo/config.toml
See sdk/examples/ for all RP2040 examples.
Legacy C Build System¶
cmake_minimum_required(VERSION 3.13)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(my_sensor_node C CXX ASM)
set(PICO_BOARD pico) # Important: target original Pico, not Pico 2
pico_sdk_init()
add_subdirectory(sdk/rp2040)
add_executable(my_sensor_node src/main.c)
target_link_libraries(my_sensor_node
pico_stdlib
hardware_adc
hardware_i2c
hardware_watchdog
hardware_timer
xylolabs_sdk_rp2040
)
pico_add_extra_outputs(my_sensor_node)
Key Difference from RP2350 Build¶
Set PICO_BOARD=pico (not pico2). The Pico SDK automatically selects the correct startup code and linker script for the RP2040.
Memory Budget¶
| Region | Size | Config Macro |
|---|---|---|
| XMBP packet buffer | 4 KB | XYLOLABS_XMBP_BUF_SIZE |
| HTTP buffer | 4 KB | XYLOLABS_HTTP_BUF_SIZE |
| Metadata accumulation | ~4 KB | 4ch x 100 samples x f32 |
| AT command buffer | ~1 KB | Internal |
| Stack + SDK internals | ~8 KB | |
| Total SDK | ~21 KB | 8% of 264 KB |
| Available for app | ~243 KB |
Software Float Considerations¶
Since the RP2040 has no FPU, floating-point operations are emulated:
floatmultiply: ~20 cycles (vs 1 cycle on Cortex-M4F)floatdivide: ~70 cyclesfloattrig: ~200+ cycles
For performance-critical sensor calibration, consider using fixed-point integer math with scaling factors instead of floating-point.
Power Management¶
The RP2040 supports dormant and sleep modes:
// Rust (Embassy) - Recommended
use embassy_time::Timer;
// Lightweight sleep between samples (async timer wakeup)
Timer::after_micros(interval_us - 500).await;
// For event-triggered wakeup, use embassy GPIO interrupt
let mut sensor_int = Input::new(p.PIN_X, Pull::Down);
sensor_int.wait_for_rising_edge().await;
Legacy C equivalent
Rust (Recommended)¶
Rust is the recommended language for new RP2040 projects. The Embassy-based Rust examples provide async sensor polling and networking with compile-time safety.
cd sdk/examples/rp2040-sensor
cargo build --release
# Flash the resulting ELF via probe-rs
probe-rs run --chip RP2040 target/thumbv6m-none-eabi/release/rp2040-sensor
See sdk/examples/README.md for detailed build instructions.
C Examples (alternative)
### Existing Examples The `sdk/c/rp2040/examples/` directory contains: | Example | Description | |---------|-------------| | `sensor_node.c` | 4-channel ADC sensor streaming at 100Hz |Troubleshooting¶
| Symptom | Likely Cause | Fix |
|---|---|---|
| Watchdog reset loop | xylolabs_tick() not called often enough |
Ensure tick runs every 4 seconds |
| Inaccurate sensor values | Software float rounding | Use integer math with scaling |
| High power consumption | Not using sleep between samples | Add sleep_us() in main loop |
| Build fails with RP2350 errors | Wrong PICO_BOARD setting | Set PICO_BOARD=pico in CMake |
| Modem not responding | UART baud mismatch | Default 115200, check modem config |
Further Reading¶
sdk/rp2040/README.md-- SDK file listing and quick-startdocs/PLATFORM-PICO.md-- RP2350 guide (for comparison)- Pico SDK documentation
- RP2040 datasheet