From 6d9af8304cf88dbfa3713acfef4d89ba3a95c2d8 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sun, 15 Sep 2024 20:09:42 +0200 Subject: [PATCH] Add USBPHYC clock configuration for H7RS series --- embassy-stm32/Cargo.toml | 6 ++--- embassy-stm32/src/rcc/h.rs | 32 +++++++++++++++++++++++- embassy-stm32/src/usb/mod.rs | 10 ++++++++ embassy-stm32/src/usb/otg.rs | 2 +- embassy-usb-synopsys-otg/src/lib.rs | 29 +++++++++++++-------- examples/stm32h7rs/src/bin/usb_serial.rs | 1 + 6 files changed, 63 insertions(+), 17 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 2f7f373af..575c4f20c 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -72,8 +72,7 @@ rand_core = "0.6.3" sdio-host = "0.5.0" critical-section = "1.1" #stm32-metapac = { version = "15" } -# stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ad00827345b4b758b2453082809d6e3b634b5364" } -stm32-metapac = { path = "../../stm32-data/build/stm32-metapac" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-acaf04256034066bd5b3a8426224ccf3e4cb7d19" } vcell = "0.1.3" nb = "1.0.0" @@ -100,8 +99,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} -# stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ad00827345b4b758b2453082809d6e3b634b5364", default-features = false, features = ["metadata"] } -stm32-metapac = { path = "../../stm32-data/build/stm32-metapac", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-acaf04256034066bd5b3a8426224ccf3e4cb7d19", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 27fc2b8d7..cd1c10407 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs @@ -35,7 +35,10 @@ pub enum VoltageScale { Scale3, } #[cfg(any(stm32h7rs))] -pub use crate::pac::pwr::vals::Vos as VoltageScale; +pub use crate::pac::{ + pwr::vals::Vos as VoltageScale, + rcc::vals::{Usbphycsel, Usbrefcksel}, +}; #[derive(Clone, Copy, Eq, PartialEq)] pub enum HseMode { @@ -557,6 +560,27 @@ pub(crate) unsafe fn init(config: Config) { let rtc = config.ls.init(); + #[cfg(stm32h7rs)] + let usb_refck = match config.mux.usbphycsel { + Usbphycsel::HSE => hse, + Usbphycsel::HSE_DIV_2 => hse.map(|hse_val| hse_val / 2u8), + Usbphycsel::PLL3_Q => pll3.q, + _ => None, + }; + #[cfg(stm32h7rs)] + let usb_refck_sel = match usb_refck { + Some(clk_val) => match clk_val { + Hertz(16_000_000) => Usbrefcksel::MHZ16, + Hertz(19_200_000) => Usbrefcksel::MHZ19_2, + Hertz(20_000_000) => Usbrefcksel::MHZ20, + Hertz(24_000_000) => Usbrefcksel::MHZ24, + Hertz(26_000_000) => Usbrefcksel::MHZ26, + Hertz(32_000_000) => Usbrefcksel::MHZ32, + _ => panic!("cannot select USBPHYC reference clock with source frequency of {} Hz, must be one of 16, 19.2, 20, 24, 26, 32 MHz", clk_val), + }, + None => Usbrefcksel::MHZ24, + }; + #[cfg(stm32h7)] { RCC.d1cfgr().modify(|w| { @@ -593,6 +617,10 @@ pub(crate) unsafe fn init(config: Config) { w.set_ppre4(config.apb4_pre); w.set_ppre5(config.apb5_pre); }); + + RCC.ahbperckselr().modify(|w| { + w.set_usbrefcksel(usb_refck_sel); + }); } #[cfg(stm32h5)] { @@ -698,6 +726,8 @@ pub(crate) unsafe fn init(config: Config) { #[cfg(stm32h7rs)] clk48mohci: None, // TODO #[cfg(stm32h7rs)] + hse_div_2: hse.map(|clk| clk / 2u32), + #[cfg(stm32h7rs)] usb: Some(Hertz(48_000_000)), ); } diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index 7d8c79618..a473285bf 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -13,9 +13,19 @@ fn common_init() { // Check the USB clock is enabled and running at exactly 48 MHz. // frequency() will panic if not enabled let freq = T::frequency(); + + // On the H7RS, the USBPHYC embeds a PLL accepting one of the input frequencies listed below and providing 48MHz to OTG_FS and 60MHz to OTG_HS internally + #[cfg(stm32h7rs)] + if ![16_000_000, 19_200_000, 20_000_000, 24_000_000, 26_000_000, 32_000_000].contains(&freq.0) { + panic!( + "USB clock should be one of 16, 19.2, 20, 24, 26, 32Mhz but is {} Hz. Please double-check your RCC settings.", + freq.0 + ) + } // Check frequency is within the 0.25% tolerance allowed by the spec. // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user // has tight clock restrictions due to something else (like audio). + #[cfg(not(stm32h7rs))] if freq.0.abs_diff(48_000_000) > 120_000 { panic!( "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.", diff --git a/embassy-stm32/src/usb/otg.rs b/embassy-stm32/src/usb/otg.rs index 59b5401cc..00cafe6e4 100644 --- a/embassy-stm32/src/usb/otg.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -554,7 +554,7 @@ fn calculate_trdt(speed: Dspd) -> u8 { match speed { Dspd::HIGH_SPEED => { // From RM0431 (F72xx), RM0090 (F429), RM0390 (F446) - if ahb_freq >= 30_000_000 { + if ahb_freq >= 30_000_000 || cfg!(stm32h7rs) { 0x9 } else { panic!("AHB frequency is too low") diff --git a/embassy-usb-synopsys-otg/src/lib.rs b/embassy-usb-synopsys-otg/src/lib.rs index 3ff965149..f90403936 100644 --- a/embassy-usb-synopsys-otg/src/lib.rs +++ b/embassy-usb-synopsys-otg/src/lib.rs @@ -584,20 +584,27 @@ impl<'d, const MAX_EP_COUNT: usize> Bus<'d, MAX_EP_COUNT> { }); } + /// Applies configuration specific to + /// Core ID 0x0000_5000 pub fn config_v5(&mut self) { let r = self.instance.regs; + let phy_type = self.instance.phy_type; - r.gccfg_v3().modify(|w| { - w.set_vbvaloven(true); - w.set_vbvaloval(true); - w.set_vbden(self.config.vbus_detection); - }); - - // Force B-peripheral session - r.gotgctl().modify(|w| { - w.set_vbvaloen(!self.config.vbus_detection); - w.set_bvaloval(true); - }); + if phy_type == PhyType::InternalHighSpeed { + r.gccfg_v3().modify(|w| { + w.set_vbvaloven(!self.config.vbus_detection); + w.set_vbvaloval(!self.config.vbus_detection); + w.set_vbden(self.config.vbus_detection); + }); + } else { + r.gotgctl().modify(|w| { + w.set_bvaloen(!self.config.vbus_detection); + w.set_bvaloval(!self.config.vbus_detection); + }); + r.gccfg_v3().modify(|w| { + w.set_vbden(self.config.vbus_detection); + }); + } } fn init(&mut self) { diff --git a/examples/stm32h7rs/src/bin/usb_serial.rs b/examples/stm32h7rs/src/bin/usb_serial.rs index 5a234e898..6773f7843 100644 --- a/examples/stm32h7rs/src/bin/usb_serial.rs +++ b/examples/stm32h7rs/src/bin/usb_serial.rs @@ -48,6 +48,7 @@ async fn main(_spawner: Spawner) { config.rcc.apb4_pre = APBPrescaler::DIV2; // 150 MHz config.rcc.apb5_pre = APBPrescaler::DIV2; // 150 MHz config.rcc.voltage_scale = VoltageScale::HIGH; + config.rcc.mux.usbphycsel = mux::Usbphycsel::HSE; } let p = embassy_stm32::init(config);