Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/fractional-pll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ fn main() -> ! {
info!("sys_ck = {} Hz", ccdr.clocks.sys_ck().raw());
assert_eq!(ccdr.clocks.sys_ck().raw(), 250_000_000);

info!("pll2_p_ck = {}", ccdr.clocks.pll2_p_ck().unwrap());
info!("pll2_q_ck = {}", ccdr.clocks.pll2_q_ck().unwrap());
info!("pll2_r_ck = {}", ccdr.clocks.pll2_r_ck().unwrap());
info!("pll2_p_ck = {}", ccdr.clocks.pll2().p_ck().unwrap());
info!("pll2_q_ck = {}", ccdr.clocks.pll2().q_ck().unwrap());
info!("pll2_r_ck = {}", ccdr.clocks.pll2().r_ck().unwrap());

let _mco2_ck = ccdr.clocks.mco2_ck().unwrap().raw();

Expand Down
119 changes: 91 additions & 28 deletions src/rcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,16 @@

use crate::pwr::PowerConfiguration;
use crate::pwr::VoltageScale as Voltage;
#[cfg(feature = "rm0481")]
use crate::stm32::rcc::pll3cfgr::PLL3SRC;
use crate::stm32::rcc::{
ccipr5::CKPERSEL, cfgr1::SW, cfgr1::TIMPRE, cfgr2::HPRE,
cfgr2::PPRE1 as PPRE, pll1cfgr::PLL1SRC, pll2cfgr::PLL2SRC,
};
use crate::stm32::{RCC, SBS};
use crate::time::Hertz;

use core_clocks::PllClocks;
#[cfg(feature = "log")]
use log::debug;

Expand Down Expand Up @@ -168,8 +171,6 @@ pub struct Config {
rcc_pclk1: Option<u32>,
rcc_pclk2: Option<u32>,
rcc_pclk3: Option<u32>,
#[cfg(feature = "rm0481")]
rcc_pclk4: Option<u32>,
mco1: MCO1Config,
mco2: MCO2Config,
pll1: PllConfig,
Expand Down Expand Up @@ -199,8 +200,6 @@ impl RccExt for RCC {
rcc_pclk1: None,
rcc_pclk2: None,
rcc_pclk3: None,
#[cfg(feature = "rm0481")]
rcc_pclk4: None,
mco1: MCO1Config::default(),
mco2: MCO2Config::default(),
pll1: PllConfig::default(),
Expand Down Expand Up @@ -376,11 +375,6 @@ impl Rcc {
pclk3: rcc_pclk3,
}

#[cfg(feature = "rm0481")]
pclk_setter! {
pclk4: rcc_pclk4,
}

pll_setter! {
pll1: [
pll1_p_ck: p_ck,
Expand All @@ -394,10 +388,24 @@ impl Rcc {
],
}

#[cfg(feature = "rm0481")]
pll_setter! {
pll3: [
pll3_p_ck: p_ck,
pll3_q_ck: q_ck,
pll3_r_ck: r_ck,
],
}

pll_strategy_setter! {
pll1: pll1_strategy,
pll2: pll2_strategy,
}

#[cfg(feature = "rm0481")]
pll_strategy_setter! {
pll3: pll3_strategy,
}
}

/// Divider calculator for pclk 1 - 4
Expand Down Expand Up @@ -574,6 +582,10 @@ impl Rcc {
let (pll2_p_ck, pll2_q_ck, pll2_r_ck) =
self.pll2_setup(rcc, &self.config.pll2);

#[cfg(feature = "rm0481")]
let (pll3_p_ck, pll3_q_ck, pll3_r_ck) =
self.pll3_setup(rcc, &self.config.pll3);

let sys_ck = if sys_use_pll1_p {
pll1_p_ck.unwrap() // Must have been set by sys_ck_setup
} else {
Expand Down Expand Up @@ -718,6 +730,15 @@ impl Rcc {
};
rcc.pll1cfgr().modify(|_, w| w.pll1src().variant(pll1src));
rcc.pll2cfgr().modify(|_, w| w.pll2src().variant(pll2src));
#[cfg(feature = "rm0481")]
{
let pll3src = if self.config.hse.is_some() {
PLL3SRC::Hse
} else {
PLL3SRC::Hsi
};
rcc.pll3cfgr().modify(|_, w| w.pll3src().variant(pll3src));
}

// PLL1
if pll1_p_ck.is_some() {
Expand All @@ -733,6 +754,14 @@ impl Rcc {
while rcc.cr().read().pll2rdy().is_not_ready() {}
}

// PLL3
#[cfg(feature = "rm0481")]
if pll3_p_ck.is_some() {
// Enable PLL and wait for it to stabilise
rcc.cr().modify(|_, w| w.pll3on().on());
while rcc.cr().read().pll3rdy().is_not_ready() {}
}

// Core Prescaler / AHB Prescaler / APBx Prescalers
rcc.cfgr2().modify(|_, w| {
w.hpre()
Expand Down Expand Up @@ -824,19 +853,6 @@ impl Rcc {
pll1cfgr.pll1ren().variant(),
);

let pll2cfgr = rcc.pll2cfgr().read();
debug!(
"PLL2CFGR register: PLL2SRC={:?} PLL2RGE={:?} PLL2FRACEN={:?} PLL2VCOSEL={:?} PLL2M={:#x} PLL2PEN={:?} PLL2QEN={:?} PLL2REN={:?}",
pll2cfgr.pll2src().variant(),
pll2cfgr.pll2rge().variant(),
pll2cfgr.pll2fracen().variant(),
pll2cfgr.pll2vcosel().variant(),
pll2cfgr.pll2m().bits(),
pll2cfgr.pll2pen().variant(),
pll2cfgr.pll2qen().variant(),
pll2cfgr.pll2ren().variant(),
);

let pll1divr = rcc.pll1divr().read();
debug!(
"PLL1DIVR register: PLL1N={:#x} PLL1P={:#x} PLL1Q={:#x} PLL1R={:#x}",
Expand All @@ -852,6 +868,19 @@ impl Rcc {
pll1fracr.pll1fracn().bits(),
);

let pll2cfgr = rcc.pll2cfgr().read();
debug!(
"PLL2CFGR register: PLL2SRC={:?} PLL2RGE={:?} PLL2FRACEN={:?} PLL2VCOSEL={:?} PLL2M={:#x} PLL2PEN={:?} PLL2QEN={:?} PLL2REN={:?}",
pll2cfgr.pll2src().variant(),
pll2cfgr.pll2rge().variant(),
pll2cfgr.pll2fracen().variant(),
pll2cfgr.pll2vcosel().variant(),
pll2cfgr.pll2m().bits(),
pll2cfgr.pll2pen().variant(),
pll2cfgr.pll2qen().variant(),
pll2cfgr.pll2ren().variant(),
);

let pll2divr = rcc.pll2divr().read();
debug!(
"PLL2DIVR register: PLL2N={:#x} PLL2P={:#x} PLL2Q={:#x} PLL2R={:#x}",
Expand All @@ -866,8 +895,44 @@ impl Rcc {
"PLL2FRACR register: FRACN2={:#x}",
pll2fracr.pll2fracn().bits(),
);

#[cfg(feature = "rm0481")]
{
let pll3cfgr = rcc.pll3cfgr().read();
debug!(
"PLL3CFGR register: PLL3SRC={:?} PLL3RGE={:?} PLL3FRACEN={:?} PLL3VCOSEL={:?} PLL3M={:#x} PLL3PEN={:?} PLL3QEN={:?} PLL3REN={:?}",
pll3cfgr.pll3src().variant(),
pll3cfgr.pll3rge().variant(),
pll3cfgr.pll3fracen().variant(),
pll3cfgr.pll3vcosel().variant(),
pll3cfgr.pll3m().bits(),
pll3cfgr.pll3pen().variant(),
pll3cfgr.pll3qen().variant(),
pll3cfgr.pll3ren().variant(),
);

let pll3divr = rcc.pll3divr().read();
debug!(
"PLL3DIVR register: PLL3N={:#x} PLL3P={:#x} PLL3Q={:#x} PLL3R={:#x}",
pll3divr.pll3n().bits(),
pll3divr.pll3p().bits(),
pll3divr.pll3q().bits(),
pll3divr.pll3r().bits(),
);

let pll3fracr = rcc.pll3fracr().read();
debug!(
"PLL3FRACR register: FRACN2={:#x}",
pll3fracr.pll3fracn().bits(),
);
}
}

let pll1 = PllClocks::new(pll1_p_ck, pll1_q_ck, pll1_r_ck);
let pll2 = PllClocks::new(pll2_p_ck, pll2_q_ck, pll2_r_ck);
#[cfg(feature = "rm0481")]
let pll3 = PllClocks::new(pll3_p_ck, pll3_q_ck, pll3_r_ck);

// Return frozen clock configuration
Ccdr {
clocks: CoreClocks {
Expand All @@ -888,12 +953,10 @@ impl Rcc {
audio_ck,
mco1_ck,
mco2_ck,
pll1_p_ck,
pll1_q_ck,
pll1_r_ck,
pll2_p_ck,
pll2_q_ck,
pll2_r_ck,
pll1,
pll2,
#[cfg(feature = "rm0481")]
pll3,
timx_ker_ck: Hertz::from_raw(rcc_timx_ker_ck),
timy_ker_ck: Hertz::from_raw(rcc_timy_ker_ck),
sys_ck,
Expand Down
75 changes: 49 additions & 26 deletions src/rcc/core_clocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,37 @@

use crate::time::Hertz;

#[derive(Clone, Copy)]
pub struct PllClocks {
p_ck: Option<Hertz>,
q_ck: Option<Hertz>,
r_ck: Option<Hertz>,
}

impl PllClocks {
pub fn new(
p_ck: Option<Hertz>,
q_ck: Option<Hertz>,
r_ck: Option<Hertz>,
) -> Self {
Self { p_ck, q_ck, r_ck }
}
}

impl PllClocks {
pub fn p_ck(&self) -> Option<Hertz> {
self.p_ck
}

pub fn q_ck(&self) -> Option<Hertz> {
self.q_ck
}

pub fn r_ck(&self) -> Option<Hertz> {
self.r_ck
}
}

/// Frozen core clock frequencies
///
/// The existence of this value indicates that the core clock
Expand All @@ -25,12 +56,10 @@ pub struct CoreClocks {
pub(super) audio_ck: Option<Hertz>,
pub(super) mco1_ck: Option<Hertz>,
pub(super) mco2_ck: Option<Hertz>,
pub(super) pll1_p_ck: Option<Hertz>,
pub(super) pll1_q_ck: Option<Hertz>,
pub(super) pll1_r_ck: Option<Hertz>,
pub(super) pll2_p_ck: Option<Hertz>,
pub(super) pll2_q_ck: Option<Hertz>,
pub(super) pll2_r_ck: Option<Hertz>,
pub(super) pll1: PllClocks,
pub(super) pll2: PllClocks,
#[cfg(feature = "rm0481")]
pub(super) pll3: PllClocks,
pub(super) timx_ker_ck: Hertz,
pub(super) timy_ker_ck: Hertz,
pub(super) sys_ck: Hertz,
Expand Down Expand Up @@ -66,19 +95,6 @@ macro_rules! optional_ck_getter {
};
}

/// Getters for pll clocks
macro_rules! pll_getter {
($($pll_ck:ident,)+) => {
$(
/// Returns `Some(frequency)` if the PLLx output is running,
/// otherwise `None`
pub fn $pll_ck(&self) -> Option<Hertz> {
self.$pll_ck
}
)+
};
}

impl CoreClocks {
/// Returns the frequency of AHB1,2,3 busses
pub fn hclk(&self) -> Hertz {
Expand Down Expand Up @@ -114,13 +130,20 @@ impl CoreClocks {
self.mco2_ck
}

pll_getter! {
pll1_p_ck,
pll1_q_ck,
pll1_r_ck,
pll2_p_ck,
pll2_q_ck,
pll2_r_ck,
/// Returns the configuration for PLL1
pub fn pll1(&self) -> PllClocks {
self.pll1
}

/// Returns the configuration for PLL2
pub fn pll2(&self) -> PllClocks {
self.pll2
}

#[cfg(feature = "rm0481")]
/// Returns the configuration for PLL3
pub fn pll3(&self) -> PllClocks {
self.pll3
}

/// Returns the input frequency to the SCGU
Expand Down
2 changes: 2 additions & 0 deletions src/rcc/pll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ fn calc_vco_ck(ref_ck: u32, pll_n: u32, pll_fracn: u16) -> u32 {
impl Rcc {
pll_setup! {pll1, false}
pll_setup! {pll2, true}
#[cfg(feature = "rm0481")]
pll_setup! {pll3, true}
}

#[cfg(test)]
Expand Down
Loading