aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Hageman <[email protected]>2024-01-04 07:52:53 -0700
committerDerek Hageman <[email protected]>2024-01-05 07:56:22 -0700
commit801a36c7b4e476388e55c842dec09d7ef2607a5a (patch)
tree49db4bb483ef6b2b846fff1e7adc8835491ec1a8
parent591c40481350d0f493b9a79aaf1abe7558e613ff (diff)
stm32: Add G0 USB RCC
Add configuration for STM32G0 USB clock.
-rw-r--r--embassy-stm32/src/rcc/g0.rs51
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))]
77pub 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
76pub struct Config { 92pub 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
84impl Default for Config { 102impl 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,