From 018c48cf1ce54effe73f2287cb78fabbdede215c Mon Sep 17 00:00:00 2001 From: shufps Date: Sun, 14 Jan 2024 22:43:22 +0100 Subject: [PATCH 1/3] changes to get usb working on a L1. Adds a usb_serial example too --- embassy-stm32/src/usb/usb.rs | 6 ++++++ examples/stm32l1/Cargo.toml | 1 + 2 files changed, 7 insertions(+) diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 04b1b35e8..364076739 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -286,7 +286,10 @@ impl<'d, T: Instance> Driver<'d, T> { #[cfg(not(usb_v4))] regs.btable().write(|w| w.set_btable(0)); + #[cfg(not(stm32l1))] dp.set_as_af(dp.af_num(), AFType::OutputPushPull); + + #[cfg(not(stm32l1))] dm.set_as_af(dm.af_num(), AFType::OutputPushPull); // Initialize the bus so that it signals that power is available @@ -444,6 +447,9 @@ impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { #[cfg(any(usb_v3, usb_v4))] regs.bcdr().write(|w| w.set_dppu(true)); + #[cfg(stm32l1)] + crate::pac::SYSCFG.pmc().modify(|w| w.set_usb_pu(true)); + trace!("enabled"); let mut ep_types = [EpType::BULK; EP_COUNT - 1]; diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index c0b35b716..322c41262 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -9,6 +9,7 @@ embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } +embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } defmt = "0.3" defmt-rtt = "0.4" From ec4cffe28c314b8cb69998fe0b5ddafbf4e092e8 Mon Sep 17 00:00:00 2001 From: shufps Date: Sun, 14 Jan 2024 22:46:20 +0100 Subject: [PATCH 2/3] usb-serial with HSI --- examples/stm32l1/src/bin/usb_serial.rs | 103 +++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 examples/stm32l1/src/bin/usb_serial.rs diff --git a/examples/stm32l1/src/bin/usb_serial.rs b/examples/stm32l1/src/bin/usb_serial.rs new file mode 100644 index 000000000..7b1e84cbc --- /dev/null +++ b/examples/stm32l1/src/bin/usb_serial.rs @@ -0,0 +1,103 @@ +#![no_std] +#![no_main] + +use defmt::{panic, *}; +use embassy_executor::Spawner; +use embassy_stm32::usb::{self, Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals}; +use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; +use embassy_usb::driver::EndpointError; +use embassy_usb::Builder; +use futures::future::join; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + USB_LP => usb::InterruptHandler; + +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = embassy_stm32::Config::default(); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = true; + config.rcc.pll = Some(Pll { + source: PllSource::HSI, + mul: PllMul::MUL6, // PLLVCO = 16*6 = 96Mhz + div: PllDiv::DIV3, // 32Mhz clock (16 * 6 / 3) + }); + config.rcc.mux = ClockSrc::PLL1_R; + } + + let p = embassy_stm32::init(config); + + info!("Hello World!"); + + let driver = Driver::new(p.USB, Irqs, p.PA12, p.PA11); + + let mut config = embassy_usb::Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("USB-Serial Example"); + config.serial_number = Some("123456"); + + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + config.composite_with_iads = true; + + let mut device_descriptor = [0; 256]; + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut device_descriptor, + &mut config_descriptor, + &mut bos_descriptor, + &mut [], // no msos descriptors + &mut control_buf, + ); + + let mut class = CdcAcmClass::new(&mut builder, &mut state, 64); + + let mut usb = builder.build(); + + let usb_fut = usb.run(); + + let echo_fut = async { + loop { + class.wait_connection().await; + info!("Connected"); + let _ = echo(&mut class).await; + info!("Disconnected"); + } + }; + + join(usb_fut, echo_fut).await; +} + +struct Disconnected {} + +impl From for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => Disconnected {}, + } + } +} + +async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = class.read_packet(&mut buf).await?; + let data = &buf[..n]; + info!("data: {:x}", data); + class.write_packet(data).await?; + } +} From 583555bc8ae58f615bff000277220d043eeb9827 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 14 Jan 2024 23:20:51 +0100 Subject: [PATCH 3/3] Suppress "unused" warnings. --- embassy-stm32/src/usb/usb.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index 364076739..f39915906 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -13,7 +13,6 @@ use embassy_usb_driver::{ }; use super::{DmPin, DpPin, Instance}; -use crate::gpio::sealed::AFType; use crate::interrupt::typelevel::Interrupt; use crate::pac::usb::regs; use crate::pac::usb::vals::{EpType, Stat}; @@ -287,10 +286,12 @@ impl<'d, T: Instance> Driver<'d, T> { regs.btable().write(|w| w.set_btable(0)); #[cfg(not(stm32l1))] - dp.set_as_af(dp.af_num(), AFType::OutputPushPull); - - #[cfg(not(stm32l1))] - dm.set_as_af(dm.af_num(), AFType::OutputPushPull); + { + dp.set_as_af(dp.af_num(), crate::gpio::sealed::AFType::OutputPushPull); + dm.set_as_af(dm.af_num(), crate::gpio::sealed::AFType::OutputPushPull); + } + #[cfg(stm32l1)] + let _ = (dp, dm); // suppress "unused" warnings. // Initialize the bus so that it signals that power is available BUS_WAKER.wake();