1use crate::pac::RCC;
2use crate::time::Hertz;
3
4pub trait RccExt {
6 fn configure(self) -> CFGR;
8}
9
10impl RccExt for RCC {
11 fn configure(self) -> CFGR {
12 CFGR {
13 hclk: None,
14 pclk: None,
15 sysclk: None,
16 clock_src: SysClkSource::HSI,
17 #[cfg(any(
19 feature = "stm32f042",
20 feature = "stm32f048",
21 feature = "stm32f071",
22 feature = "stm32f072",
23 feature = "stm32f078",
24 feature = "stm32f091",
25 feature = "stm32f098",
26 ))]
27 crs: None,
28 #[cfg(any(
29 feature = "stm32f042",
30 feature = "stm32f048",
31 feature = "stm32f072",
32 feature = "stm32f078",
33 ))]
34 usb_src: USBClockSource::HSI48,
35 #[cfg(feature = "stm32f070")]
36 usb_src: USBClockSource::Disabled,
37 rcc: self,
38 }
39 }
40}
41
42pub struct Rcc {
44 pub clocks: Clocks,
45 pub(crate) regs: RCC,
46}
47
48pub enum HSEBypassMode {
49 NotBypassed,
51 Bypassed,
53}
54#[cfg(any(
55 feature = "stm32f042",
56 feature = "stm32f048",
57 feature = "stm32f070", feature = "stm32f072",
59 feature = "stm32f078",
60))]
61#[allow(clippy::upper_case_acronyms)]
62pub enum USBClockSource {
63 #[cfg(feature = "stm32f070")]
64 Disabled,
66 #[cfg(not(feature = "stm32f070"))]
67 HSI48,
69 PLL,
71}
72#[cfg(any(feature = "stm32f030", feature = "stm32f070",))]
74mod inner {
75 use crate::pac::{rcc::cfgr::SW_A, RCC};
76
77 pub(super) const HSI: u32 = 8_000_000; #[cfg(any(
81 feature = "stm32f030x4",
82 feature = "stm32f030x6",
83 feature = "stm32f030x8",
84 feature = "stm32f070",
88 feature = "stm32f030xc"
90 ))]
91 pub(super) const RCC_PLLSRC_PREDIV1_SUPPORT: bool = false;
92
93 #[allow(clippy::upper_case_acronyms)]
94 pub(super) enum SysClkSource {
95 HSI,
96 HSE(u32, super::HSEBypassMode),
98 }
99
100 pub(super) fn get_freq(c_src: &SysClkSource) -> u32 {
101 match c_src {
104 SysClkSource::HSE(freq, _) => *freq,
105 _ => HSI,
106 }
107 }
108
109 pub(super) fn enable_clock(rcc: &mut RCC, c_src: &SysClkSource) {
110 match c_src {
112 SysClkSource::HSE(_, bypassed) => {
113 match bypassed {
114 super::HSEBypassMode::NotBypassed => {
115 rcc.cr
116 .modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed());
117 }
118 super::HSEBypassMode::Bypassed => {
119 rcc.cr
120 .modify(|_, w| w.csson().on().hseon().on().hsebyp().bypassed());
121 }
122 }
123 while !rcc.cr.read().hserdy().bit_is_set() {}
124 }
125 SysClkSource::HSI => {
126 rcc.cr.write(|w| w.hsion().set_bit());
127 while rcc.cr.read().hsirdy().bit_is_clear() {}
128 }
129 }
130 }
131
132 pub(super) fn enable_pll(
133 rcc: &mut RCC,
134 c_src: &SysClkSource,
135 pllmul_bits: u8,
136 ppre_bits: u8,
137 hpre_bits: u8,
138 ) {
139 let pllsrc_bit: bool = match c_src {
140 SysClkSource::HSI => false,
141 SysClkSource::HSE(_, _) => true,
142 };
143
144 rcc.cfgr
146 .modify(|_, w| w.pllsrc().bit(pllsrc_bit).pllmul().bits(pllmul_bits));
147
148 rcc.cr.modify(|_, w| w.pllon().set_bit());
149 while rcc.cr.read().pllrdy().bit_is_clear() {}
150
151 rcc.cfgr
152 .modify(|_, w| unsafe { w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll() });
153 }
154
155 pub(super) fn get_sww(c_src: &SysClkSource) -> SW_A {
156 match c_src {
157 SysClkSource::HSI => SW_A::HSI,
158 SysClkSource::HSE(_, _) => SW_A::HSE,
159 }
160 }
161}
162#[cfg(any(
164 feature = "stm32f031",
165 feature = "stm32f038",
166 feature = "stm32f042",
167 feature = "stm32f048",
168 feature = "stm32f051",
169 feature = "stm32f058",
170 feature = "stm32f071",
171 feature = "stm32f072",
172 feature = "stm32f078",
173 feature = "stm32f091",
174 feature = "stm32f098",
175))]
176mod inner {
177 use crate::pac::{rcc::cfgr::SW_A, RCC};
178
179 pub(super) const HSI: u32 = 8_000_000; #[cfg(any(
181 feature = "stm32f042",
182 feature = "stm32f048",
183 feature = "stm32f071",
184 feature = "stm32f072",
185 feature = "stm32f078",
186 feature = "stm32f091",
187 feature = "stm32f098",
188 ))]
189 pub(super) const HSI48: u32 = 48_000_000; #[cfg(any(
193 feature = "stm32f042",
194 feature = "stm32f048",
195 feature = "stm32f071",
196 feature = "stm32f072",
197 feature = "stm32f078",
198 feature = "stm32f091",
199 feature = "stm32f098",
200 ))]
201 pub(super) const RCC_PLLSRC_PREDIV1_SUPPORT: bool = true;
202 #[cfg(any(
203 feature = "stm32f031",
204 feature = "stm32f038",
205 feature = "stm32f051",
206 feature = "stm32f058"
207 ))]
208 pub(super) const RCC_PLLSRC_PREDIV1_SUPPORT: bool = false;
209
210 #[allow(clippy::upper_case_acronyms)]
211 pub(super) enum SysClkSource {
212 HSI,
213 HSE(u32, super::HSEBypassMode),
215 #[cfg(any(
216 feature = "stm32f042",
217 feature = "stm32f048",
218 feature = "stm32f071",
219 feature = "stm32f072",
220 feature = "stm32f078",
221 feature = "stm32f091",
222 feature = "stm32f098",
223 ))]
224 HSI48,
225 }
226
227 pub(super) fn get_freq(c_src: &SysClkSource) -> u32 {
228 match c_src {
231 SysClkSource::HSE(freq, _) => *freq,
232 #[cfg(any(
233 feature = "stm32f042",
234 feature = "stm32f048",
235 feature = "stm32f071",
236 feature = "stm32f072",
237 feature = "stm32f078",
238 feature = "stm32f091",
239 feature = "stm32f098",
240 ))]
241 SysClkSource::HSI48 => HSI48,
242 _ => HSI,
243 }
244 }
245
246 pub(super) fn enable_clock(rcc: &mut RCC, c_src: &SysClkSource) {
247 match c_src {
249 SysClkSource::HSE(_, bypassed) => {
250 match bypassed {
251 super::HSEBypassMode::NotBypassed => {
252 rcc.cr
253 .modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed());
254 }
255 super::HSEBypassMode::Bypassed => {
256 rcc.cr
257 .modify(|_, w| w.csson().on().hseon().on().hsebyp().bypassed());
258 }
259 }
260
261 while !rcc.cr.read().hserdy().bit_is_set() {}
262 }
263 #[cfg(any(
264 feature = "stm32f042",
265 feature = "stm32f048",
266 feature = "stm32f071",
267 feature = "stm32f072",
268 feature = "stm32f078",
269 feature = "stm32f091",
270 feature = "stm32f098",
271 ))]
272 SysClkSource::HSI48 => {
273 rcc.cr2.modify(|_, w| w.hsi48on().set_bit());
274 while rcc.cr2.read().hsi48rdy().bit_is_clear() {}
275 }
276 SysClkSource::HSI => {
277 rcc.cr.write(|w| w.hsion().set_bit());
278 while rcc.cr.read().hsirdy().bit_is_clear() {}
279 }
280 }
281 }
282
283 pub(super) fn enable_pll(
284 rcc: &mut RCC,
285 c_src: &SysClkSource,
286 pllmul_bits: u8,
287 ppre_bits: u8,
288 hpre_bits: u8,
289 ) {
290 let pllsrc_bit: u8 = match (c_src, RCC_PLLSRC_PREDIV1_SUPPORT) {
291 (SysClkSource::HSI, false) => 0b00, (SysClkSource::HSI, true) => 0b01, #[cfg(any(
294 feature = "stm32f042",
295 feature = "stm32f048",
296 feature = "stm32f071",
297 feature = "stm32f072",
298 feature = "stm32f078",
299 feature = "stm32f091",
300 feature = "stm32f098",
301 ))]
302 (SysClkSource::HSI48, _) => 0b11,
303 (SysClkSource::HSE(_, _), _) => 0b10,
304 };
305
306 rcc.cfgr
308 .modify(|_, w| w.pllsrc().bits(pllsrc_bit).pllmul().bits(pllmul_bits));
309
310 rcc.cr.modify(|_, w| w.pllon().set_bit());
311 while rcc.cr.read().pllrdy().bit_is_clear() {}
312
313 rcc.cfgr
314 .modify(|_, w| unsafe { w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll() });
315 }
316
317 pub(super) fn get_sww(c_src: &SysClkSource) -> SW_A {
318 match c_src {
319 SysClkSource::HSI => SW_A::HSI,
320 #[cfg(any(
321 feature = "stm32f042",
322 feature = "stm32f048",
323 feature = "stm32f071",
324 feature = "stm32f072",
325 feature = "stm32f078",
326 feature = "stm32f091",
327 feature = "stm32f098",
328 ))]
329 SysClkSource::HSI48 => SW_A::HSI48,
330 SysClkSource::HSE(_, _) => SW_A::HSE,
331 }
332 }
333}
334
335use self::inner::SysClkSource;
336
337pub struct CFGR {
338 hclk: Option<u32>,
339 pclk: Option<u32>,
340 sysclk: Option<u32>,
341 clock_src: SysClkSource,
342 #[cfg(any(
343 feature = "stm32f042",
344 feature = "stm32f048",
345 feature = "stm32f070",
346 feature = "stm32f072",
347 feature = "stm32f078",
348 ))]
349 usb_src: USBClockSource,
350 #[cfg(any(
352 feature = "stm32f042",
353 feature = "stm32f048",
354 feature = "stm32f071",
355 feature = "stm32f072",
356 feature = "stm32f078",
357 feature = "stm32f091",
358 feature = "stm32f098",
359 ))]
360 crs: Option<crate::pac::CRS>,
361 rcc: RCC,
362}
363
364impl CFGR {
365 pub fn hse<F>(mut self, freq: F, bypass: HSEBypassMode) -> Self
366 where
367 F: Into<Hertz>,
368 {
369 self.clock_src = SysClkSource::HSE(freq.into().0, bypass);
370 self
371 }
372
373 #[cfg(any(
374 feature = "stm32f042",
375 feature = "stm32f048",
376 feature = "stm32f071",
377 feature = "stm32f072",
378 feature = "stm32f078",
379 feature = "stm32f091",
380 feature = "stm32f098",
381 ))]
382 pub fn hsi48(mut self) -> Self {
383 self.clock_src = SysClkSource::HSI48;
384 self
385 }
386
387 pub fn hclk<F>(mut self, freq: F) -> Self
388 where
389 F: Into<Hertz>,
390 {
391 self.hclk = Some(freq.into().0);
392 self
393 }
394
395 pub fn pclk<F>(mut self, freq: F) -> Self
396 where
397 F: Into<Hertz>,
398 {
399 self.pclk = Some(freq.into().0);
400 self
401 }
402
403 pub fn sysclk<F>(mut self, freq: F) -> Self
404 where
405 F: Into<Hertz>,
406 {
407 self.sysclk = Some(freq.into().0);
408 self
409 }
410 #[cfg(any(
411 feature = "stm32f042",
412 feature = "stm32f048",
413 feature = "stm32f070",
414 feature = "stm32f072",
415 feature = "stm32f078",
416 ))]
417 pub fn usbsrc(mut self, src: USBClockSource) -> Self {
419 self.usb_src = src;
420 self
421 }
422
423 #[cfg(any(
424 feature = "stm32f042",
425 feature = "stm32f048",
426 feature = "stm32f071",
427 feature = "stm32f072",
428 feature = "stm32f078",
429 feature = "stm32f091",
430 feature = "stm32f098",
431 ))]
432 pub fn enable_crs(mut self, crs: crate::pac::CRS) -> Self {
433 self.crs = Some(crs);
434 self
435 }
436
437 pub fn freeze(mut self, flash: &mut crate::pac::FLASH) -> Rcc {
438 let sysclk = self.sysclk.unwrap_or(self::inner::HSI);
440
441 let r_sysclk; let pllmul_bits;
443
444 let src_clk_freq = self::inner::get_freq(&self.clock_src);
448
449 if sysclk == src_clk_freq {
451 pllmul_bits = None;
455 r_sysclk = src_clk_freq;
456 } else {
457 let pllprediv = match (&self.clock_src, self::inner::RCC_PLLSRC_PREDIV1_SUPPORT) {
461 (self::inner::SysClkSource::HSI, false) => 2,
462 (_, _) => 1,
463 };
464 let pllmul = (2 * pllprediv * self.sysclk.unwrap_or(src_clk_freq) + src_clk_freq)
466 / src_clk_freq
467 / 2;
468 let pllmul = core::cmp::min(core::cmp::max(pllmul, 2), 16);
469 r_sysclk = pllmul * src_clk_freq / pllprediv;
470
471 pllmul_bits = Some(pllmul as u8 - 2)
472 }
473
474 let hpre_bits = self
475 .hclk
476 .map(|hclk| match r_sysclk / hclk {
477 0 => unreachable!(),
478 1 => 0b0111,
479 2 => 0b1000,
480 3..=5 => 0b1001,
481 6..=11 => 0b1010,
482 12..=39 => 0b1011,
483 40..=95 => 0b1100,
484 96..=191 => 0b1101,
485 192..=383 => 0b1110,
486 _ => 0b1111,
487 })
488 .unwrap_or(0b0111);
489
490 let hclk = r_sysclk / (1 << (hpre_bits - 0b0111));
491
492 let ppre_bits = self
493 .pclk
494 .map(|pclk| match hclk / pclk {
495 0 => unreachable!(),
496 1 => 0b011,
497 2 => 0b100,
498 3..=5 => 0b101,
499 6..=11 => 0b110,
500 _ => 0b111,
501 })
502 .unwrap_or(0b011);
503
504 let ppre: u8 = 1 << (ppre_bits - 0b011);
505 let pclk = hclk / cast::u32(ppre);
506
507 unsafe {
509 flash.acr.write(|w| {
510 w.latency().bits(if r_sysclk <= 24_000_000 {
511 0b000
512 } else if r_sysclk <= 48_000_000 {
513 0b001
514 } else {
515 0b010
516 })
517 })
518 }
519
520 self::inner::enable_clock(&mut self.rcc, &self.clock_src);
522
523 #[cfg(feature = "stm32f070")]
525 {
526 match self.usb_src {
527 USBClockSource::Disabled => self.rcc.cfgr3.modify(|_, w| w.usbsw().clear_bit()),
528 USBClockSource::PLL => self.rcc.cfgr3.modify(|_, w| w.usbsw().set_bit()),
529 }
530 }
531 #[cfg(any(
532 feature = "stm32f042",
533 feature = "stm32f048",
534 feature = "stm32f072",
535 feature = "stm32f078",
536 ))]
537 match self.usb_src {
538 USBClockSource::HSI48 => self.rcc.cfgr3.modify(|_, w| w.usbsw().clear_bit()),
539 USBClockSource::PLL => self.rcc.cfgr3.modify(|_, w| w.usbsw().set_bit()),
540 }
541 if let Some(pllmul_bits) = pllmul_bits {
545 self::inner::enable_pll(
546 &mut self.rcc,
547 &self.clock_src,
548 pllmul_bits,
549 ppre_bits,
550 hpre_bits,
551 );
552 } else {
553 let sw_var = self::inner::get_sww(&self.clock_src);
554
555 #[cfg(any(
557 feature = "stm32f042",
558 feature = "stm32f048",
559 feature = "stm32f071",
560 feature = "stm32f072",
561 feature = "stm32f078",
562 feature = "stm32f091",
563 feature = "stm32f098",
564 ))]
565 match self.crs {
566 Some(crs) => {
567 self.rcc.apb1enr.modify(|_, w| w.crsen().set_bit());
568
569 crs.cr.modify(|_, w| w.autotrimen().set_bit());
572 crs.cr.modify(|_, w| w.cen().set_bit());
574 }
575 _ => {}
576 }
577
578 self.rcc.cfgr.modify(|_, w| unsafe {
580 w.ppre()
581 .bits(ppre_bits)
582 .hpre()
583 .bits(hpre_bits)
584 .sw()
585 .variant(sw_var)
586 });
587 }
588 Rcc {
589 clocks: Clocks {
590 hclk: Hertz(hclk),
591 pclk: Hertz(pclk),
592 sysclk: Hertz(sysclk),
593 },
594 regs: self.rcc,
595 }
596 }
597}
598
599#[derive(Clone, Copy)]
603pub struct Clocks {
604 hclk: Hertz,
605 pclk: Hertz,
606 sysclk: Hertz,
607}
608
609impl Clocks {
610 pub fn hclk(&self) -> Hertz {
612 self.hclk
613 }
614
615 pub fn pclk(&self) -> Hertz {
617 self.pclk
618 }
619
620 pub fn sysclk(&self) -> Hertz {
622 self.sysclk
623 }
624}