diff options
| author | Gerzain Mata <[email protected]> | 2025-07-24 16:28:59 -0700 |
|---|---|---|
| committer | Gerzain Mata <[email protected]> | 2025-07-24 16:28:59 -0700 |
| commit | a8d215ff1484cde754695b08e91663e2220c9790 (patch) | |
| tree | 5dcb775578a0da34137a7e2fc821c9dd4a0d0a34 | |
| parent | c5565ccc288863b7d7e5a82aa42141eb7a1cff9f (diff) | |
Partially working USB example
| -rw-r--r-- | embassy-stm32/src/rcc/wba.rs | 14 | ||||
| -rw-r--r-- | embassy-stm32/src/usb/otg.rs | 26 | ||||
| -rw-r--r-- | examples/stm32wba/src/bin/usb_hs_serial.rs | 20 |
3 files changed, 37 insertions, 23 deletions
diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs index 4ca622614..a5e6b33ff 100644 --- a/embassy-stm32/src/rcc/wba.rs +++ b/embassy-stm32/src/rcc/wba.rs | |||
| @@ -2,7 +2,7 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; | |||
| 2 | use crate::pac::rcc::regs::Cfgr1; | 2 | use crate::pac::rcc::regs::Cfgr1; |
| 3 | pub use crate::pac::rcc::vals::{ | 3 | pub use crate::pac::rcc::vals::{ |
| 4 | Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, | 4 | Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk, Pllsrc as PllSource, |
| 5 | Plldiv as PllDiv, Pllm, Plln as PllMul, | 5 | Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, |
| 6 | }; | 6 | }; |
| 7 | use crate::pac::rcc::vals::Pllrge; | 7 | use crate::pac::rcc::vals::Pllrge; |
| 8 | use crate::pac::{FLASH, RCC}; | 8 | use crate::pac::{FLASH, RCC}; |
| @@ -32,7 +32,7 @@ pub struct Pll { | |||
| 32 | /// The PLL pre-divider. | 32 | /// The PLL pre-divider. |
| 33 | /// | 33 | /// |
| 34 | /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. | 34 | /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. |
| 35 | pub pllm: Pllm, | 35 | pub prediv: PllPreDiv, |
| 36 | /// The PLL multiplier. | 36 | /// The PLL multiplier. |
| 37 | /// | 37 | /// |
| 38 | /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 | 38 | /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 |
| @@ -287,15 +287,18 @@ fn init_pll(config: Option<Pll>, input: &PllInput, voltage_range: VoltageScale) | |||
| 287 | 287 | ||
| 288 | let Some(pll) = config else { return PllOutput::default() }; | 288 | let Some(pll) = config else { return PllOutput::default() }; |
| 289 | 289 | ||
| 290 | let src_freq = match pll.source { | 290 | let pre_src_freq = match pll.source { |
| 291 | PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), | 291 | PllSource::DISABLE => panic!("must not select PLL source as DISABLE"), |
| 292 | PllSource::HSE => unwrap!(input.hse), | 292 | PllSource::HSE => unwrap!(input.hse), |
| 293 | PllSource::HSI => unwrap!(input.hsi), | 293 | PllSource::HSI => unwrap!(input.hsi), |
| 294 | PllSource::_RESERVED_1 => panic!("must not select RESERVED_1 source as DISABLE"), | 294 | PllSource::_RESERVED_1 => panic!("must not select RESERVED_1 source as DISABLE"), |
| 295 | }; | 295 | }; |
| 296 | 296 | ||
| 297 | let hse_div = RCC.cr().read().hsepre(); | ||
| 298 | let src_freq = pre_src_freq / hse_div; | ||
| 299 | |||
| 297 | // Calculate the reference clock, which is the source divided by m | 300 | // Calculate the reference clock, which is the source divided by m |
| 298 | let ref_freq = src_freq / pll.pllm; | 301 | let ref_freq = src_freq / pll.prediv; |
| 299 | // Check limits per RM0515 § 12.4.3 | 302 | // Check limits per RM0515 § 12.4.3 |
| 300 | assert!(Hertz::mhz(4) <= ref_freq && ref_freq <= Hertz::mhz(16)); | 303 | assert!(Hertz::mhz(4) <= ref_freq && ref_freq <= Hertz::mhz(16)); |
| 301 | 304 | ||
| @@ -325,7 +328,6 @@ fn init_pll(config: Option<Pll>, input: &PllInput, voltage_range: VoltageScale) | |||
| 325 | w.set_pllp(pll.divp.unwrap_or(PllDiv::DIV1)); | 328 | w.set_pllp(pll.divp.unwrap_or(PllDiv::DIV1)); |
| 326 | w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1)); | 329 | w.set_pllq(pll.divq.unwrap_or(PllDiv::DIV1)); |
| 327 | w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1)); | 330 | w.set_pllr(pll.divr.unwrap_or(PllDiv::DIV1)); |
| 328 | // w.set_pllfracn(pll.frac.unwrap_or(1)); | ||
| 329 | }); | 331 | }); |
| 330 | RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(1));}); | 332 | RCC.pll1fracr().write(|w| {w.set_pllfracn(pll.frac.unwrap_or(1));}); |
| 331 | 333 | ||
| @@ -340,7 +342,7 @@ fn init_pll(config: Option<Pll>, input: &PllInput, voltage_range: VoltageScale) | |||
| 340 | $w.set_pllqen(pll.divq.is_some()); | 342 | $w.set_pllqen(pll.divq.is_some()); |
| 341 | $w.set_pllren(pll.divr.is_some()); | 343 | $w.set_pllren(pll.divr.is_some()); |
| 342 | $w.set_pllfracen(pll.frac.is_some()); | 344 | $w.set_pllfracen(pll.frac.is_some()); |
| 343 | $w.set_pllm(pll.pllm); | 345 | $w.set_pllm(pll.prediv); |
| 344 | $w.set_pllsrc(pll.source); | 346 | $w.set_pllsrc(pll.source); |
| 345 | $w.set_pllrge(input_range); | 347 | $w.set_pllrge(input_range); |
| 346 | }; | 348 | }; |
diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 02b27ed48..6b28ac980 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs | |||
| @@ -315,30 +315,42 @@ impl<'d, T: Instance> Bus<'d, T> { | |||
| 315 | 315 | ||
| 316 | #[cfg(all(stm32u5, peri_usb_otg_hs))] | 316 | #[cfg(all(stm32u5, peri_usb_otg_hs))] |
| 317 | { | 317 | { |
| 318 | crate::pac::SYSCFG.otghsphycr().modify(|w| { | ||
| 319 | w.set_en(true); | ||
| 320 | }); | ||
| 321 | |||
| 322 | critical_section::with(|_| { | 318 | critical_section::with(|_| { |
| 323 | crate::pac::RCC.ahb2enr1().modify(|w| { | 319 | crate::pac::RCC.ahb2enr1().modify(|w| { |
| 324 | w.set_usb_otg_hsen(true); | 320 | w.set_usb_otg_hsen(true); |
| 325 | w.set_usb_otg_hs_phyen(true); | 321 | w.set_usb_otg_hs_phyen(true); |
| 326 | }); | 322 | }); |
| 327 | }); | 323 | }); |
| 328 | } | ||
| 329 | 324 | ||
| 330 | #[cfg(all(stm32wba, peri_usb_otg_hs))] | ||
| 331 | { | ||
| 332 | crate::pac::SYSCFG.otghsphycr().modify(|w| { | 325 | crate::pac::SYSCFG.otghsphycr().modify(|w| { |
| 333 | w.set_en(true); | 326 | w.set_en(true); |
| 334 | }); | 327 | }); |
| 328 | } | ||
| 335 | 329 | ||
| 330 | #[cfg(all(stm32wba, peri_usb_otg_hs))] | ||
| 331 | { | ||
| 336 | critical_section::with(|_| { | 332 | critical_section::with(|_| { |
| 333 | crate::pac::RCC.apb7enr().modify(|w| { | ||
| 334 | w.set_syscfgen(true); | ||
| 335 | }); | ||
| 337 | crate::pac::RCC.ahb2enr().modify(|w| { | 336 | crate::pac::RCC.ahb2enr().modify(|w| { |
| 338 | w.set_usb_otg_hsen(true); | 337 | w.set_usb_otg_hsen(true); |
| 339 | w.set_usb_otg_hs_phyen(true); | 338 | w.set_usb_otg_hs_phyen(true); |
| 340 | }); | 339 | }); |
| 341 | }); | 340 | }); |
| 341 | |||
| 342 | // pub use crate::pac::rcc::vals::Otghssel; | ||
| 343 | // // select HSE | ||
| 344 | // crate::pac::RCC.ccipr2().modify(|w| {w.set_otghssel(Otghssel::HSE);}); | ||
| 345 | |||
| 346 | crate::pac::SYSCFG.otghsphytuner2().modify(|w| { | ||
| 347 | w.set_compdistune(0b010); | ||
| 348 | w.set_sqrxtune(0b000); | ||
| 349 | }); | ||
| 350 | |||
| 351 | crate::pac::SYSCFG.otghsphycr().modify(|w| { | ||
| 352 | w.set_en(true); | ||
| 353 | }); | ||
| 342 | } | 354 | } |
| 343 | 355 | ||
| 344 | let r = T::regs(); | 356 | let r = T::regs(); |
diff --git a/examples/stm32wba/src/bin/usb_hs_serial.rs b/examples/stm32wba/src/bin/usb_hs_serial.rs index e30f33625..bda4a5013 100644 --- a/examples/stm32wba/src/bin/usb_hs_serial.rs +++ b/examples/stm32wba/src/bin/usb_hs_serial.rs | |||
| @@ -5,7 +5,7 @@ use defmt::{panic, *}; | |||
| 5 | use defmt_rtt as _; // global logger | 5 | use defmt_rtt as _; // global logger |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 8 | use embassy_stm32::rcc::PllSource; | 8 | use embassy_stm32::rcc::{PllSource, PllPreDiv, PllMul, PllDiv}; |
| 9 | use embassy_stm32::rcc::{mux, AHBPrescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; | 9 | use embassy_stm32::rcc::{mux, AHBPrescaler, APBPrescaler, Hse, HsePrescaler, Sysclk, VoltageScale}; |
| 10 | use embassy_stm32::usb::{Driver, Instance}; | 10 | use embassy_stm32::usb::{Driver, Instance}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; | 11 | use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; |
| @@ -26,21 +26,18 @@ async fn main(_spawner: Spawner) { | |||
| 26 | 26 | ||
| 27 | // External HSE (32 MHz) setup | 27 | // External HSE (32 MHz) setup |
| 28 | config.rcc.hse = Some(Hse { | 28 | config.rcc.hse = Some(Hse { |
| 29 | prescaler: HsePrescaler::DIV1, | 29 | prescaler: HsePrescaler::DIV2, |
| 30 | }); | 30 | }); |
| 31 | 31 | ||
| 32 | // route HSE into the USB‐OTG‐HS block | ||
| 33 | config.rcc.mux.otghssel = mux::Otghssel::HSE; | ||
| 34 | config.rcc.sys = Sysclk::HSE; | ||
| 35 | 32 | ||
| 36 | // Fine-tune PLL1 dividers/multipliers | 33 | // Fine-tune PLL1 dividers/multipliers |
| 37 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | 34 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { |
| 38 | source: PllSource::HSE, | 35 | source: PllSource::HSE, |
| 39 | pllm: 2.into(), // PLLM = 2 → HSE / 2 = 16 MHz input | 36 | prediv: PllPreDiv::DIV2, // PLLM = 2 → HSE / 2 = 8 MHz |
| 40 | mul: 12.into(), // PLLN = 12 → 16 MHz * 12 = 192 MHz VCO | 37 | mul: PllMul::MUL60, // PLLN = 60 → 8 MHz * 60 = 480 MHz VCO |
| 41 | divp: Some(2.into()), // PLLP = 2 → 96 MHz | 38 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) |
| 42 | divq: Some(2.into()), // PLLQ = 2 → 96 MHz | 39 | divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (USB) |
| 43 | divr: Some(2.into()), // PLLR = 2 → 96 MHz | 40 | divp: Some(PllDiv::DIV15), // PLLP = 15 → 32 MHz (USBOTG) |
| 44 | frac: Some(4096), // Fractional part (enabled) | 41 | frac: Some(4096), // Fractional part (enabled) |
| 45 | }); | 42 | }); |
| 46 | 43 | ||
| @@ -51,6 +48,9 @@ async fn main(_spawner: Spawner) { | |||
| 51 | 48 | ||
| 52 | // voltage scale for max performance | 49 | // voltage scale for max performance |
| 53 | config.rcc.voltage_scale = VoltageScale::RANGE1; | 50 | config.rcc.voltage_scale = VoltageScale::RANGE1; |
| 51 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 52 | config.rcc.mux.otghssel = mux::Otghssel::PLL1_P; | ||
| 53 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 54 | 54 | ||
| 55 | let p = embassy_stm32::init(config); | 55 | let p = embassy_stm32::init(config); |
| 56 | 56 | ||
