diff options
| author | Derek Hageman <[email protected]> | 2024-01-04 07:52:53 -0700 |
|---|---|---|
| committer | Derek Hageman <[email protected]> | 2024-01-05 07:56:22 -0700 |
| commit | 801a36c7b4e476388e55c842dec09d7ef2607a5a (patch) | |
| tree | 49db4bb483ef6b2b846fff1e7adc8835491ec1a8 /embassy-stm32 | |
| parent | 591c40481350d0f493b9a79aaf1abe7558e613ff (diff) | |
stm32: Add G0 USB RCC
Add configuration for STM32G0 USB clock.
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/rcc/g0.rs | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index aedc95bf3..b38fe1dcc 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs | |||
| @@ -72,6 +72,22 @@ pub enum PllSource { | |||
| 72 | HSE(Hertz, HseMode), | 72 | HSE(Hertz, HseMode), |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | /// Sets the source for the 48MHz clock to the USB peripheral. | ||
| 76 | #[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))] | ||
| 77 | pub enum UsbSrc { | ||
| 78 | /// Use the High Speed Internal Oscillator. The CRS must be used to calibrate the | ||
| 79 | /// oscillator to comply with the USB specification for oscillator tolerance. | ||
| 80 | #[cfg(any(stm32g0b1, stm32g0c1))] | ||
| 81 | Hsi48(super::Hsi48Config), | ||
| 82 | /// Use the PLLQ output. The PLL must be configured to output a 48MHz clock. The | ||
| 83 | /// PLL needs to be using the HSE source to comply with the USB specification for oscillator | ||
| 84 | /// tolerance. | ||
| 85 | PllQ, | ||
| 86 | /// Use the HSE source directly. The HSE must be a 48MHz source. The HSE source must comply | ||
| 87 | /// with the USB specification for oscillator tolerance. | ||
| 88 | HSE, | ||
| 89 | } | ||
| 90 | |||
| 75 | /// Clocks configutation | 91 | /// Clocks configutation |
| 76 | pub struct Config { | 92 | pub struct Config { |
| 77 | pub mux: ClockSrc, | 93 | pub mux: ClockSrc, |
| @@ -79,6 +95,8 @@ pub struct Config { | |||
| 79 | pub apb_pre: APBPrescaler, | 95 | pub apb_pre: APBPrescaler, |
| 80 | pub low_power_run: bool, | 96 | pub low_power_run: bool, |
| 81 | pub ls: super::LsConfig, | 97 | pub ls: super::LsConfig, |
| 98 | #[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))] | ||
| 99 | pub usb_src: Option<UsbSrc>, | ||
| 82 | } | 100 | } |
| 83 | 101 | ||
| 84 | impl Default for Config { | 102 | impl Default for Config { |
| @@ -90,6 +108,8 @@ impl Default for Config { | |||
| 90 | apb_pre: APBPrescaler::DIV1, | 108 | apb_pre: APBPrescaler::DIV1, |
| 91 | low_power_run: false, | 109 | low_power_run: false, |
| 92 | ls: Default::default(), | 110 | ls: Default::default(), |
| 111 | #[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))] | ||
| 112 | usb_src: None, | ||
| 93 | } | 113 | } |
| 94 | } | 114 | } |
| 95 | } | 115 | } |
| @@ -303,13 +323,42 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 303 | let lsi_freq = (sw == Sw::LSI).then_some(super::LSI_FREQ); | 323 | let lsi_freq = (sw == Sw::LSI).then_some(super::LSI_FREQ); |
| 304 | let hse_freq = (sw == Sw::HSE).then_some(sys_clk); | 324 | let hse_freq = (sw == Sw::HSE).then_some(sys_clk); |
| 305 | 325 | ||
| 326 | #[cfg(any(stm32g0b1, stm32g0c1, stm32g0b0))] | ||
| 327 | let hsi48_freq = config.usb_src.and_then(|config| { | ||
| 328 | match config { | ||
| 329 | UsbSrc::PllQ => { | ||
| 330 | // Make sure the PLLQ is enabled and running at 48Mhz | ||
| 331 | assert!(pll1_q_freq.is_some() && pll1_q_freq.unwrap().0 == 48_000_000); | ||
| 332 | RCC.ccipr2() | ||
| 333 | .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::PLL1_Q)); | ||
| 334 | None | ||
| 335 | } | ||
| 336 | UsbSrc::HSE => { | ||
| 337 | // Make sure the HSE is enabled and running at 48Mhz | ||
| 338 | assert!(hse_freq.is_some() && hse_freq.unwrap().0 == 48_000_000); | ||
| 339 | RCC.ccipr2() | ||
| 340 | .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSE)); | ||
| 341 | None | ||
| 342 | } | ||
| 343 | #[cfg(any(stm32g0b1, stm32g0c1))] | ||
| 344 | UsbSrc::Hsi48(config) => { | ||
| 345 | let freq = super::init_hsi48(config); | ||
| 346 | RCC.ccipr2() | ||
| 347 | .modify(|w| w.set_usbsel(crate::pac::rcc::vals::Usbsel::HSI48)); | ||
| 348 | Some(freq) | ||
| 349 | } | ||
| 350 | } | ||
| 351 | }); | ||
| 352 | #[cfg(not(any(stm32g0b1, stm32g0c1, stm32g0b0)))] | ||
| 353 | let hsi48_freq: Option<Hertz> = None; | ||
| 354 | |||
| 306 | set_freqs(Clocks { | 355 | set_freqs(Clocks { |
| 307 | sys: sys_clk, | 356 | sys: sys_clk, |
| 308 | hclk1: ahb_freq, | 357 | hclk1: ahb_freq, |
| 309 | pclk1: apb_freq, | 358 | pclk1: apb_freq, |
| 310 | pclk1_tim: apb_tim_freq, | 359 | pclk1_tim: apb_tim_freq, |
| 311 | hsi: hsi_freq, | 360 | hsi: hsi_freq, |
| 312 | hsi48: None, | 361 | hsi48: hsi48_freq, |
| 313 | hsi_div_8: hsi_div_8_freq, | 362 | hsi_div_8: hsi_div_8_freq, |
| 314 | hse: hse_freq, | 363 | hse: hse_freq, |
| 315 | lse: lse_freq, | 364 | lse: lse_freq, |
