| Crates.io | rp-usb-console |
| lib.rs | rp-usb-console |
| version | 0.2.4 |
| created_at | 2025-09-30 19:14:22.959332+00 |
| updated_at | 2026-01-10 20:23:10.167245+00 |
| description | Zero-heap USB CDC logging and command channel for RP2040 with Embassy async framework |
| homepage | https://github.com/petersallai/rp-usb-console |
| repository | https://github.com/petersallai/rp-usb-console |
| max_upload_size | |
| id | 1861561 |
| size | 818,137 |
When developing for the Raspberry Pi Pico, you typically have two choices: debugging with a hardware probe or deploying programs directly via USB. The latter is quick and convenient, but it doesn’t allow runtime communication with your application. Embassy’s built-in usb-logger lets you stream logs over USB, yet it lacks a way to send commands back (such as rebooting into BOOTSEL mode). rp-usb-console fills this gap by providing a lightweight, zero-heap solution for both logging and command exchange over USB, designed specifically for the RP2040 and the Embassy async framework. Initially, I created this library for my own use.

All command must be ended with /r or /n or both.
Add this to your Cargo.toml:
[dependencies]
rp-usb-console = "0.1.0"
Basic usage example:
use embassy_executor::Spawner;
use embassy_sync::channel::Channel;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use log::info;
use rp_usb_console::USB_READ_BUFFER_SIZE;
// Create a channel for receiving commands from USB
static COMMAND_CHANNEL: Channel<CriticalSectionRawMutex, [u8; USB_READ_BUFFER_SIZE], 4> = Channel::new();
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
// Initialize USB logging with Info level
rp_usb_console::start(
spawner,
log::LevelFilter::Info,
p.USB,
Some(COMMAND_CHANNEL.sender()),
);
// Now you can use standard log macros
info!("Hello over USB!");
// Handle incoming commands in a separate task
spawner.spawn(command_handler()).unwrap();
}
#[embassy_executor::task]
async fn command_handler() {
let receiver = COMMAND_CHANNEL.receiver();
loop {
let command = receiver.receive().await;
// Process received command data (terminated by CR/LF; trailing zeros may be present)
info!("Received command: {:?}", command);
}
}
start()Initialize the USB CDC interface and spawn necessary tasks.
pub fn start(
spawner: Spawner,
level: LevelFilter,
usb_peripheral: Peri<'static, USB>,
command_sender: Option<Sender<'static, CriticalSectionRawMutex, [u8; USB_READ_BUFFER_SIZE], 4>>
)
Parameters:
spawner: Embassy task spawnerlevel: Log level filter (e.g., LevelFilter::Info)usb_peripheral: RP2040 USB peripheralcommand_sender: Optional channel sender for receiving line-buffered USB commands (None disables forwarding)LogMessageFixed-size message buffer with USB packet fragmentation support.
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.