A Rust workspace that implements a no_std, async SX1278 LoRa driver and a set of example applications for Raspberry Pi Pico-class boards:
radio-sender(RP2350/Pico 2): transmits a short message repeatedlyradio-listener(RP2040/Pico): receives packets and logs RSSI/SNRlora-driver: embedded-hal 1.0 async driver for the SX1278led(RP2350): simple LED blinkusb(RP2350): USB logger + LED blink skeleton
The examples are built on Embassy and target the RP2040 and RP2350 using their respective Arm Cortex-M cores.
- Boards: Raspberry Pi Pico (RP2040) and/or Raspberry Pi Pico 2 (RP2350)
- Radio: SX1278 LoRa module (433 MHz), 3.3 V logic and power
- Wiring (SPI0 on Pico header):
- SCK → GP2
- MOSI → GP3
- MISO → GP4
- NSS/CS → GP5
- RESET → GP6
- LED (on-board) → GP25
- Power: 3V3 and GND
- Antenna: Use a proper 433 MHz antenna for the SX1278 module
The examples use these LoRa settings by default:
- Frequency: 433_000_000 Hz
- Bandwidth: 125 kHz
- Spreading factor: SF12
- Coding rate: 4/8
- Sync word: 0x12
- TX power: up to 20 dBm with PA_BOOST
Note: DIO0/IRQ is not used in these examples; RX/TX completion is polled.
- Workspace root
Cargo.tomllists members:radio-sender/(RP2350, targetthumbv8m.main-none-eabihf)radio-listener/(RP2040, targetthumbv6m-none-eabi)led/(RP2350)usb/(RP2350)lora-driver/(platform-agnostic,no_std)
- Each runtime crate has:
.cargo/config.tomlwith its target triple and a PowerShellrunnermemory.xandbuild.rsfor linker configuration
- Rust (stable) via rustup
- Arm embedded targets:
rustup target add thumbv6m-none-eabi thumbv8m.main-none-eabihf
- UF2 tooling (used by provided PowerShell scripts):
cargo install elf2flash
- Windows (recommended for the provided
runnerscripts). On Linux/macOS, adapt the copy step or therunnercommand.
The crate-level
.cargo/config.tomlfiles setrunnerto a PowerShell script that:
- converts the built ELF to a UF2 file with
elf2flash, and- copies it to the UF2 mass-storage device exposed by the board.
General flow (per example crate):
- Put the board in bootloader (UF2) mode: hold the BOOTSEL button while plugging in USB, or press RESET with BOOTSEL held.
- A removable drive named like
RPI-RP2,RPI-RP2350, orPICOappears. - From the example crate directory, run
cargo run --release.
The configured runner will convert the artifact to UF2 and copy it to the detected drive (defaults to E:\, otherwise auto-detects a removable RPI* volume).
cd radio-sender
cargo run --release- SPI pins: GP2/GP3/GP4, CS: GP5, RESET: GP6
- Periodically sends:
"Hello from Pico 2 - <counter>" - LED blinks briefly while sending
cd radio-listener
cargo run --release- Same SPI/CS/RESET pins as the sender
- Logs received payloads plus RSSI/SNR; automatically re-arms or resets the radio on CRC errors/timeouts
cd led
cargo run --releasecd usb
cargo run --release- Exposes a USB CDC serial interface and logs via
embassy-usb-logger - Connect with any serial terminal (baud setting is typically ignored for USB CDC;
115200 8N1is fine)
- Driver crate:
lora-driver/is ano_stdasync driver for the SX1278 usingembedded-halandembedded-hal-asynctraits plusembassy-time. - Targets:
- RP2040:
thumbv6m-none-eabi - RP2350:
thumbv8m.main-none-eabihf(Cortex-M33)
- RP2040:
- Linker scripts: each runtime crate ships a
memory.xand copies it inbuild.rs. - Logging: examples use the
logfacade withembassy-usb-logger.
If you need different PHY settings, change the calls in radio-sender/src/main.rs and radio-listener/src/main.rs:
set_frequency(u32 hz)set_bandwidth(Bandwidth)set_spreading_factor(SpreadingFactor)set_coding_rate(CodingRate)set_tx_power(level, use_pa_boost)set_sync_word(u8)
Ensure both ends use compatible parameters and a proper antenna for the chosen band.