use crate::{
clocks::SpeedError,
pac::{FLASH, RCC},
rcc_en_reset,
traits::{ClockCfg, ClocksValid},
};
use cfg_if::cfg_if;
#[cfg(not(feature = "g0"))]
#[derive(Clone, Copy, PartialEq)]
#[repr(u8)]
pub enum Clk48Src {
Hsi48 = 0b00,
#[cfg(not(feature = "g4"))]
PllSai1 = 0b01,
Pllq = 0b10,
#[cfg(not(feature = "g4"))]
Msi = 0b11,
}
#[cfg(not(any(feature = "g0", feature = "g4")))]
#[derive(Clone, Copy, PartialEq)]
pub enum PllSrc {
None,
Msi(MsiRange),
Hsi,
Hse(u32),
}
#[cfg(any(feature = "g0", feature = "g4"))]
#[derive(Clone, Copy, PartialEq)]
pub enum PllSrc {
None,
Hsi,
Hse(u32),
}
#[cfg(any(feature = "l4", feature = "l5"))]
#[derive(Clone, Copy, PartialEq)]
#[repr(u8)]
pub enum StopWuck {
Msi = 0,
Hsi = 1,
}
#[derive(Clone, Copy)]
#[repr(u8)]
enum WaitState {
W0 = 0,
W1 = 1,
W2 = 2,
W3 = 3,
W4 = 4,
#[cfg(feature = "l5")]
W5 = 5,
}
impl PllSrc {
pub fn bits(&self) -> u8 {
#[cfg(not(any(feature = "g0", feature = "g4")))]
match self {
Self::None => 0b00,
Self::Msi(_) => 0b01,
Self::Hsi => 0b10,
Self::Hse(_) => 0b11,
}
#[cfg(any(feature = "g0", feature = "g4"))]
match self {
Self::None => 0b00,
Self::Hsi => 0b10,
Self::Hse(_) => 0b11,
}
}
}
cfg_if! {
if #[cfg(feature = "g0")] {
#[derive(Clone, Copy, PartialEq)]
pub enum InputSrc {
Hsi,
Hse(u32),
Pll(PllSrc),
Lsi,
Lse,
}
impl InputSrc {
pub fn bits(&self) -> u8 {
match self {
Self::Hsi => 0b000,
Self::Hse(_) => 0b001,
Self::Pll(_) => 0b010,
Self::Lsi => 0b011,
Self::Lse => 0b100,
}
}
}
} else if #[cfg(feature = "g4")] {
#[derive(Clone, Copy, PartialEq)]
pub enum InputSrc {
Hsi,
Hse(u32),
Pll(PllSrc),
}
impl InputSrc {
pub fn bits(&self) -> u8 {
match self {
Self::Hsi => 0b01,
Self::Hse(_) => 0b10,
Self::Pll(_) => 0b11,
}
}
}
} else {
#[derive(Clone, Copy, PartialEq)]
pub enum InputSrc {
Msi(MsiRange),
Hsi,
Hse(u32),
Pll(PllSrc),
}
impl InputSrc {
pub fn bits(&self) -> u8 {
match self {
Self::Msi(_) => 0b00,
Self::Hsi => 0b01,
Self::Hse(_) => 0b10,
Self::Pll(_) => 0b11,
}
}
}
}
}
#[cfg(not(any(feature = "g0", feature = "g4")))]
#[derive(Clone, Copy, PartialEq)]
#[repr(u8)]
pub enum MsiRange {
R100k = 0b0000,
R200k = 0b0001,
R400k = 0b0010,
R800k = 0b0011,
R1M = 0b0100,
R2M = 0b0101,
R4M = 0b0110,
R8M = 0b0111,
R16M = 0b1000,
R24M = 0b1001,
R32M = 0b1010,
R48M = 0b1011,
}
#[cfg(not(any(feature = "g0", feature = "g4")))]
impl MsiRange {
fn value(&self) -> u32 {
match self {
Self::R100k => 100_000,
Self::R200k => 200_000,
Self::R400k => 400_000,
Self::R800k => 800_000,
Self::R1M => 1_000_000,
Self::R2M => 2_000_000,
Self::R4M => 4_000_000,
Self::R8M => 8_000_000,
Self::R16M => 16_000_000,
Self::R24M => 24_000_000,
Self::R32M => 32_000_000,
Self::R48M => 48_000_000,
}
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Prediv {
Div1 = 0b0000,
Div2 = 0b0001,
Div3 = 0b0010,
Div4 = 0b0011,
Div5 = 0b0100,
Div6 = 0b0101,
Div7 = 0b0110,
Div8 = 0b0111,
}
impl Prediv {
pub fn value(&self) -> u8 {
match self {
Self::Div1 => 1,
Self::Div2 => 2,
Self::Div3 => 3,
Self::Div4 => 4,
Self::Div5 => 5,
Self::Div6 => 6,
Self::Div7 => 7,
Self::Div8 => 8,
}
}
}
#[cfg(not(feature = "g4"))]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Pllm {
Div1 = 0b000,
Div2 = 0b001,
Div3 = 0b010,
Div4 = 0b011,
Div5 = 0b100,
Div6 = 0b101,
Div7 = 0b110,
Div8 = 0b111,
}
#[cfg(feature = "g4")]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Pllm {
Div1 = 0b0000,
Div2 = 0b0001,
Div3 = 0b0010,
Div4 = 0b0011,
Div5 = 0b0100,
Div6 = 0b0101,
Div7 = 0b0110,
Div8 = 0b0111,
Div9 = 0b1000,
Div10 = 0b1001,
Div11 = 0b1010,
Div12 = 0b1011,
Div13 = 0b1100,
Div14 = 0b1101,
Div15 = 0b1110,
Div16 = 0b1111,
}
impl Pllm {
pub fn value(&self) -> u8 {
#[cfg(not(feature = "g4"))]
match self {
Self::Div1 => 1,
Self::Div2 => 2,
Self::Div3 => 3,
Self::Div4 => 4,
Self::Div5 => 5,
Self::Div6 => 6,
Self::Div7 => 7,
Self::Div8 => 8,
}
#[cfg(feature = "g4")]
match self {
Self::Div1 => 1,
Self::Div2 => 2,
Self::Div3 => 3,
Self::Div4 => 4,
Self::Div5 => 5,
Self::Div6 => 6,
Self::Div7 => 7,
Self::Div8 => 8,
Self::Div9 => 9,
Self::Div10 => 10,
Self::Div11 => 11,
Self::Div12 => 12,
Self::Div13 => 13,
Self::Div14 => 14,
Self::Div15 => 15,
Self::Div16 => 16,
}
}
}
#[cfg(feature = "g0")]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Pllr {
Div2 = 0b000,
Div3 = 0b001,
Div4 = 0b010,
Div5 = 0b011,
Div6 = 0b101,
Div7 = 0b110,
Div8 = 0b111,
}
#[cfg(feature = "g0")]
impl Pllr {
pub fn value(&self) -> u8 {
match self {
Self::Div2 => 2,
Self::Div3 => 3,
Self::Div4 => 4,
Self::Div5 => 5,
Self::Div6 => 6,
Self::Div7 => 7,
Self::Div8 => 8,
}
}
}
#[cfg(not(feature = "g0"))]
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Pllr {
Div2 = 0b00,
Div4 = 0b01,
Div6 = 0b10,
Div8 = 0b11,
}
#[cfg(not(feature = "g0"))]
impl Pllr {
pub fn value(&self) -> u8 {
match self {
Self::Div2 => 2,
Self::Div4 => 4,
Self::Div6 => 6,
Self::Div8 => 8,
}
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum HclkPrescaler {
Div1 = 0b0000,
Div2 = 0b1000,
Div4 = 0b1001,
Div8 = 0b1010,
Div16 = 0b1011,
Div64 = 0b1100,
Div128 = 0b1101,
Div256 = 0b1110,
Div512 = 0b1111,
}
impl HclkPrescaler {
pub fn value(&self) -> u16 {
match self {
Self::Div1 => 1,
Self::Div2 => 2,
Self::Div4 => 4,
Self::Div8 => 8,
Self::Div16 => 16,
Self::Div64 => 64,
Self::Div128 => 128,
Self::Div256 => 256,
Self::Div512 => 512,
}
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum ApbPrescaler {
Div1 = 0b000,
Div2 = 0b100,
Div4 = 0b101,
Div8 = 0b110,
Div16 = 0b111,
}
impl ApbPrescaler {
pub fn value(&self) -> u8 {
match self {
Self::Div1 => 1,
Self::Div2 => 2,
Self::Div4 => 4,
Self::Div8 => 8,
Self::Div16 => 16,
}
}
}
pub struct Clocks {
pub input_src: InputSrc,
pub pllm: Pllm,
pub plln: u8,
#[cfg(not(any(feature = "g0", feature = "g4")))]
pub pll_sai1_mul: u8,
#[cfg(not(any(feature = "g0", feature = "g4")))]
pub pll_sai2_mul: u8,
pub pllr: Pllr,
pub hclk_prescaler: HclkPrescaler,
pub apb1_prescaler: ApbPrescaler,
#[cfg(not(feature = "g0"))]
pub apb2_prescaler: ApbPrescaler,
#[cfg(not(any(feature = "g0")))]
pub clk48_src: Clk48Src,
#[cfg(not(any(feature = "g0", feature = "g4")))]
pub sai1_enabled: bool,
#[cfg(not(any(feature = "g0", feature = "g4")))]
pub sai2_enabled: bool,
pub hse_bypass: bool,
pub security_system: bool,
#[cfg(not(feature = "g0"))]
pub hsi48_on: bool,
#[cfg(any(feature = "l4", feature = "l5"))]
pub stop_wuck: StopWuck,
}
impl Clocks {
pub fn setup(&self, rcc: &mut RCC, flash: &mut FLASH) -> Result<(), SpeedError> {
if let ClocksValid::NotValid = self.validate_speeds() {
return Err(SpeedError {});
}
let (_, sysclk) = calc_sysclock(self.input_src, self.pllm, self.plln, self.pllr);
let hclk = sysclk / self.hclk_prescaler.value() as u32;
cfg_if! {
if #[cfg(feature = "l4")] {
flash.acr.modify(|_, w| unsafe {
if hclk <= 16_000_000 {
w.latency().bits(WaitState::W0 as u8)
} else if hclk <= 32_000_000 {
w.latency().bits(WaitState::W1 as u8)
} else if hclk <= 48_000_000 {
w.latency().bits(WaitState::W2 as u8)
} else if hclk <= 64_000_000 {
w.latency().bits(WaitState::W3 as u8)
} else {
w.latency().bits(WaitState::W4 as u8)
}
});
} else if #[cfg(feature = "l5")] {
flash.acr.modify(|_, w| unsafe {
if hclk <= 20_000_000 {
w.latency().bits(WaitState::W0 as u8)
} else if hclk <= 40_000_000 {
w.latency().bits(WaitState::W1 as u8)
} else if hclk <= 60_000_000 {
w.latency().bits(WaitState::W2 as u8)
} else if hclk <= 80_000_000 {
w.latency().bits(WaitState::W3 as u8)
} else if hclk <= 100_000_000 {
w.latency().bits(WaitState::W4 as u8)
} else {
w.latency().bits(WaitState::W5 as u8)
}
});
} else if #[cfg(feature = "g0")] {
flash.acr.modify(|_, w| unsafe {
if hclk <= 24_000_000 {
w.latency().bits(WaitState::W0 as u8)
} else if hclk <= 48_000_000 {
w.latency().bits(WaitState::W1 as u8)
} else {
w.latency().bits(WaitState::W2 as u8)
}
})
} else {
flash.acr.modify(|_, w| unsafe {
if hclk <= 34_000_000 {
w.latency().bits(WaitState::W0 as u8)
} else if hclk <= 68_000_000 {
w.latency().bits(WaitState::W1 as u8)
} else if hclk <= 102_000_000 {
w.latency().bits(WaitState::W2 as u8)
} else if hclk <= 136_000_000 {
w.latency().bits(WaitState::W3 as u8)
} else {
w.latency().bits(WaitState::W4 as u8)
}
});
}
}
match self.input_src {
#[cfg(not(any(feature = "g0", feature = "g4")))]
InputSrc::Msi(range) => {
rcc.cr.modify(|_, w| w.msion().clear_bit());
while rcc.cr.read().msirdy().bit_is_set() {}
rcc.cr.modify(|_, w| unsafe {
w.msirange()
.bits(range as u8)
.msirgsel()
.set_bit()
.msion()
.set_bit()
});
while rcc.cr.read().msirdy().bit_is_clear() {}
}
InputSrc::Hse(_) => {
rcc.cr.modify(|_, w| w.hseon().set_bit());
while rcc.cr.read().hserdy().bit_is_clear() {}
}
InputSrc::Hsi => {
rcc.cr.modify(|_, w| w.hsion().set_bit());
while rcc.cr.read().hsirdy().bit_is_clear() {}
}
InputSrc::Pll(pll_src) => {
match pll_src {
#[cfg(not(any(feature = "g0", feature = "g4")))]
PllSrc::Msi(range) => {
rcc.cr.modify(|_, w| unsafe {
w.msirange()
.bits(range as u8)
.msirgsel()
.set_bit()
.msion()
.set_bit()
});
while rcc.cr.read().msirdy().bit_is_clear() {}
}
PllSrc::Hse(_) => {
rcc.cr.modify(|_, w| w.hseon().set_bit());
while rcc.cr.read().hserdy().bit_is_clear() {}
}
PllSrc::Hsi => {
rcc.cr.modify(|_, w| w.hsion().set_bit());
while rcc.cr.read().hsirdy().bit_is_clear() {}
}
PllSrc::None => {}
}
}
#[cfg(feature = "g0")]
InputSrc::Lsi => {
rcc.csr.modify(|_, w| w.lsion().set_bit());
while rcc.csr.read().lsirdy().bit_is_clear() {}
}
#[cfg(feature = "g0")]
InputSrc::Lse => {
rcc.bdcr.modify(|_, w| w.lseon().set_bit());
while rcc.bdcr.read().lserdy().bit_is_clear() {}
}
}
rcc.cr.modify(|_, w| {
w.hsebyp().bit(self.hse_bypass)
});
if let InputSrc::Pll(pll_src) = self.input_src {
rcc.cr.modify(|_, w| w.pllon().clear_bit());
while rcc.cr.read().pllrdy().bit_is_set() {}
cfg_if! {
if #[cfg(feature = "g0")] {
rcc.pllsyscfgr.modify(|_, w| unsafe {
w.pllsrc().bits(pll_src.bits());
w.plln().bits(self.plln);
w.pllm().bits(self.pllm as u8);
w.pllr().bits(self.pllr as u8)
});
} else {
rcc.pllcfgr.modify(|_, w| unsafe {
w.pllsrc().bits(pll_src.bits());
w.plln().bits(self.plln);
w.pllm().bits(self.pllm as u8);
w.pllr().bits(self.pllr as u8)
});
}
}
cfg_if! {
if #[cfg(not(any(feature = "g0", feature = "g4")))] {
if self.sai1_enabled {
rcc.pllsai1cfgr
.modify(|_, w| unsafe { w.pllsai1n().bits(self.pll_sai1_mul) });
}
#[cfg(any(feature = "l4x5", feature = "l4x6",))]
if self.sai2_enabled {
rcc.pllsai2cfgr
.modify(|_, w| unsafe { w.pllsai2n().bits(self.pll_sai2_mul) });
}
}
}
rcc.cr.modify(|_, w| w.pllon().set_bit());
cfg_if! {
if #[cfg(not(any(feature = "g0", feature = "g4")))] {
if self.sai1_enabled {
rcc.cr.modify(|_, w| w.pllsai1on().set_bit());
while rcc.cr.read().pllsai1rdy().bit_is_clear() {}
}
#[cfg(any(feature = "l4x5", feature = "l4x6",))]
if self.sai2_enabled {
rcc.cr.modify(|_, w| w.pllsai2on().set_bit());
while rcc.cr.read().pllsai2rdy().bit_is_clear() {}
}
}
}
while rcc.cr.read().pllrdy().bit_is_clear() {}
cfg_if! {
if #[cfg(feature = "g0")] {
rcc.pllsyscfgr.modify(|_, w| {
w.pllpen().set_bit();
w.pllqen().set_bit();
w.pllren().set_bit()
});
} else {
rcc.pllcfgr.modify(|_, w| {
w.pllpen().set_bit();
w.pllqen().set_bit();
w.pllren().set_bit()
});
}
}
cfg_if! {
if #[cfg(not(any(feature = "g0", feature = "g4")))] {
if self.sai1_enabled {
rcc.pllsai1cfgr.modify(|_, w| {
w.pllsai1pen().set_bit();
w.pllsai1qen().set_bit();
w.pllsai1ren().set_bit()
});
}
#[cfg(any(feature = "l4x5", feature = "l4x6"))]
if self.sai2_enabled {
rcc.pllsai2cfgr.modify(|_, w| {
w.pllsai2pen().set_bit();
w.pllsai2ren().set_bit()
});
}
}
}
}
rcc.cfgr.modify(|_, w| unsafe {
w.sw().bits(self.input_src.bits());
w.hpre().bits(self.hclk_prescaler as u8);
#[cfg(not(feature = "g0"))]
w.ppre2().bits(self.apb2_prescaler as u8);
#[cfg(any(feature = "l4", feature = "l5"))]
w.stopwuck().bit(self.stop_wuck as u8 != 0);
#[cfg(not(feature = "g0"))]
return w.ppre1().bits(self.apb1_prescaler as u8);
#[cfg(feature = "g0")]
return w.ppre().bits(self.apb1_prescaler as u8);
});
rcc.cr.modify(|_, w| w.csson().bit(self.security_system));
#[cfg(any(feature = "l4", feature = "g4"))]
rcc.ccipr
.modify(|_, w| unsafe { w.clk48sel().bits(self.clk48_src as u8) });
#[cfg(feature = "l5")]
rcc.ccipr1
.modify(|_, w| unsafe { w.clk48msel().bits(self.clk48_src as u8) });
#[cfg(not(feature = "g0"))]
if self.hsi48_on {
rcc.crrcr.modify(|_, w| w.hsi48on().set_bit());
while rcc.crrcr.read().hsi48rdy().bit_is_clear() {}
}
cfg_if! {
if #[cfg(any(feature = "l4", feature = "l5"))] {
match self.input_src {
InputSrc::Msi(_) => (),
InputSrc::Pll(pll_src) => {
match pll_src {
PllSrc::Msi(_) => (),
_ => {
rcc.cr.modify(|_, w| w.msion().clear_bit());
}
}
}
_ => {
rcc.cr.modify(|_, w| w.msion().clear_bit());
}
}
} else {
match self.input_src {
InputSrc::Hsi => (),
InputSrc::Pll(pll_src) => {
match pll_src {
PllSrc::Hsi => (),
_ => {
rcc.cr.modify(|_, w| w.hsion().clear_bit());
}
}
}
_ => {
rcc.cr.modify(|_, w| w.hsion().clear_bit());
}
}
}
}
rcc_en_reset!(apb2, syscfg, rcc);
Ok(())
}
pub(crate) fn re_select_input(&self, rcc: &mut RCC) {
match self.input_src {
InputSrc::Hse(_) => {
rcc.cr.modify(|_, w| w.hseon().set_bit());
while rcc.cr.read().hserdy().bit_is_clear() {}
rcc.cfgr
.modify(|_, w| unsafe { w.sw().bits(self.input_src.bits()) });
}
InputSrc::Pll(pll_src) => {
match pll_src {
PllSrc::Hse(_) => {
rcc.cr.modify(|_, w| w.hseon().set_bit());
while rcc.cr.read().hserdy().bit_is_clear() {}
}
PllSrc::Hsi => {
#[cfg(any(feature = "l4", feature = "l5"))]
if let StopWuck::Msi = self.stop_wuck {
rcc.cr.modify(|_, w| w.hsion().set_bit());
while rcc.cr.read().hsirdy().bit_is_clear() {}
}
}
#[cfg(not(any(feature = "g0", feature = "g4")))]
PllSrc::Msi(_) => {
if let StopWuck::Hsi = self.stop_wuck {
rcc.cr.modify(|_, w| w.msion().set_bit());
while rcc.cr.read().msirdy().bit_is_clear() {}
}
}
PllSrc::None => (),
}
rcc.cr.modify(|_, w| w.pllon().clear_bit());
while rcc.cr.read().pllrdy().bit_is_set() {}
rcc.cfgr
.modify(|_, w| unsafe { w.sw().bits(self.input_src.bits()) });
rcc.cr.modify(|_, w| w.pllon().set_bit());
while rcc.cr.read().pllrdy().bit_is_clear() {}
}
InputSrc::Hsi => {
{
#[cfg(not(any(feature = "g0", feature = "g4")))]
if let StopWuck::Msi = self.stop_wuck {
rcc.cr.modify(|_, w| w.hsion().set_bit());
while rcc.cr.read().hsirdy().bit_is_clear() {}
rcc.cfgr
.modify(|_, w| unsafe { w.sw().bits(self.input_src.bits()) });
}
}
}
#[cfg(not(any(feature = "g0", feature = "g4")))]
InputSrc::Msi(_) => {
if let StopWuck::Hsi = self.stop_wuck {
rcc.cr.modify(|_, w| w.msion().set_bit());
while rcc.cr.read().msirdy().bit_is_clear() {}
rcc.cfgr
.modify(|_, w| unsafe { w.sw().bits(self.input_src.bits()) });
}
}
#[cfg(feature = "g0")]
InputSrc::Lsi => {
rcc.csr.modify(|_, w| w.lsion().set_bit());
while rcc.csr.read().lsirdy().bit_is_clear() {}
rcc.cfgr
.modify(|_, w| unsafe { w.sw().bits(self.input_src.bits()) });
}
#[cfg(feature = "g0")]
InputSrc::Lse => {
rcc.bdcr.modify(|_, w| w.lseon().set_bit());
while rcc.bdcr.read().lserdy().bit_is_clear() {}
rcc.cfgr
.modify(|_, w| unsafe { w.sw().bits(self.input_src.bits()) });
}
}
}
#[cfg(any(feature = "l4", feature = "l5"))]
pub fn change_msi_speed(&mut self, range: MsiRange, rcc: &mut RCC) {
match self.input_src {
InputSrc::Msi(_) => (),
_ => panic!("Only change MSI speed using this function if MSI is the input source."),
}
while rcc.cr.read().msirdy().bit_is_clear() {}
rcc.cr
.modify(|_, w| unsafe { w.msirange().bits(range as u8).msirgsel().set_bit() });
self.input_src = InputSrc::Msi(range);
}
#[cfg(any(feature = "l4", feature = "l5"))]
pub fn enable_msi_48(&self, rcc: &mut RCC) {
if let InputSrc::Msi(_) = self.input_src {
panic!(
"Only use this function to set up MSI as 48MHz oscillator\
if not using it as the input source."
);
}
if let InputSrc::Pll(pll_src) = self.input_src {
if let PllSrc::Msi(_) = pll_src {
panic!(
"Only use this function to set up MSI as 48MHz oscillator \
if not using it as the input source."
);
}
panic!(
"Only use this function to set up MSI as 48MHz oscillator \
if not using it as the input source."
);
}
rcc.cr.modify(|_, w| w.msion().clear_bit());
while rcc.cr.read().msirdy().bit_is_set() {}
rcc.cr.modify(|_, w| unsafe {
w.msirange()
.bits(MsiRange::R48M as u8)
.msirgsel()
.set_bit()
.msion()
.set_bit()
});
while rcc.cr.read().msirdy().bit_is_clear() {}
}
}
impl ClockCfg for Clocks {
fn sysclk(&self) -> u32 {
let (_, sysclk) = calc_sysclock(self.input_src, self.pllm, self.plln, self.pllr);
sysclk
}
fn hclk(&self) -> u32 {
self.sysclk() / self.hclk_prescaler.value() as u32
}
fn systick(&self) -> u32 {
self.hclk()
}
cfg_if! {
if #[cfg(feature = "g0")] {
fn usb(&self) -> u32 {
unimplemented!("No USB on G0");
}
} else if #[cfg(feature = "g4")] {
fn usb(&self) -> u32 {
48_000_000
}
} else {
fn usb(&self) -> u32 {
match self.clk48_src {
Clk48Src::Hsi48 => 48_000_000,
Clk48Src::PllSai1 => unimplemented!(),
Clk48Src::Pllq => unimplemented!(),
Clk48Src::Msi => unimplemented!(),
}
}
}
}
fn apb1(&self) -> u32 {
self.hclk() / self.apb1_prescaler.value() as u32
}
fn apb1_timer(&self) -> u32 {
if let ApbPrescaler::Div1 = self.apb1_prescaler {
self.apb1()
} else {
self.apb1() * 2
}
}
cfg_if! {
if #[cfg(feature = "g0")] {
fn apb2(&self) -> u32 {
unimplemented!("No apb2 on G0");
}
fn apb2_timer(&self) -> u32 {
unimplemented!("No apb2 on G0");
}
} else {
fn apb2(&self) -> u32 {
self.hclk() / self.apb2_prescaler.value() as u32
}
fn apb2_timer(&self) -> u32 {
if let ApbPrescaler::Div1 = self.apb2_prescaler {
self.apb2()
} else {
self.apb2() * 2
}
}
}
}
fn validate_speeds(&self) -> ClocksValid {
let mut result = ClocksValid::Valid;
#[cfg(feature = "l4")]
let max_clock = 80_000_000;
#[cfg(feature = "l5")]
let max_clock = 110_000_000;
#[cfg(feature = "g0")]
let max_clock = 64_000_000;
#[cfg(feature = "g4")]
let max_clock = 170_000_000;
#[cfg(any(feature = "l4", feature = "l5"))]
if self.plln < 7
|| self.plln > 86
|| self.pll_sai1_mul < 7
|| self.pll_sai1_mul > 86
|| self.pll_sai2_mul < 7
|| self.pll_sai2_mul > 86
{
return ClocksValid::NotValid;
}
#[cfg(feature = "g0")]
if self.plln < 9 || self.plln > 86 {
return ClocksValid::NotValid;
}
#[cfg(feature = "g4")]
if self.plln < 8 || self.plln > 127 {
return ClocksValid::NotValid;
}
if self.sysclk() > max_clock {
result = ClocksValid::NotValid;
}
if self.hclk() > max_clock {
result = ClocksValid::NotValid;
}
if self.apb1() > max_clock {
result = ClocksValid::NotValid;
}
#[cfg(not(feature = "g0"))]
if self.apb2() > max_clock {
result = ClocksValid::NotValid;
}
result
}
}
impl Default for Clocks {
fn default() -> Self {
Self {
input_src: InputSrc::Pll(PllSrc::Hsi),
pllm: Pllm::Div2,
#[cfg(feature = "l4")]
plln: 20,
#[cfg(feature = "l5")]
plln: 27,
#[cfg(feature = "g0")]
plln: 16,
#[cfg(feature = "g4")]
plln: 42,
#[cfg(not(any(feature = "g0", feature = "g4")))]
pll_sai1_mul: 8,
#[cfg(not(any(feature = "g0", feature = "g4")))]
pll_sai2_mul: 8,
pllr: Pllr::Div2,
hclk_prescaler: HclkPrescaler::Div1,
apb1_prescaler: ApbPrescaler::Div1,
#[cfg(not(feature = "g0"))]
apb2_prescaler: ApbPrescaler::Div1,
#[cfg(any(feature = "l4", feature = "l5"))]
clk48_src: Clk48Src::Msi,
#[cfg(feature = "g4")]
clk48_src: Clk48Src::Hsi48,
#[cfg(not(any(feature = "g0", feature = "g4")))]
sai1_enabled: false,
#[cfg(not(any(feature = "g0", feature = "g4")))]
sai2_enabled: false,
hse_bypass: false,
security_system: false,
#[cfg(not(feature = "g0"))]
hsi48_on: false,
#[cfg(any(feature = "l4", feature = "l5"))]
stop_wuck: StopWuck::Msi,
}
}
}
fn calc_sysclock(input_src: InputSrc, pllm: Pllm, plln: u8, pllr: Pllr) -> (u32, u32) {
let input_freq;
let sysclk = match input_src {
InputSrc::Pll(pll_src) => {
input_freq = match pll_src {
#[cfg(not(any(feature = "g0", feature = "g4")))]
PllSrc::Msi(range) => range.value() as u32,
PllSrc::Hsi => 16_000_000,
PllSrc::Hse(freq) => freq,
PllSrc::None => 0,
};
input_freq / pllm.value() as u32 * plln as u32 / pllr.value() as u32
}
#[cfg(not(any(feature = "g0", feature = "g4")))]
InputSrc::Msi(range) => {
input_freq = range.value() as u32;
input_freq
}
InputSrc::Hsi => {
input_freq = 16_000_000;
input_freq
}
InputSrc::Hse(freq) => {
input_freq = freq;
input_freq
}
#[cfg(feature = "g0")]
InputSrc::Lsi => {
input_freq = 32_000;
input_freq
}
#[cfg(feature = "g0")]
InputSrc::Lse => {
input_freq = 32_768;
input_freq
}
};
(input_freq, sysclk)
}