From f46db13d6407dc6f5976c728621860c2f818284f Mon Sep 17 00:00:00 2001 From: Wilfried Chauveau Date: Tue, 15 Aug 2023 18:54:26 +0100 Subject: [PATCH 1/3] update pico_usb_serial_interrupt --- .../examples/pico_usb_serial_interrupt.rs | 209 ++++++++++-------- 1 file changed, 118 insertions(+), 91 deletions(-) diff --git a/boards/rp-pico/examples/pico_usb_serial_interrupt.rs b/boards/rp-pico/examples/pico_usb_serial_interrupt.rs index 676d576f..884328e3 100644 --- a/boards/rp-pico/examples/pico_usb_serial_interrupt.rs +++ b/boards/rp-pico/examples/pico_usb_serial_interrupt.rs @@ -12,22 +12,31 @@ #![no_std] #![no_main] +// A cell to be used with `critical_section::Mutex` +use core::cell::RefCell; + +// Trait required to use `writeln!(…)` +use core::fmt::Write; + +// A system wide mutex synchrinising IRQ & cores +use critical_section::Mutex; + +// Import common embedded_hal traits +use embedded_hal::prelude::*; + +// The macro for marking out exception function +use cortex_m_rt::exception; + // The macro for our start-up function use rp_pico::entry; // The macro for marking our interrupt functions use rp_pico::hal::pac::interrupt; -// GPIO traits -use embedded_hal::digital::v2::OutputPin; - // Ensure we halt the program on panic (if we don't mention this crate it won't // be linked) use panic_halt as _; -// Pull in any important traits -use rp_pico::hal::prelude::*; - // A shorter alias for the Peripheral Access Crate, which provides low-level // register access use rp_pico::hal::pac; @@ -42,14 +51,28 @@ use usb_device::{class_prelude::*, prelude::*}; // USB Communications Class Device support use usbd_serial::SerialPort; -/// The USB Device Driver (shared with the interrupt). -static mut USB_DEVICE: Option> = None; +struct StaticUsb<'a> { + usb_device: UsbDevice<'a, hal::usb::UsbBus>, + usb_serial: SerialPort<'a, hal::usb::UsbBus>, +} -/// The USB Bus Driver (shared with the interrupt). -static mut USB_BUS: Option> = None; +// shared with the interrupt +static STATIC_USB: Mutex>> = Mutex::new(RefCell::new(None)); -/// The USB Serial Device Driver (shared with the interrupt). -static mut USB_SERIAL: Option> = None; +/// Call the closure within a critical section passing the content of `STATIC_USB`. +/// +/// This function `panic!`s if `STATIC_USB` does not contain `Some` value. +fn do_with_usb(closure: impl FnOnce(&mut StaticUsb) -> T) -> T { + critical_section::with(|cs| { + // Create a mutable local binding for the RefMut type wrapping our Option. + let mut usb = STATIC_USB.borrow_ref_mut(cs); + // Borrow the content of that binding. + let usb = usb + .as_mut() + .expect("Usb must be setup before calling this function."); + closure(usb) + }) +} /// Entry point to our bare-metal application. /// @@ -60,9 +83,12 @@ static mut USB_SERIAL: Option> = None; /// infinite loop. #[entry] fn main() -> ! { + // The USB Bus Driver (shared with the interrupt). + static mut USB_BUS: Option> = None; + // Grab our singleton objects let mut pac = pac::Peripherals::take().unwrap(); - let core = pac::CorePeripherals::take().unwrap(); + let mut core = pac::CorePeripherals::take().unwrap(); // Set up the watchdog driver - needed by the clock setup code let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); @@ -82,75 +108,82 @@ fn main() -> ! { .ok() .unwrap(); + // The delay object lets us wait for specified amounts of time (in milliseconds) + let mut delay = hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); + // Set up the USB driver - let usb_bus = UsbBusAllocator::new(hal::usb::UsbBus::new( + *USB_BUS = Some(UsbBusAllocator::new(hal::usb::UsbBus::new( pac.USBCTRL_REGS, pac.USBCTRL_DPRAM, clocks.usb_clock, true, &mut pac.RESETS, - )); - unsafe { - // Note (safety): This is safe as interrupts haven't been started yet - USB_BUS = Some(usb_bus); - } + ))); // Grab a reference to the USB Bus allocator. We are promising to the // compiler not to take mutable access to this global variable whilst this // reference exists! - let bus_ref = unsafe { USB_BUS.as_ref().unwrap() }; + let bus_ref = USB_BUS.as_mut().unwrap(); // Set up the USB Communications Class Device driver - let serial = SerialPort::new(bus_ref); - unsafe { - USB_SERIAL = Some(serial); - } - + let usb_serial = SerialPort::new(bus_ref); // Create a USB device with a fake VID and PID - let usb_dev = UsbDeviceBuilder::new(bus_ref, UsbVidPid(0x16c0, 0x27dd)) + let usb_device = UsbDeviceBuilder::new(bus_ref, UsbVidPid(0x16c0, 0x27dd)) .manufacturer("Fake company") .product("Serial port") .serial_number("TEST") .device_class(2) // from: https://www.usb.org/defined-class-codes .build(); - unsafe { - // Note (safety): This is safe as interrupts haven't been started yet - USB_DEVICE = Some(usb_dev); - } + + // Setup the shared usb items in their global storage. + critical_section::with(|cs| { + STATIC_USB.replace( + cs, + Some(StaticUsb { + usb_device, + usb_serial, + }), + ); + }); + + // How many system clock ticks are there in a 100th of a second (10ms)? + let ticks = pac::SYST::get_ticks_per_10ms(); + + // Setup SysTick for a 10ms periodic interrupt. + core.SYST.set_reload(ticks); + core.SYST.enable_counter(); + core.SYST.enable_interrupt(); // Enable the USB interrupt unsafe { pac::NVIC::unmask(hal::pac::Interrupt::USBCTRL_IRQ); }; - // No more USB code after this point in main! We can do anything we want in - // here since USB is handled in the interrupt - let's blink an LED! - - // The delay object lets us wait for specified amounts of time (in - // milliseconds) - let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); - - // The single-cycle I/O block controls our GPIO pins - let sio = hal::Sio::new(pac.SIO); + // wait for the usb device to be configured (aka enumerated on a host). + while do_with_usb(|u| u.usb_device.state()) != UsbDeviceState::Configured { + delay.delay_ms(1); + } - // Set the pins up according to their function on this particular board - let pins = rp_pico::Pins::new( - pac.IO_BANK0, - pac.PADS_BANK0, - sio.gpio_bank0, - &mut pac.RESETS, - ); + // Print a loop count every 2 seconds up to 10 times, then reset to usb boot. + for i in 0..10 { + delay.delay_ms(2_000); - // Set the LED to be an output - let mut led_pin = pins.led.into_push_pull_output(); + let mut text = heapless::String::<20>::new(); + writeln!(&mut text, "loop number: {}", i).unwrap(); - // Blink the LED at 1 Hz - loop { - led_pin.set_high().unwrap(); - delay.delay_ms(500); - led_pin.set_low().unwrap(); - delay.delay_ms(500); + write_serial(text.as_bytes()); } + delay.delay_ms(2_000); + hal::rom_data::reset_to_usb_boot(0, 0); + unreachable!(); +} + +/// Writes to the serial port. +/// +/// We do this with in a system wide critical-section to avoid a race hazard with the USB IRQ and +/// the other core (although this example does not use it). +fn write_serial(byte_array: &[u8]) { + let _ = do_with_usb(|u| u.usb_serial.write(byte_array)); } /// This function is called whenever the USB Hardware generates an Interrupt @@ -160,48 +193,42 @@ fn main() -> ! { /// knowing nothing about USB. #[allow(non_snake_case)] #[interrupt] -unsafe fn USBCTRL_IRQ() { - use core::sync::atomic::{AtomicBool, Ordering}; - - /// Note whether we've already printed the "hello" message. - static SAID_HELLO: AtomicBool = AtomicBool::new(false); - +fn USBCTRL_IRQ() { // Grab the global objects. This is OK as we only access them under interrupt. - let usb_dev = USB_DEVICE.as_mut().unwrap(); - let serial = USB_SERIAL.as_mut().unwrap(); - - // Say hello exactly once on start-up - if !SAID_HELLO.load(Ordering::Relaxed) { - SAID_HELLO.store(true, Ordering::Relaxed); - let _ = serial.write(b"Hello, World!\r\n"); - } - - // Poll the USB driver with all of our supported USB Classes - if usb_dev.poll(&mut [serial]) { - let mut buf = [0u8; 64]; - match serial.read(&mut buf) { - Err(_e) => { - // Do nothing - } - Ok(0) => { - // Do nothing - } - Ok(count) => { - // Convert to upper case - buf.iter_mut().take(count).for_each(|b| { - b.make_ascii_uppercase(); - }); - - // Send back to the host - let mut wr_ptr = &buf[..count]; - while !wr_ptr.is_empty() { - let _ = serial.write(wr_ptr).map(|len| { - wr_ptr = &wr_ptr[len..]; + do_with_usb(|usb| { + // Poll the USB driver with all of our supported USB Classes + if usb.usb_device.poll(&mut [&mut usb.usb_serial]) { + let mut buf = [0u8; 64]; + match usb.usb_serial.read(&mut buf) { + Err(_e) => { + // Do nothing + } + Ok(0) => { + // Do nothing + } + Ok(count) => { + // Convert to upper case + buf.iter_mut().take(count).for_each(|b| { + b.make_ascii_uppercase(); }); + + // Send back to the host + let mut wr_ptr = &buf[..count]; + while !wr_ptr.is_empty() { + let _ = usb.usb_serial.write(wr_ptr).map(|len| { + wr_ptr = &wr_ptr[len..]; + }); + } } } } - } + }); +} + +#[allow(non_snake_case)] +#[exception] +fn SysTick() { + do_with_usb(|usb| usb.usb_device.poll(&mut [&mut usb.usb_serial])); } // End of file From 975da354bbffcf458670a57f7e87ea446055ce4e Mon Sep 17 00:00:00 2001 From: Wilfried Chauveau Date: Sat, 11 Nov 2023 19:05:34 +0000 Subject: [PATCH 2/3] Fix documentation inconsistencies Thanks @Agent59. --- .../examples/pico_usb_serial_interrupt.rs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/boards/rp-pico/examples/pico_usb_serial_interrupt.rs b/boards/rp-pico/examples/pico_usb_serial_interrupt.rs index 884328e3..ea78218b 100644 --- a/boards/rp-pico/examples/pico_usb_serial_interrupt.rs +++ b/boards/rp-pico/examples/pico_usb_serial_interrupt.rs @@ -18,7 +18,7 @@ use core::cell::RefCell; // Trait required to use `writeln!(…)` use core::fmt::Write; -// A system wide mutex synchrinising IRQ & cores +// A system wide mutex synchronising IRQ & cores use critical_section::Mutex; // Import common embedded_hal traits @@ -79,11 +79,14 @@ fn do_with_usb(closure: impl FnOnce(&mut StaticUsb) -> T) -> T { /// The `#[entry]` macro ensures the Cortex-M start-up code calls this function /// as soon as all global variables are initialised. /// -/// The function configures the RP2040 peripherals, then blinks the LED in an -/// infinite loop. +/// The function +/// 1. configures the RP2040 peripherals, +/// 2. waits for USB enumeration to complete, +/// 3. runs a loop 20 times sending a message over usbd-serial before +/// 4. finally resetting to usbboot in bootrom. #[entry] fn main() -> ! { - // The USB Bus Driver (shared with the interrupt). + // The USB Bus Driver. static mut USB_BUS: Option> = None; // Grab our singleton objects @@ -120,9 +123,7 @@ fn main() -> ! { &mut pac.RESETS, ))); - // Grab a reference to the USB Bus allocator. We are promising to the - // compiler not to take mutable access to this global variable whilst this - // reference exists! + // Grab a reference to the USB Bus allocator. let bus_ref = USB_BUS.as_mut().unwrap(); // Set up the USB Communications Class Device driver @@ -228,6 +229,11 @@ fn USBCTRL_IRQ() { #[allow(non_snake_case)] #[exception] fn SysTick() { + // Keeps the usb_device updated in case there is no activity on the bus triggering a + // USBCTRL_IRQ. + // + // This is required by the usb-specs and recommented by usb-device to be at least every 10ms. + // see: https://docs.rs/usb-device/latest/usb_device/device/struct.UsbDevice.html#method.poll do_with_usb(|usb| usb.usb_device.poll(&mut [&mut usb.usb_serial])); } From 37a124c1eef063e3bf6699eb2a4202f2ef5a0312 Mon Sep 17 00:00:00 2001 From: Wilfried Chauveau Date: Mon, 13 Nov 2023 23:13:46 +0000 Subject: [PATCH 3/3] bump st7789, heapless, embedded-sdmmc, usb-device, usbd-serial & usbd-hid versions --- Cargo.toml | 2 + boards/boardsource-blok/Cargo.toml | 4 +- .../examples/blok_usb_keyboard_input.rs | 4 +- boards/pimoroni-pico-explorer/Cargo.toml | 2 +- boards/pimoroni-pico-explorer/src/lib.rs | 3 +- boards/rp-pico/Cargo.toml | 10 +- boards/rp-pico/examples/pico_spi_sd_card.rs | 125 ++++++------------ boards/rp-pico/examples/pico_usb_serial.rs | 10 +- .../examples/pico_usb_serial_interrupt.rs | 10 +- .../examples/pico_usb_twitchy_mouse.rs | 9 +- boards/vcc-gnd-yd-rp2040/Cargo.toml | 2 +- 11 files changed, 75 insertions(+), 106 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 960a2e83..2f989492 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,5 @@ members = [ "boards/waveshare-rp2040-zero", "boards/waveshare-rp2040-lcd-0-96", ] +[patch.crates-io] +rp2040-hal = { git = "https://github.com/ithinuel/rp-hal", branch = "prepare-for-next-usb-device-release" } diff --git a/boards/boardsource-blok/Cargo.toml b/boards/boardsource-blok/Cargo.toml index 3c9e4024..aaa69416 100644 --- a/boards/boardsource-blok/Cargo.toml +++ b/boards/boardsource-blok/Cargo.toml @@ -23,9 +23,9 @@ embedded-hal = "0.2.7" nb = "1.0" smart-leds = "0.3.0" ws2812-pio = "0.7.0" -usb-device = "0.2.9" -usbd-hid = "0.5.2" critical-section = "1.1.1" +usb-device = "0.3.0" +usbd-hid = "0.7.0" [features] # This is the set of features we enable by default diff --git a/boards/boardsource-blok/examples/blok_usb_keyboard_input.rs b/boards/boardsource-blok/examples/blok_usb_keyboard_input.rs index 724dcd44..05ed689a 100644 --- a/boards/boardsource-blok/examples/blok_usb_keyboard_input.rs +++ b/boards/boardsource-blok/examples/blok_usb_keyboard_input.rs @@ -27,6 +27,7 @@ use boardsource_blok::{ Pins, XOSC_CRYSTAL_FREQ, }; use panic_halt as _; +use usb_device::device::StringDescriptors; use usb_device::{ bus::UsbBusAllocator, device::UsbDevice, device::UsbDeviceBuilder, device::UsbVidPid, }; @@ -84,7 +85,8 @@ fn main() -> ! { } let usb_device = UsbDeviceBuilder::new(bus_ref, UsbVidPid(0x1209, 0x0001)) - .product("keyboard input") + .strings(&[StringDescriptors::default().product("keyboard input")]) + .expect("Failed to configure UsbDevice") .build(); unsafe { USB_DEVICE = Some(usb_device); diff --git a/boards/pimoroni-pico-explorer/Cargo.toml b/boards/pimoroni-pico-explorer/Cargo.toml index 61ea00e5..789794e0 100644 --- a/boards/pimoroni-pico-explorer/Cargo.toml +++ b/boards/pimoroni-pico-explorer/Cargo.toml @@ -18,7 +18,7 @@ embedded-hal = { version = "0.2.7", features = ["unproven"] } fugit = "0.3.7" rp2040-boot2 = { version = "0.3.0", optional = true } rp2040-hal = { version = "0.9.0" } -st7789 = "0.6.1" +st7789 = "0.7.0" [dev-dependencies] arrayvec = { version = "0.7.4", default-features = false } diff --git a/boards/pimoroni-pico-explorer/src/lib.rs b/boards/pimoroni-pico-explorer/src/lib.rs index c93e53ad..96c02137 100644 --- a/boards/pimoroni-pico-explorer/src/lib.rs +++ b/boards/pimoroni-pico-explorer/src/lib.rs @@ -162,6 +162,7 @@ pub type Screen = ST7789< Pin, >, DummyPin, + DummyPin, >; pub struct PicoExplorer { @@ -217,7 +218,7 @@ impl PicoExplorer { let spii_screen = SPIInterface::new(spi_screen, dc, cs); - let mut screen = ST7789::new(spii_screen, DummyPin, 240, 240); + let mut screen = ST7789::new(spii_screen, Some(DummyPin), Some(DummyPin), 240, 240); screen.init(delay).unwrap(); screen diff --git a/boards/rp-pico/Cargo.toml b/boards/rp-pico/Cargo.toml index 0246f9fb..3af0f45d 100644 --- a/boards/rp-pico/Cargo.toml +++ b/boards/rp-pico/Cargo.toml @@ -15,7 +15,7 @@ cortex-m-rt = { version = "0.7", optional = true } fugit = "0.3.7" rp2040-boot2 = { version = "0.3.0", optional = true } rp2040-hal = { version = "0.9.0" } -usb-device= "0.2.9" +usb-device= "0.3.0" [dev-dependencies] cortex-m = "0.7.7" @@ -23,9 +23,9 @@ cortex-m-rtic = "1.1.4" critical-section = "1.1.2" embedded-graphics = "0.7.1" embedded-hal ="0.2.7" -embedded-sdmmc = "0.5.0" +embedded-sdmmc = "0.6.0" hd44780-driver = "0.4.0" -heapless = "0.7.16" +heapless = "0.8.0" i2c-pio = "0.7.0" nb = "1.1" panic-halt= "0.2.0" @@ -34,8 +34,8 @@ pio-proc = "0.2.2" rp2040-hal = { version = "0.9.0", features = [ "defmt" ] } smart-leds = "0.3.0" ssd1306 = "0.7.1" -usbd-hid = "0.5.2" -usbd-serial = "0.1.1" +usbd-hid = "0.7.0" +usbd-serial = "0.2.0" ws2812-pio = "0.7.0" defmt = "0.3.5" diff --git a/boards/rp-pico/examples/pico_spi_sd_card.rs b/boards/rp-pico/examples/pico_spi_sd_card.rs index e38b0f2b..db9683e4 100644 --- a/boards/rp-pico/examples/pico_spi_sd_card.rs +++ b/boards/rp-pico/examples/pico_spi_sd_card.rs @@ -59,8 +59,6 @@ #![no_std] #![no_main] -use core::cell::RefCell; - // The macro for our start-up function use rp_pico::entry; @@ -73,6 +71,8 @@ use defmt_rtt as _; use panic_halt as _; // Pull in any important traits +use embedded_hal::blocking::delay::DelayMs; +use embedded_hal::digital::v2::OutputPin; use rp_pico::hal::prelude::*; // Embed the `Hz` function/trait: @@ -95,17 +95,14 @@ use rp_pico::hal; // Link in the embedded_sdmmc crate. // The `SdMmcSpi` is used for block level access to the card. // And the `VolumeManager` gives access to the FAT filesystem functions. -use embedded_sdmmc::{SdCard, TimeSource, Timestamp, VolumeIdx, VolumeManager}; +use embedded_sdmmc::{SdCard, TimeSource, Timestamp, VolumeIdx}; // Get the file open mode enum: use embedded_sdmmc::filesystem::Mode; -use embedded_hal::blocking::delay::DelayMs; -use embedded_hal::blocking::delay::DelayUs; - /// A dummy timesource, which is mostly important for creating files. #[derive(Default)] -pub struct DummyTimesource(); +pub struct DummyTimesource; impl TimeSource for DummyTimesource { // In theory you could use the RTC of the rp2040 here, if you had @@ -126,14 +123,14 @@ impl TimeSource for DummyTimesource { const BLINK_OK_LONG: [u8; 1] = [8u8]; const BLINK_OK_SHORT_LONG: [u8; 4] = [1u8, 0u8, 6u8, 0u8]; const BLINK_OK_SHORT_SHORT_LONG: [u8; 6] = [1u8, 0u8, 1u8, 0u8, 6u8, 0u8]; -const BLINK_ERR_3_SHORT: [u8; 6] = [1u8, 0u8, 1u8, 0u8, 1u8, 0u8]; -const BLINK_ERR_4_SHORT: [u8; 8] = [1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8]; -const BLINK_ERR_5_SHORT: [u8; 10] = [1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8]; -const BLINK_ERR_6_SHORT: [u8; 12] = [1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8]; +const BLINK_ERR_2_SHORT: [u8; 6] = [1u8, 0u8, 1u8, 0u8, 1u8, 0u8]; +const BLINK_ERR_3_SHORT: [u8; 8] = [1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8]; +const BLINK_ERR_4_SHORT: [u8; 10] = [1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8]; +const BLINK_ERR_5_SHORT: [u8; 12] = [1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8, 1u8, 0u8]; fn blink_signals( - pin: &mut dyn embedded_hal::digital::v2::OutputPin, - delay: &mut dyn DelayMs, + pin: &mut impl OutputPin, + mut delay: impl DelayMs + Copy, sig: &[u8], ) { for bit in sig { @@ -156,8 +153,8 @@ fn blink_signals( } fn blink_signals_loop( - pin: &mut dyn embedded_hal::digital::v2::OutputPin, - delay: &mut dyn DelayMs, + pin: &mut impl OutputPin, + mut delay: impl DelayMs + Copy, sig: &[u8], ) -> ! { loop { @@ -172,7 +169,7 @@ fn main() -> ! { // Grab our singleton objects let mut pac = pac::Peripherals::take().unwrap(); - let core = pac::CorePeripherals::take().unwrap(); + let _core = pac::CorePeripherals::take().unwrap(); // Set up the watchdog driver - needed by the clock setup code let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); @@ -225,61 +222,49 @@ fn main() -> ! { // We need a delay implementation that can be passed to SdCard and still be used // for the blink signals. - let mut delay = &SharedDelay::new(cortex_m::delay::Delay::new( - core.SYST, - clocks.system_clock.freq().to_Hz(), - )); + let mut timer = rp_pico::hal::timer::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); info!("Initialize SPI SD/MMC data structures..."); - let sdcard = SdCard::new(spi, spi_cs, delay); - let mut volume_mgr = VolumeManager::new(sdcard, DummyTimesource::default()); - - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_LONG); + let sdcard = SdCard::new(spi, spi_cs, timer); - info!("Init SD card controller and retrieve card size..."); - match volume_mgr.device().num_bytes() { + info!("OK!\nCard size..."); + match sdcard.num_bytes() { Ok(size) => info!("card size is {} bytes", size), Err(e) => { error!("Error retrieving card size: {}", defmt::Debug2Format(&e)); - blink_signals_loop(&mut led_pin, &mut delay, &BLINK_ERR_3_SHORT); + blink_signals_loop(&mut led_pin, timer, &BLINK_ERR_2_SHORT); } } - - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_LONG); - - // Now that the card is initialized, clock can go faster - volume_mgr - .device() - .spi(|spi| spi.set_baudrate(clocks.peripheral_clock.freq(), 16.MHz())); + blink_signals(&mut led_pin, timer, &BLINK_OK_LONG); info!("Getting Volume 0..."); - let mut volume = match volume_mgr.get_volume(VolumeIdx(0)) { + let mut volume_mgr = embedded_sdmmc::VolumeManager::new(sdcard, DummyTimesource); + let volume = match volume_mgr.open_volume(VolumeIdx(0)) { Ok(v) => v, Err(e) => { error!("Error getting volume 0: {}", defmt::Debug2Format(&e)); - blink_signals_loop(&mut led_pin, &mut delay, &BLINK_ERR_4_SHORT); + blink_signals_loop(&mut led_pin, timer, &BLINK_ERR_3_SHORT); } }; - - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_LONG); + blink_signals(&mut led_pin, timer, &BLINK_OK_LONG); // After we have the volume (partition) of the drive we got to open the // root directory: - let dir = match volume_mgr.open_root_dir(&volume) { + let dir = match volume_mgr.open_root_dir(volume) { Ok(dir) => dir, Err(e) => { error!("Error opening root dir: {}", defmt::Debug2Format(&e)); - blink_signals_loop(&mut led_pin, &mut delay, &BLINK_ERR_5_SHORT); + blink_signals_loop(&mut led_pin, timer, &BLINK_ERR_4_SHORT); } }; info!("Root directory opened!"); - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_LONG); + blink_signals(&mut led_pin, timer, &BLINK_OK_LONG); // This shows how to iterate through the directory and how // to get the file names (and print them in hope they are UTF-8 compatible): volume_mgr - .iterate_dir(&volume, &dir, |ent| { + .iterate_dir(dir, |ent| { info!( "/{}.{}", core::str::from_utf8(ent.name.base_name()).unwrap(), @@ -288,15 +273,15 @@ fn main() -> ! { }) .unwrap(); - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_LONG); + blink_signals(&mut led_pin, timer, &BLINK_OK_LONG); let mut successful_read = false; // Next we going to read a file from the SD card: - if let Ok(mut file) = volume_mgr.open_file_in_dir(&mut volume, &dir, "O.TST", Mode::ReadOnly) { + if let Ok(file) = volume_mgr.open_file_in_dir(dir, "O.TST", Mode::ReadOnly) { let mut buf = [0u8; 32]; - let read_count = volume_mgr.read(&volume, &mut file, &mut buf).unwrap(); - volume_mgr.close_file(&volume, file).unwrap(); + let read_count = volume_mgr.read(file, &mut buf).unwrap(); + volume_mgr.close_file(file).unwrap(); if read_count >= 2 { info!("READ {} bytes: {}", read_count, buf); @@ -310,24 +295,22 @@ fn main() -> ! { } } - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_LONG); + blink_signals(&mut led_pin, timer, &BLINK_OK_LONG); - match volume_mgr.open_file_in_dir(&mut volume, &dir, "O.TST", Mode::ReadWriteCreateOrTruncate) { - Ok(mut file) => { - volume_mgr - .write(&mut volume, &mut file, b"\x42\x1E") - .unwrap(); - volume_mgr.close_file(&volume, file).unwrap(); + match volume_mgr.open_file_in_dir(dir, "O.TST", Mode::ReadWriteCreateOrTruncate) { + Ok(file) => { + volume_mgr.write(file, b"\x42\x1E").unwrap(); + volume_mgr.close_file(file).unwrap(); } Err(e) => { error!("Error opening file 'O.TST': {}", defmt::Debug2Format(&e)); - blink_signals_loop(&mut led_pin, &mut delay, &BLINK_ERR_6_SHORT); + blink_signals_loop(&mut led_pin, timer, &BLINK_ERR_5_SHORT); } } volume_mgr.free(); - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_LONG); + blink_signals(&mut led_pin, timer, &BLINK_OK_LONG); if successful_read { info!("Successfully read previously written file 'O.TST'"); @@ -338,37 +321,11 @@ fn main() -> ! { loop { if successful_read { - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_SHORT_SHORT_LONG); + blink_signals(&mut led_pin, timer, &BLINK_OK_SHORT_SHORT_LONG); } else { - blink_signals(&mut led_pin, &mut delay, &BLINK_OK_SHORT_LONG); - } - - delay.delay_ms(1000); - } -} - -// Can be removed once we have https://github.com/rp-rs/rp-hal/pull/614, -// ie. when we move to rp2040-hal 0.9 -struct SharedDelay { - inner: RefCell, -} - -impl SharedDelay { - fn new(delay: cortex_m::delay::Delay) -> Self { - Self { - inner: delay.into(), + blink_signals(&mut led_pin, timer, &BLINK_OK_SHORT_LONG); } - } -} - -impl DelayMs for &SharedDelay { - fn delay_ms(&mut self, ms: u32) { - self.inner.borrow_mut().delay_ms(ms); - } -} -impl DelayUs for &SharedDelay { - fn delay_us(&mut self, us: u8) { - self.inner.borrow_mut().delay_us(us as u32); + timer.delay_ms(1000); } } diff --git a/boards/rp-pico/examples/pico_usb_serial.rs b/boards/rp-pico/examples/pico_usb_serial.rs index 29ccb222..440d6e7f 100644 --- a/boards/rp-pico/examples/pico_usb_serial.rs +++ b/boards/rp-pico/examples/pico_usb_serial.rs @@ -28,7 +28,7 @@ use rp_pico::hal::pac; use rp_pico::hal; // USB Device support -use usb_device::{class_prelude::*, prelude::*}; +use usb_device::{class_prelude::*, device::StringDescriptors, prelude::*}; // USB Communications Class Device support use usbd_serial::SerialPort; @@ -94,9 +94,11 @@ fn main() -> ! { // Create a USB device with a fake VID and PID let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) - .manufacturer("Fake company") - .product("Serial port") - .serial_number("TEST") + .strings(&[StringDescriptors::default() + .manufacturer("Fake company") + .product("Serial port") + .serial_number("TEST")]) + .expect("Failed to configure UsbDevice") .device_class(2) // from: https://www.usb.org/defined-class-codes .build(); diff --git a/boards/rp-pico/examples/pico_usb_serial_interrupt.rs b/boards/rp-pico/examples/pico_usb_serial_interrupt.rs index ea78218b..cd8aa917 100644 --- a/boards/rp-pico/examples/pico_usb_serial_interrupt.rs +++ b/boards/rp-pico/examples/pico_usb_serial_interrupt.rs @@ -46,7 +46,7 @@ use rp_pico::hal::pac; use rp_pico::hal; // USB Device support -use usb_device::{class_prelude::*, prelude::*}; +use usb_device::{class_prelude::*, device::StringDescriptors, prelude::*}; // USB Communications Class Device support use usbd_serial::SerialPort; @@ -130,9 +130,11 @@ fn main() -> ! { let usb_serial = SerialPort::new(bus_ref); // Create a USB device with a fake VID and PID let usb_device = UsbDeviceBuilder::new(bus_ref, UsbVidPid(0x16c0, 0x27dd)) - .manufacturer("Fake company") - .product("Serial port") - .serial_number("TEST") + .strings(&[StringDescriptors::default() + .manufacturer("Fake company") + .product("Serial port") + .serial_number("TEST")]) + .expect("Failed to configure UsbDevice") .device_class(2) // from: https://www.usb.org/defined-class-codes .build(); diff --git a/boards/rp-pico/examples/pico_usb_twitchy_mouse.rs b/boards/rp-pico/examples/pico_usb_twitchy_mouse.rs index 5779b09a..6926d100 100644 --- a/boards/rp-pico/examples/pico_usb_twitchy_mouse.rs +++ b/boards/rp-pico/examples/pico_usb_twitchy_mouse.rs @@ -35,6 +35,7 @@ use rp_pico::hal::pac; // higher-level drivers. use rp_pico::hal; +use usb_device::device::StringDescriptors; // USB Device support use usb_device::{class_prelude::*, prelude::*}; @@ -120,9 +121,11 @@ fn main() -> ! { // Create a USB device with a fake VID and PID let usb_dev = UsbDeviceBuilder::new(bus_ref, UsbVidPid(0x16c0, 0x27da)) - .manufacturer("Fake company") - .product("Twitchy Mousey") - .serial_number("TEST") + .strings(&[StringDescriptors::default() + .manufacturer("Fake company") + .product("Twitchy Mousey") + .serial_number("TEST")]) + .expect("Failed to configure UsbDevice") .device_class(0) .build(); unsafe { diff --git a/boards/vcc-gnd-yd-rp2040/Cargo.toml b/boards/vcc-gnd-yd-rp2040/Cargo.toml index f76b4a4a..5ac8d128 100644 --- a/boards/vcc-gnd-yd-rp2040/Cargo.toml +++ b/boards/vcc-gnd-yd-rp2040/Cargo.toml @@ -15,7 +15,7 @@ cortex-m-rt = { version = "0.7", optional = true } fugit = "0.3.7" rp2040-boot2 = { version = "0.3.0", optional = true } rp2040-hal = { version = "0.9.0" } -usb-device= "0.2.9" +usb-device= "0.3.0" [dev-dependencies] cortex-m = "0.7.7"