stm32/rcc: use more PLL etc enums from PAC.
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
#[cfg(rcc_f3)]
|
||||
use crate::pac::adccommon::vals::Ckmode;
|
||||
use crate::pac::flash::vals::Latency;
|
||||
use crate::pac::rcc::vals::{Adcpres, Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
|
||||
pub use crate::pac::rcc::vals::Adcpres;
|
||||
use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
|
||||
use crate::pac::{FLASH, RCC};
|
||||
use crate::rcc::{set_freqs, Clocks};
|
||||
use crate::time::Hertz;
|
||||
@ -12,25 +13,6 @@ pub const HSI_FREQ: Hertz = Hertz(8_000_000);
|
||||
/// LSI speed
|
||||
pub const LSI_FREQ: Hertz = Hertz(40_000);
|
||||
|
||||
impl From<AdcClockSource> for Adcpres {
|
||||
fn from(value: AdcClockSource) -> Self {
|
||||
match value {
|
||||
AdcClockSource::PllDiv1 => Adcpres::DIV1,
|
||||
AdcClockSource::PllDiv2 => Adcpres::DIV2,
|
||||
AdcClockSource::PllDiv4 => Adcpres::DIV4,
|
||||
AdcClockSource::PllDiv6 => Adcpres::DIV6,
|
||||
AdcClockSource::PllDiv8 => Adcpres::DIV8,
|
||||
AdcClockSource::PllDiv12 => Adcpres::DIV12,
|
||||
AdcClockSource::PllDiv16 => Adcpres::DIV16,
|
||||
AdcClockSource::PllDiv32 => Adcpres::DIV32,
|
||||
AdcClockSource::PllDiv64 => Adcpres::DIV64,
|
||||
AdcClockSource::PllDiv128 => Adcpres::DIV128,
|
||||
AdcClockSource::PllDiv256 => Adcpres::DIV256,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(rcc_f3)]
|
||||
impl From<AdcClockSource> for Ckmode {
|
||||
fn from(value: AdcClockSource) -> Self {
|
||||
@ -45,32 +27,13 @@ impl From<AdcClockSource> for Ckmode {
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum AdcClockSource {
|
||||
PllDiv1 = 1,
|
||||
PllDiv2 = 2,
|
||||
PllDiv4 = 4,
|
||||
PllDiv6 = 6,
|
||||
PllDiv8 = 8,
|
||||
PllDiv12 = 12,
|
||||
PllDiv16 = 16,
|
||||
PllDiv32 = 32,
|
||||
PllDiv64 = 64,
|
||||
PllDiv128 = 128,
|
||||
PllDiv256 = 256,
|
||||
Pll(Adcpres),
|
||||
BusDiv1,
|
||||
BusDiv2,
|
||||
BusDiv4,
|
||||
}
|
||||
|
||||
impl AdcClockSource {
|
||||
pub fn is_bus(&self) -> bool {
|
||||
match self {
|
||||
Self::BusDiv1 => true,
|
||||
Self::BusDiv2 => true,
|
||||
Self::BusDiv4 => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bus_div(&self) -> u32 {
|
||||
match self {
|
||||
Self::BusDiv1 => 1,
|
||||
@ -137,67 +100,67 @@ struct PllConfig {
|
||||
/// Initialize and Set the clock frequencies
|
||||
pub(crate) unsafe fn init(config: Config) {
|
||||
// Calculate the real System clock, and PLL configuration if applicable
|
||||
let (Hertz(sysclk), pll_config) = get_sysclk(&config);
|
||||
assert!(sysclk <= 72_000_000);
|
||||
let (sysclk, pll_config) = get_sysclk(&config);
|
||||
assert!(sysclk.0 <= 72_000_000);
|
||||
|
||||
// Calculate real AHB clock
|
||||
let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk);
|
||||
let (hpre_bits, hpre_div) = match sysclk / hclk {
|
||||
let hclk = config.hclk.map(|h| h).unwrap_or(sysclk);
|
||||
let hpre = match sysclk.0 / hclk.0 {
|
||||
0 => unreachable!(),
|
||||
1 => (Hpre::DIV1, 1),
|
||||
2 => (Hpre::DIV2, 2),
|
||||
3..=5 => (Hpre::DIV4, 4),
|
||||
6..=11 => (Hpre::DIV8, 8),
|
||||
12..=39 => (Hpre::DIV16, 16),
|
||||
40..=95 => (Hpre::DIV64, 64),
|
||||
96..=191 => (Hpre::DIV128, 128),
|
||||
192..=383 => (Hpre::DIV256, 256),
|
||||
_ => (Hpre::DIV512, 512),
|
||||
1 => Hpre::DIV1,
|
||||
2 => Hpre::DIV2,
|
||||
3..=5 => Hpre::DIV4,
|
||||
6..=11 => Hpre::DIV8,
|
||||
12..=39 => Hpre::DIV16,
|
||||
40..=95 => Hpre::DIV64,
|
||||
96..=191 => Hpre::DIV128,
|
||||
192..=383 => Hpre::DIV256,
|
||||
_ => Hpre::DIV512,
|
||||
};
|
||||
let hclk = sysclk / hpre_div;
|
||||
assert!(hclk <= 72_000_000);
|
||||
let hclk = sysclk / hpre;
|
||||
assert!(hclk <= Hertz(72_000_000));
|
||||
|
||||
// Calculate real APB1 clock
|
||||
let pclk1 = config.pclk1.map(|p| p.0).unwrap_or(hclk);
|
||||
let (ppre1_bits, ppre1) = match hclk / pclk1 {
|
||||
let pclk1 = config.pclk1.unwrap_or(hclk);
|
||||
let ppre1 = match hclk / pclk1 {
|
||||
0 => unreachable!(),
|
||||
1 => (Ppre::DIV1, 1),
|
||||
2 => (Ppre::DIV2, 2),
|
||||
3..=5 => (Ppre::DIV4, 4),
|
||||
6..=11 => (Ppre::DIV8, 8),
|
||||
_ => (Ppre::DIV16, 16),
|
||||
1 => Ppre::DIV1,
|
||||
2 => Ppre::DIV2,
|
||||
3..=5 => Ppre::DIV4,
|
||||
6..=11 => Ppre::DIV8,
|
||||
_ => Ppre::DIV16,
|
||||
};
|
||||
let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
|
||||
let timer_mul1 = if ppre1 == Ppre::DIV1 { 1u32 } else { 2 };
|
||||
let pclk1 = hclk / ppre1;
|
||||
assert!(pclk1 <= 36_000_000);
|
||||
assert!(pclk1 <= Hertz(36_000_000));
|
||||
|
||||
// Calculate real APB2 clock
|
||||
let pclk2 = config.pclk2.map(|p| p.0).unwrap_or(hclk);
|
||||
let (ppre2_bits, ppre2) = match hclk / pclk2 {
|
||||
let pclk2 = config.pclk2.unwrap_or(hclk);
|
||||
let ppre2 = match hclk / pclk2 {
|
||||
0 => unreachable!(),
|
||||
1 => (Ppre::DIV1, 1),
|
||||
2 => (Ppre::DIV2, 2),
|
||||
3..=5 => (Ppre::DIV4, 4),
|
||||
6..=11 => (Ppre::DIV8, 8),
|
||||
_ => (Ppre::DIV16, 16),
|
||||
1 => Ppre::DIV1,
|
||||
2 => Ppre::DIV2,
|
||||
3..=5 => Ppre::DIV4,
|
||||
6..=11 => Ppre::DIV8,
|
||||
_ => Ppre::DIV16,
|
||||
};
|
||||
let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
|
||||
let timer_mul2 = if ppre2 == Ppre::DIV1 { 1u32 } else { 2 };
|
||||
let pclk2 = hclk / ppre2;
|
||||
assert!(pclk2 <= 72_000_000);
|
||||
assert!(pclk2 <= Hertz(72_000_000));
|
||||
|
||||
// Set latency based on HCLK frquency
|
||||
// RM0316: "The prefetch buffer must be kept on when using a prescaler
|
||||
// different from 1 on the AHB clock.", "Half-cycle access cannot be
|
||||
// used when there is a prescaler different from 1 on the AHB clock"
|
||||
FLASH.acr().modify(|w| {
|
||||
w.set_latency(if hclk <= 24_000_000 {
|
||||
w.set_latency(if hclk <= Hertz(24_000_000) {
|
||||
Latency::WS0
|
||||
} else if hclk <= 48_000_000 {
|
||||
} else if hclk <= Hertz(48_000_000) {
|
||||
Latency::WS1
|
||||
} else {
|
||||
Latency::WS2
|
||||
});
|
||||
if hpre_div != 1 {
|
||||
if hpre != Hpre::DIV1 {
|
||||
w.set_hlfcya(false);
|
||||
w.set_prftbe(true);
|
||||
}
|
||||
@ -240,9 +203,9 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
// Set prescalers
|
||||
// CFGR has been written before (PLL, PLL48) don't overwrite these settings
|
||||
RCC.cfgr().modify(|w| {
|
||||
w.set_ppre2(ppre2_bits);
|
||||
w.set_ppre1(ppre1_bits);
|
||||
w.set_hpre(hpre_bits);
|
||||
w.set_ppre2(ppre2);
|
||||
w.set_ppre1(ppre1);
|
||||
w.set_hpre(hpre);
|
||||
});
|
||||
|
||||
// Wait for the new prescalers to kick in
|
||||
@ -260,45 +223,43 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
});
|
||||
|
||||
#[cfg(rcc_f3)]
|
||||
let adc = config.adc.map(|adc| {
|
||||
if !adc.is_bus() {
|
||||
let adc = config.adc.map(|adc| match adc {
|
||||
AdcClockSource::Pll(adcpres) => {
|
||||
RCC.cfgr2().modify(|w| {
|
||||
// Make sure that we're using the PLL
|
||||
pll_config.unwrap();
|
||||
w.set_adc12pres(adc.into());
|
||||
w.set_adc12pres(adcpres);
|
||||
|
||||
Hertz(sysclk / adc as u32)
|
||||
})
|
||||
} else {
|
||||
crate::pac::ADC_COMMON.ccr().modify(|w| {
|
||||
assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1));
|
||||
|
||||
w.set_ckmode(adc.into());
|
||||
|
||||
Hertz(sysclk / adc.bus_div() as u32)
|
||||
sysclk / adcpres
|
||||
})
|
||||
}
|
||||
_ => crate::pac::ADC_COMMON.ccr().modify(|w| {
|
||||
assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1));
|
||||
|
||||
w.set_ckmode(adc.into());
|
||||
|
||||
sysclk / adc.bus_div()
|
||||
}),
|
||||
});
|
||||
|
||||
#[cfg(all(rcc_f3, adc3_common))]
|
||||
let adc34 = config.adc.map(|adc| {
|
||||
if !adc.is_bus() {
|
||||
let adc34 = config.adc34.map(|adc| match adc {
|
||||
AdcClockSource::Pll(adcpres) => {
|
||||
RCC.cfgr2().modify(|w| {
|
||||
// Make sure that we're using the PLL
|
||||
pll_config.unwrap();
|
||||
w.set_adc12pres(adc.into());
|
||||
w.set_adc34pres(adcpres);
|
||||
|
||||
Hertz(sysclk / adc as u32)
|
||||
})
|
||||
} else {
|
||||
crate::pac::ADC3_COMMON.ccr().modify(|w| {
|
||||
assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1));
|
||||
|
||||
w.set_ckmode(adc.into());
|
||||
|
||||
Hertz(sysclk / adc.bus_div() as u32)
|
||||
sysclk / adcpres
|
||||
})
|
||||
}
|
||||
_ => crate::pac::ADC_COMMON.ccr().modify(|w| {
|
||||
assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1));
|
||||
|
||||
w.set_ckmode(adc.into());
|
||||
|
||||
sysclk / adc.bus_div()
|
||||
}),
|
||||
});
|
||||
|
||||
#[cfg(stm32f334)]
|
||||
@ -310,21 +271,21 @@ pub(crate) unsafe fn init(config: Config) {
|
||||
|
||||
// Make sure that we're using the PLL
|
||||
pll_config.unwrap();
|
||||
assert!((pclk2 == sysclk) || (pclk2 * 2 == sysclk));
|
||||
assert!((pclk2 == sysclk) || (pclk2 * 2u32 == sysclk));
|
||||
|
||||
RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL));
|
||||
|
||||
Some(Hertz(sysclk * 2))
|
||||
Some(sysclk * 2u32)
|
||||
}
|
||||
};
|
||||
|
||||
set_freqs(Clocks {
|
||||
sys: Hertz(sysclk),
|
||||
apb1: Hertz(pclk1),
|
||||
apb2: Hertz(pclk2),
|
||||
apb1_tim: Hertz(pclk1 * timer_mul1),
|
||||
apb2_tim: Hertz(pclk2 * timer_mul2),
|
||||
ahb1: Hertz(hclk),
|
||||
sys: sysclk,
|
||||
apb1: pclk1,
|
||||
apb2: pclk2,
|
||||
apb1_tim: pclk1 * timer_mul1,
|
||||
apb2_tim: pclk2 * timer_mul2,
|
||||
ahb1: hclk,
|
||||
#[cfg(rcc_f3)]
|
||||
adc: adc,
|
||||
#[cfg(all(rcc_f3, adc3_common))]
|
||||
@ -421,16 +382,16 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
|
||||
|
||||
#[inline]
|
||||
#[allow(unused_variables)]
|
||||
fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre {
|
||||
fn get_usb_pre(config: &Config, sysclk: Hertz, pclk1: Hertz, pll_config: &Option<PllConfig>) -> Usbpre {
|
||||
cfg_if::cfg_if! {
|
||||
// Some chips do not have USB
|
||||
if #[cfg(any(stm32f301, stm32f318, stm32f334))] {
|
||||
panic!("USB clock not supported by the chip");
|
||||
} else {
|
||||
let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= 10_000_000);
|
||||
let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= Hertz(10_000_000));
|
||||
match (usb_ok, sysclk) {
|
||||
(true, 72_000_000) => Usbpre::DIV1_5,
|
||||
(true, 48_000_000) => Usbpre::DIV1,
|
||||
(true, Hertz(72_000_000)) => Usbpre::DIV1_5,
|
||||
(true, Hertz(48_000_000)) => Usbpre::DIV1,
|
||||
_ => panic!(
|
||||
"USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz"
|
||||
),
|
||||
|
Reference in New Issue
Block a user