diff --git a/Cargo.lock b/Cargo.lock index 55c279490..c25ab9d1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,13 +458,9 @@ dependencies = [ [[package]] name = "menu" -version = "0.3.2" - -[[package]] -name = "menu" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03d7f798bfe97329ad6df937951142eec93886b37d87010502dd25e8cc75fd5" +checksum = "d5208bd660042c7760f40d960ba0b1a9dc7a9c90775bea4c4637c3b666d2b53d" [[package]] name = "miniconf" @@ -635,6 +631,15 @@ dependencies = [ "num_enum_derive 0.5.11", ] +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", +] + [[package]] name = "num_enum" version = "0.7.1" @@ -655,6 +660,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "num_enum_derive" version = "0.7.1" @@ -672,6 +688,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "portable-atomic" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" + [[package]] name = "postcard" version = "1.0.8" @@ -871,10 +893,10 @@ name = "serial-settings" version = "0.1.0" dependencies = [ "cortex-m 0.7.7", - "embedded-io 0.5.0", + "embedded-io 0.6.1", "embedded-storage", "heapless 0.8.0", - "menu 0.3.2", + "menu", "miniconf", "postcard", "serde", @@ -979,7 +1001,6 @@ dependencies = [ "lm75", "log", "mcp230xx", - "menu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "miniconf", "minimq", "mono-clock", @@ -1067,8 +1088,7 @@ dependencies = [ [[package]] name = "synopsys-usb-otg" version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678f3707a7b1fd4863023292c42f73c6bab0e9b0096f41ae612d1af0ff221b45" +source = "git+https://github.com/quartiq/synopsys-usb-otg?branch=feature/usb-device-bump#06bd4b0827f4ae7907ce3a2f9db1444c4ad10d1c" dependencies = [ "cortex-m 0.7.7", "embedded-hal", @@ -1107,18 +1127,23 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "usb-device" -version = "0.2.9" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f6cc3adc849b5292b4075fc0d5fdcf2f24866e88e336dd27a8943090a520508" +checksum = "e73e438f527e567fb3982f2370967821fab4f5aea84c42e218a211dd2002b6a2" +dependencies = [ + "heapless 0.7.16", + "num_enum 0.6.1", + "portable-atomic", +] [[package]] name = "usbd-serial" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db75519b86287f12dcf0d171c7cf4ecc839149fe9f3b720ac4cfce52959e1dfe" +version = "0.2.0" +source = "git+https://github.com/rust-embedded-community/usbd-serial?branch=feature/embedded-io#1b2d0fc7049640761f55a71b765e63a835637151" dependencies = [ "embedded-hal", - "nb 0.1.3", + "embedded-io 0.6.1", + "nb 1.1.0", "usb-device", ] diff --git a/Cargo.toml b/Cargo.toml index 8d585ebb9..ac3b333d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,6 @@ members = ["ad9959", "serial-settings"] [dependencies] embedded-io = "0.5" embedded-storage = "0.3" -menu = "0.3" cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = { version = "0.7", features = ["device"] } log = { version = "0.4", features = ["max_level_trace", "release_max_level_info"] } @@ -65,8 +64,8 @@ rand_xorshift = "0.3.0" rand_core = "0.6.4" minimq = "0.8.0" # patch with https://github.com/rust-embedded-community/usb-device/pull/129 -usb-device = "0.2.9" -usbd-serial = "0.1.1" +usb-device = "0.3.0" +usbd-serial = "0.2" # Keep this synced with the miniconf version in py/setup.py miniconf = "0.9.0" smoltcp-nal = { version = "0.4.1", features = ["shared-stack"]} @@ -77,6 +76,14 @@ postcard = "1" version = "0.15.1" features = ["stm32h743v", "rt", "ethernet", "xspi", "usb_hs"] +[patch.crates-io.usbd-serial] +git = "https://github.com/rust-embedded-community/usbd-serial" +branch = "feature/embedded-io" + +[patch.crates-io.synopsys-usb-otg] +git = "https://github.com/quartiq/synopsys-usb-otg" +branch = "feature/usb-device-bump" + [features] nightly = [ ] pounder_v1_0 = [ ] diff --git a/serial-settings/Cargo.toml b/serial-settings/Cargo.toml index 30512c5fb..b54779678 100644 --- a/serial-settings/Cargo.toml +++ b/serial-settings/Cargo.toml @@ -8,9 +8,9 @@ edition = "2021" [dependencies] embedded-storage = "0.3" miniconf = "0.9" -menu = {path = "../../../rust-embedded-community/menu"} +menu = "0.4" cortex-m = "0.7" heapless = "0.8" postcard = "1" -embedded-io = "0.5" -serde = {version = "1", default-features=false} +embedded-io = "0.6" +serde = { version = "1", default-features=false } diff --git a/serial-settings/src/lib.rs b/serial-settings/src/lib.rs index ef3ce5d93..09e18843a 100644 --- a/serial-settings/src/lib.rs +++ b/serial-settings/src/lib.rs @@ -1,4 +1,4 @@ -#![no_std] +#![cfg_attr(not(test), no_std)] use core::fmt::Write; use embedded_storage::nor_flash::NorFlash; @@ -16,7 +16,18 @@ pub trait Settings: } pub trait Interface: - embedded_io::Read + embedded_io::ReadReady + embedded_io::Write + embedded_io::Read + + embedded_io::ReadReady + + embedded_io::Write + + embedded_io::WriteReady +{ +} + +impl Interface for T where + T: embedded_io::Read + + embedded_io::ReadReady + + embedded_io::Write + + embedded_io::WriteReady { } @@ -43,7 +54,7 @@ impl<'a, I: Interface, S: Settings, Flash: NorFlash + 'static> Context<'a, I, S, Flash> { fn save(&mut self) -> Result<(), Error> { - let serialized = postcard::to_slice(&self.settings, &mut self.buffer)?; + let serialized = postcard::to_slice(&self.settings, self.buffer)?; self.flash .erase(0, serialized.len() as u32) .map_err(Error::Flash)?; @@ -123,7 +134,9 @@ impl<'a, I: Interface, S: Settings, Flash: NorFlash + 'static> core::fmt::Write /// # Note /// The terminal uses an internal buffer. Overflows of the output buffer are silently ignored. fn write_str(&mut self, s: &str) -> core::fmt::Result { - self.interface.write_all(s.as_bytes()).ok(); + if let Ok(true) = self.interface.write_ready() { + self.interface.write_all(s.as_bytes()).ok(); + } Ok(()) } } diff --git a/src/bin/dual-iir.rs b/src/bin/dual-iir.rs index 77238d6e9..8b3418f64 100644 --- a/src/bin/dual-iir.rs +++ b/src/bin/dual-iir.rs @@ -46,6 +46,7 @@ use stabilizer::{ hal, signal_generator::{self, SignalGenerator}, timers::SamplingTimer, + usb::UsbDevice, DigitalInput0, DigitalInput1, SerialTerminal, SystemTimer, Systick, AFE0, AFE1, }, @@ -183,7 +184,7 @@ mod app { #[shared] struct Shared { - usb_terminal: SerialTerminal, + usb: UsbDevice, network: NetworkUsers, settings: Settings, @@ -193,6 +194,7 @@ mod app { #[local] struct Local { + usb_terminal: SerialTerminal, sampling_timer: SamplingTimer, digital_inputs: (DigitalInput0, DigitalInput1), afes: (AFE0, AFE1), @@ -231,7 +233,7 @@ mod app { let settings = Settings::default(); let shared = Shared { - usb_terminal: stabilizer.usb_serial, + usb: stabilizer.usb_device, network, settings, telemetry: TelemetryBuffer::default(), @@ -250,6 +252,7 @@ mod app { }; let mut local = Local { + usb_terminal: stabilizer.usb_serial, sampling_timer: stabilizer.adc_dac_timer, digital_inputs: stabilizer.digital_inputs, afes: stabilizer.afes, @@ -393,7 +396,7 @@ mod app { ); } - #[idle(shared=[network, usb_terminal])] + #[idle(shared=[network, usb])] fn idle(mut c: idle::Context) -> ! { loop { match c.shared.network.lock(|net| net.update()) { @@ -403,9 +406,7 @@ mod app { NetworkState::Updated => {} NetworkState::NoChange => { // We can't sleep if USB is not in suspend. - if c.shared.usb_terminal.lock(|terminal| { - terminal.interface().usb_is_suspended() - }) { + if c.shared.usb.lock(|usb| usb.usb_is_suspended()) { cortex_m::asm::wfi(); } } @@ -464,12 +465,11 @@ mod app { .unwrap(); } - #[task(priority = 1, shared=[usb_terminal])] + #[task(priority = 1, shared=[usb], local=[usb_terminal])] fn usb(mut c: usb::Context) { // Handle the USB serial terminal. - c.shared.usb_terminal.lock(|usb| { - usb.interface_mut().process(); - usb.process().ok(); + c.shared.usb.lock(|usb| { + usb.process(c.local.usb_terminal); }); // Schedule to run this task every 10 milliseconds. diff --git a/src/bin/lockin.rs b/src/bin/lockin.rs index 19fa2043a..381de9c1f 100644 --- a/src/bin/lockin.rs +++ b/src/bin/lockin.rs @@ -49,6 +49,7 @@ use stabilizer::{ input_stamper::InputStamper, signal_generator, timers::SamplingTimer, + usb::UsbDevice, DigitalInput0, DigitalInput1, SerialTerminal, SystemTimer, Systick, AFE0, AFE1, }, @@ -222,7 +223,7 @@ mod app { #[shared] struct Shared { - usb_terminal: SerialTerminal, + usb: UsbDevice, network: NetworkUsers, settings: Settings, telemetry: TelemetryBuffer, @@ -230,6 +231,7 @@ mod app { #[local] struct Local { + usb_terminal: SerialTerminal, sampling_timer: SamplingTimer, digital_inputs: (DigitalInput0, DigitalInput1), timestamper: InputStamper, @@ -270,7 +272,7 @@ mod app { let shared = Shared { network, - usb_terminal: stabilizer.usb_serial, + usb: stabilizer.usb_device, telemetry: TelemetryBuffer::default(), settings: Settings::default(), }; @@ -285,6 +287,7 @@ mod app { }; let mut local = Local { + usb_terminal: stabilizer.usb_serial, sampling_timer: stabilizer.adc_dac_timer, digital_inputs: stabilizer.digital_inputs, afes: stabilizer.afes, @@ -455,7 +458,7 @@ mod app { }); } - #[idle(shared=[network, usb_terminal])] + #[idle(shared=[network, usb])] fn idle(mut c: idle::Context) -> ! { loop { match c.shared.network.lock(|net| net.update()) { @@ -465,9 +468,7 @@ mod app { NetworkState::Updated => {} NetworkState::NoChange => { // We can't sleep if USB is not in suspend. - if c.shared.usb_terminal.lock(|terminal| { - terminal.interface().usb_is_suspended() - }) { + if c.shared.usb.lock(|usb| usb.usb_is_suspended()) { cortex_m::asm::wfi(); } } @@ -515,12 +516,11 @@ mod app { .unwrap(); } - #[task(priority = 1, shared=[usb_terminal])] + #[task(priority = 1, shared=[usb], local=[usb_terminal])] fn usb(mut c: usb::Context) { // Handle the USB serial terminal. - c.shared.usb_terminal.lock(|usb| { - usb.interface_mut().process(); - usb.process().ok(); + c.shared.usb.lock(|usb| { + usb.process(c.local.usb_terminal); }); // Schedule to run this task every 10 milliseconds. diff --git a/src/hardware/mod.rs b/src/hardware/mod.rs index 24b354dc6..c7aa1c106 100644 --- a/src/hardware/mod.rs +++ b/src/hardware/mod.rs @@ -12,11 +12,11 @@ pub mod design_parameters; pub mod flash; pub mod input_stamper; pub mod pounder; -pub mod serial_terminal; pub mod setup; pub mod shared_adc; pub mod signal_generator; pub mod timers; +pub mod usb; mod eeprom; @@ -83,7 +83,7 @@ pub type I2c1Proxy = pub type SerialTerminal = serial_settings::SerialSettings< 'static, - serial_terminal::SerialInterface, + usbd_serial::SerialPort<'static, UsbBus>, flash::Settings, flash::Flash, >; diff --git a/src/hardware/serial_terminal.rs b/src/hardware/serial_terminal.rs deleted file mode 100644 index dcb093b89..000000000 --- a/src/hardware/serial_terminal.rs +++ /dev/null @@ -1,69 +0,0 @@ -use super::UsbBus; - -pub struct SerialInterface { - usb_device: usb_device::device::UsbDevice<'static, UsbBus>, - usb_serial: usbd_serial::SerialPort<'static, UsbBus>, -} - -#[derive(Debug)] -pub struct Error(usbd_serial::UsbError); - -impl From for Error { - fn from(e: usbd_serial::UsbError) -> Self { - Self(e) - } -} - -impl embedded_io::Error for Error { - fn kind(&self) -> embedded_io::ErrorKind { - embedded_io::ErrorKind::Other - } -} - -impl embedded_io::ErrorType for SerialInterface { - type Error = Error; -} - -impl embedded_io::Read for SerialInterface { - fn read(&mut self, buf: &mut [u8]) -> Result { - self.usb_serial.read(buf).map_err(From::from) - } -} - -impl embedded_io::ReadReady for SerialInterface { - fn read_ready(&mut self) -> Result { - Ok(true) - } -} - -impl embedded_io::Write for SerialInterface { - fn write(&mut self, buf: &[u8]) -> Result { - self.usb_serial.write(buf).map_err(From::from) - } - - fn flush(&mut self) -> Result<(), Self::Error> { - unimplemented!() - } -} - -impl serial_settings::Interface for SerialInterface {} - -impl SerialInterface { - pub fn new( - usb_device: usb_device::device::UsbDevice<'static, UsbBus>, - usb_serial: usbd_serial::SerialPort<'static, UsbBus>, - ) -> Self { - Self { - usb_device, - usb_serial, - } - } - - pub fn usb_is_suspended(&self) -> bool { - self.usb_device.state() == usb_device::device::UsbDeviceState::Suspend - } - - pub fn process(&mut self) { - self.usb_device.poll(&mut [&mut self.usb_serial]); - } -} diff --git a/src/hardware/setup.rs b/src/hardware/setup.rs index b3b4f34fd..53dfa7616 100644 --- a/src/hardware/setup.rs +++ b/src/hardware/setup.rs @@ -15,10 +15,10 @@ use smoltcp_nal::smoltcp; use super::{ adc, afe, cpu_temp_sensor::CpuTempSensor, dac, delay, design_parameters, eeprom, input_stamper::InputStamper, pounder, - pounder::dds_output::DdsOutput, serial_terminal::SerialInterface, - shared_adc::SharedAdc, timers, DigitalInput0, DigitalInput1, - EemDigitalInput0, EemDigitalInput1, EemDigitalOutput0, EemDigitalOutput1, - EthernetPhy, NetworkStack, SystemTimer, Systick, UsbBus, AFE0, AFE1, + pounder::dds_output::DdsOutput, shared_adc::SharedAdc, timers, + usb::UsbDevice, DigitalInput0, DigitalInput1, EemDigitalInput0, + EemDigitalInput1, EemDigitalOutput0, EemDigitalOutput1, EthernetPhy, + NetworkStack, SerialTerminal, SystemTimer, Systick, UsbBus, AFE0, AFE1, }; const NUM_TCP_SOCKETS: usize = 4; @@ -117,7 +117,8 @@ pub struct StabilizerDevices { pub net: NetworkDevices, pub digital_inputs: (DigitalInput0, DigitalInput1), pub eem_gpio: EemGpioDevices, - pub usb_serial: super::SerialTerminal, + pub usb_serial: SerialTerminal, + pub usb_device: UsbDevice, } /// The available Pounder-specific hardware interfaces. @@ -1061,13 +1062,15 @@ pub fn setup( usb_bus.as_ref().unwrap(), usb_device::device::UsbVidPid(0x1209, 0x392F), ) - .manufacturer("ARTIQ/Sinara") - .product("Stabilizer") - .serial_number(serial_number.as_ref().unwrap()) + .strings(&[usb_device::device::StringDescriptors::default() + .manufacturer("ARTIQ/Sinara") + .product("Stabilizer") + .serial_number(serial_number.as_ref().unwrap())]) + .unwrap() .device_class(usbd_serial::USB_CLASS_CDC) .build(); - (usb_device, serial) + (UsbDevice::new(usb_device), serial) }; let usb_serial = { @@ -1078,8 +1081,6 @@ pub fn setup( let serialize_buffer = cortex_m::singleton!(: [u8; 512] = [0u8; 512]).unwrap(); - let usb_interface = SerialInterface::new(usb_device, usb_serial); - let settings_callback = |maybe_settings: Option| { match maybe_settings { @@ -1094,7 +1095,7 @@ pub fn setup( }; serial_settings::SerialSettings::new( - usb_interface, + usb_serial, super::flash::Flash(flash_bank2.unwrap()), settings_callback, input_buffer, @@ -1117,6 +1118,7 @@ pub fn setup( timestamp_timer, digital_inputs, eem_gpio, + usb_device, usb_serial, }; diff --git a/src/hardware/usb.rs b/src/hardware/usb.rs new file mode 100644 index 000000000..030b93cc7 --- /dev/null +++ b/src/hardware/usb.rs @@ -0,0 +1,22 @@ +use super::SerialTerminal; +use super::UsbBus; + +pub struct UsbDevice { + usb_device: usb_device::device::UsbDevice<'static, UsbBus>, +} + +impl UsbDevice { + pub fn new( + usb_device: usb_device::device::UsbDevice<'static, UsbBus>, + ) -> Self { + Self { usb_device } + } + + pub fn usb_is_suspended(&self) -> bool { + self.usb_device.state() == usb_device::device::UsbDeviceState::Suspend + } + + pub fn process(&mut self, terminal: &mut SerialTerminal) { + self.usb_device.poll(&mut [terminal.interface_mut()]); + } +}