| Crates.io | defmt-embassy-usbserial |
| lib.rs | defmt-embassy-usbserial |
| version | 0.2.1 |
| created_at | 2025-10-27 16:44:56.273706+00 |
| updated_at | 2025-10-27 16:57:44.07244+00 |
| description | Transmit defmt log messages over USB serial |
| homepage | |
| repository | https://github.com/robjwells/defmt-embassy-usbserial |
| max_upload_size | |
| id | 1903255 |
| size | 87,925 |
defmtusb lets you read your Embassy firmware's defmt log messages over USB serial.
This is the easiest method, for when you are not otherwise using the USB peripheral in your firmware (to, for example, act as a keyboard).
Add defmtusb to your dependencies in your Cargo.toml file. In your firmware, create
an Embassy task that constructs your HAL-specific USB driver and an approriate USB
configuration. For example, using embassy-rp and with general firmware setup elided:
use embassy_rp::{bind_interrupts, Peri};
bind_interrupts!(struct Irqs {
USBCTRL_IRQ => embassy_rp::usb::InterruptHandler<embassy_rp::peripherals::USB>;
});
#[embassy_executor::task]
async fn defmtusb_wrapper(usb: Peri<'static, embassy_rp::peripherals::USB>) {
let driver = embassy_rp::usb::Driver::new(usb, Irqs);
let usb_config = {
let mut c = embassy_usb::Config::new(0x1234, 0x5678);
c.serial_number = Some("defmt");
c.max_packet_size_0 = 64;
c.composite_with_iads = true;
c.device_class = 0xEF;
c.device_sub_class = 0x02;
c.device_protocol = 0x01;
c
};
defmt_embassy_usbserial::run(driver, usb_config).await;
}
In your main function, pass in the USB peripheral and spawn the task:
spawner.must_spawn(defmtusb_wrapper(peripherals.USB));
Now you can use the defmt logging macros as you'd expect.
loop {
defmt::info!("Hello! {=u64:ts}", Instant::now().as_secs());
delay.delay_ms(1000).await;
}
On the host side, use defmt-print to decode and print the messages.
(Note: This section has not yet been updated since the fork from micro-rust/defmtusb.)
If you intend to create a variety of endpoints in the USB and use them, you can
create them and then simply pass a CDC ACM Sender to the logger task in
defmtusb. This method also requires the maximum packet size of the hardware
USB implementation.
#[task]
async fn logger_wrapper(usb: USB) {
// Create the USB driver.
let driver = Driver::new(usb, Irqs);
// Create the different interfaces and endpoints.
...
// Create the CDC ACM class.
let cdc = CdcAcmClass::new(&mut builder, &mut state, <max_packet_size>);
// Split to get the sender only.
let sender = class.split();
// Run only the logging function.
defmtusb::logger(sender, <max_packet_size>).await;
}
Any contribution intentionally submitted for inclusion in the work by you shall be licensed under either the MIT License or the Mozilla Public License Version 2.0, without any additional terms and conditions.
This work is licensed, at your option, under the