#rp2040-bootloader #firmware #usb #rp2040 #upload #bootloader

app crispy-upload

Firmware upload tool for crispy-bootloader via USB CDC

1 unstable release

0.2.0 Feb 11, 2026

#399 in Embedded development

MIT license

42KB
668 lines

Crispy RP2040 — Bootloader + Firmware

A/B bootloader for RP2040 (Raspberry Pi Pico) written in Rust. The bootloader copies firmware from flash to RAM before executing it, and supports two banks for safe over-the-air updates via USB CDC.

         FLASH (2MB)                          RAM (256KB)
  ┌─────────────────────┐
  │  BOOT2 (256B)       │
  ├─────────────────────┤
  │  Bootloader (64KB)  │──── selects A or B
  ├─────────────────────┤          │
  │  FW Bank A (768KB)  │──┐       │
  ├─────────────────────┤  ├───────┼───► copy ───► ┌──────────────────┐
  │  FW Bank B (768KB)  │──┘       │               │ Firmware (192KB) │
  ├─────────────────────┤          │               │ runs from RAM    │
  │  BOOT_DATA (4KB)    │ ◄────────┘               │ @ 0x20000000     │
  └─────────────────────┘    active bank           └──────────────────┘

Firmware updates are performed via USB CDC using crispy-upload, or via SWD with probe-rs.

Note: Since firmware runs from RAM, standard probe-rs cannot set breakpoints (Cortex-M0+ FPB only covers flash addresses). This project requires a custom probe-rs fork that adds software breakpoint support. Install it with make install-probe-rs.

Project Structure

crispy-bootloader/     # RP2040 bootloader (flash → RAM copy, A/B bank selection)
crispy-fw-sample-rs/   # Sample Rust firmware (runs from RAM @ 0x20000000)
crispy-fw-sample-cpp/  # Sample C++ firmware (Pico SDK)
crispy-sdk-cpp/        # C++ SDK for Crispy bootloader
crispy-common/         # Shared Rust crate (board init, flash operations)
crispy-upload/         # Host tool to manage the bootloader (upload, wipe, ...)
scripts/               # Utility scripts (flash, build, python)
linker_scripts/        # Memory layouts for bootloader and firmware

Prerequisites

# Install rust-objcopy (cargo-binutils) and llvm-tools
make install-tools

Quick Start

# Show all available targets
make help

# Build everything (ELF + BIN + UF2)
make all

# Show crispy-upload usage
cargo run --release -p crispy-upload -- --help

Testing

Unit Tests

make test

Integration Tests (hardware)

Integration tests require a physical RP2040 board connected via SWD probe.

# Full run: build, flash, and test
./scripts/test-integration.sh --device /dev/ttyACM0

# Or using environment variables
export CRISPY_DEVICE=/dev/ttyACM0
./scripts/test-integration.sh

You can also run pytest directly from scripts/python/:

cd scripts/python
python -m pytest tests/test_integration.py -v --device /dev/ttyACM0

Environment Variables

Variable Description Example
CRISPY_DEVICE Serial port of the bootloader /dev/ttyACM0
CRISPY_SKIP_BUILD Skip cargo build step (1 to enable) 1
CRISPY_SKIP_FLASH Skip SWD flashing (1 to enable) 1

These work with both test-integration.sh and pytest. CLI flags (--device, --skip-build, --skip-flash) take precedence over environment variables.

CI Runner Example

For a self-hosted runner with a board permanently connected:

export CRISPY_DEVICE=/dev/ttyACM0
export CRISPY_SKIP_BUILD=1
export CRISPY_SKIP_FLASH=1
python -m pytest tests/test_integration.py -v

License

MIT — Copyright (c) 2026 ADNT Sàrl

Dependencies

~7–19MB
~204K SLoC