Skip to content

Commit a602140

Browse files
committed
rcc: Add force pll use function
1 parent 638839c commit a602140

File tree

3 files changed

+55
-13
lines changed

3 files changed

+55
-13
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
6161
- On the bases of these interrupts, the interrupt controller (NVIC) can
6262
be set to mask or unmask these interrupts.
6363
- Implement the `embedded-hal::timer::Cancel` trait for timers. ([#267])
64+
- Add `use_pll` to `CFGR` - the clock configuration - to force to use the PLL
65+
source for the systemclock. Also `Clocks::pllclk()` was introduced to be able
66+
to check, whether PLL is used.
6467

6568
[`enumset`]: https://crates.io/crates/enumset
6669

src/rcc.rs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,17 +261,32 @@ impl BDCR {
261261
/// let rcc = dp.RCC.constrain();
262262
/// use_cfgr(&mut rcc.cfgr)
263263
/// ```
264-
#[derive(Default)]
265264
pub struct CFGR {
266265
hse: Option<u32>,
267266
hse_bypass: bool,
267+
pll_bypass: bool,
268268
css: bool,
269269
hclk: Option<u32>,
270270
pclk1: Option<u32>,
271271
pclk2: Option<u32>,
272272
sysclk: Option<u32>,
273273
}
274274

275+
impl Default for CFGR {
276+
fn default() -> Self {
277+
Self {
278+
hse: None,
279+
hse_bypass: false,
280+
pll_bypass: true,
281+
css: false,
282+
hclk: None,
283+
pclk1: None,
284+
pclk2: None,
285+
sysclk: None,
286+
}
287+
}
288+
}
289+
275290
pub(crate) struct PllConfig {
276291
src: cfgr::PLLSRC_A,
277292
mul: cfgr::PLLMUL_A,
@@ -350,6 +365,12 @@ impl CFGR {
350365
self
351366
}
352367

368+
/// Set this to disallow bypass the PLLCLK for the systemclock generation.
369+
pub fn use_pll(mut self) -> Self {
370+
self.pll_bypass = false;
371+
self
372+
}
373+
353374
/// Enable `HSE` bypass.
354375
///
355376
/// Uses user provided clock signal instead of an external oscillator.
@@ -602,9 +623,11 @@ impl CFGR {
602623
// because the two valid USB clocks, 72 Mhz and 48 Mhz, can't be generated
603624
// directly from neither the internal rc (8 Mhz) nor the external
604625
// Oscillator (max 32 Mhz), without using the PLL.
605-
(Some(sysclk), Some(hse)) if sysclk == hse => (hse, cfgr::SW_A::HSE, None),
626+
(Some(sysclk), Some(hse)) if sysclk == hse && self.pll_bypass => {
627+
(hse, cfgr::SW_A::HSE, None)
628+
}
606629
// No need to use the PLL
607-
(Some(sysclk), None) if sysclk == HSI.integer() => {
630+
(Some(sysclk), None) if sysclk == HSI.integer() && self.pll_bypass => {
608631
(HSI.integer(), cfgr::SW_A::HSI, None)
609632
}
610633
(Some(sysclk), _) => {
@@ -758,6 +781,7 @@ impl CFGR {
758781
ppre2,
759782
sysclk: Hertz(sysclk),
760783
usbclk_valid,
784+
pll_bypass: self.pll_bypass,
761785
}
762786
}
763787
}
@@ -775,6 +799,7 @@ pub struct Clocks {
775799
ppre2: u8,
776800
sysclk: Hertz,
777801
usbclk_valid: bool,
802+
pll_bypass: bool,
778803
}
779804

780805
// TODO(Sh3Rm4n) Add defmt support for embedded-time!
@@ -784,14 +809,15 @@ impl defmt::Format for Clocks {
784809
// Format as hexadecimal.
785810
defmt::write!(
786811
f,
787-
"Clocks {{ hclk: {} Hz, pclk1: {} Hz, pclk2: {} Hz, ppre1: {:b}, ppre2: {:b}, sysclk: {} Hz, usbclk_valid: {} }}",
812+
"Clocks {{ hclk: {} Hz, pclk1: {} Hz, pclk2: {} Hz, ppre1: {:b}, ppre2: {:b}, sysclk: {} Hz, usbclk_valid: {}, pll_bypass: {} }}",
788813
self.hclk.integer(),
789814
self.pclk1.integer(),
790815
self.pclk2.integer(),
791816
self.ppre1,
792817
self.ppre2,
793818
self.sysclk.integer(),
794819
self.usbclk_valid,
820+
self.pll_bypass,
795821
);
796822
}
797823
}
@@ -830,6 +856,19 @@ impl Clocks {
830856
self.sysclk
831857
}
832858

859+
/// Returns the PLL clock if configured, else it returns `None`.
860+
///
861+
/// The PLL clock is a source of the system clock, but it is not necessarily configured to be one.
862+
pub fn pllclk(&self) -> Option<Hertz> {
863+
if self.pll_bypass {
864+
None
865+
} else {
866+
// The PLLCLK is the same as the sysclk, beccause
867+
// the sysclk is using it as a source.
868+
Some(self.sysclk())
869+
}
870+
}
871+
833872
/// Returns whether the USBCLK clock frequency is valid for the USB peripheral
834873
///
835874
/// If the microcontroller does support USB, 48 Mhz or 72 Mhz have to be used

src/timer.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -472,15 +472,15 @@ macro_rules! timer_var_clock {
472472
clocks.$pclkX()
473473
}
474474
}
475-
// TODO: Implement PLL in Rcc
476-
// 1: PLL vco output (running up to 144 MHz)
477-
// TODO: Make sure that * 2 is always correct
478-
crate::pac::rcc::cfgr3::TIM1SW_A::PLL /* if $PLL */ => clocks.$pclkX() * 2,
479-
// This state should not be posslbe.
480-
// TODO: Check if this assumption is correct.
481-
// TODO: Because of the way the it is created in the macro,
482-
// // this disticntion is not really needed anymore?
483-
// _ => crate::panic!("Invalid timer clock source."),
475+
crate::pac::rcc::cfgr3::TIM1SW_A::PLL => {
476+
if let Some(pllclk) = clocks.pllclk() {
477+
pllclk * 2
478+
} else {
479+
// This state should currently not be possible,
480+
// because the software source can not be configured right now.
481+
crate::panic!("Invalid timer clock source.");
482+
}
483+
}
484484
}
485485
}
486486
)+

0 commit comments

Comments
 (0)