//! This example shows how to use USB (Universal Serial Bus) in the RP2040 chip. //! //! This creates the possibility to send log::info/warn/error/debug! to USB serial port. #![no_std] #![no_main] use core::str; use embassy_executor::Spawner; use embassy_rp::bind_interrupts; use embassy_rp::peripherals::USB; use embassy_rp::rom_data::reset_to_usb_boot; use embassy_rp::usb::{Driver, InterruptHandler}; use embassy_time::Timer; use embassy_usb_logger::ReceiverHandler; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { USBCTRL_IRQ => InterruptHandler; }); struct Handler; impl ReceiverHandler for Handler { async fn handle_data(&self, data: &[u8]) { if let Ok(data) = str::from_utf8(data) { let data = data.trim(); // If you are using elf2uf2-term with the '-t' flag, then when closing the serial monitor, // this will automatically put the pico into boot mode if data == "q" || data == "elf2uf2-term" { reset_to_usb_boot(0, 0); // Restart the chip } else if data.eq_ignore_ascii_case("hello") { log::info!("World!"); } else { log::info!("Recieved: {:?}", data); } } } fn new() -> Self { Self } } #[embassy_executor::task] async fn logger_task(driver: Driver<'static, USB>) { embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver, Handler); } #[embassy_executor::main] async fn main(spawner: Spawner) { let p = embassy_rp::init(Default::default()); let driver = Driver::new(p.USB, Irqs); spawner.spawn(logger_task(driver)).unwrap(); let mut counter = 0; loop { counter += 1; log::info!("Tick {}", counter); Timer::after_secs(1).await; } }