use crate::{
pac::{FLASH, RCC},
rcc,
time::U32Ext,
};
pub struct SpeedError {}
#[derive(Clone, Debug)]
pub struct Speeds {
sysclk: f32,
hclk: f32,
systick: f32,
fclk: f32,
pclk1: f32,
timer1: f32,
pclk2: f32,
timer2: f32,
usb: f32,
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Validation {
Valid,
NotValid,
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum PllSrc {
HsiDiv2 = 0b00,
Hsi = 0b01,
Hse = 0b10,
}
#[derive(Clone)]
pub enum InputSrc {
Hsi,
Hse,
Pll(PllSrc),
}
impl InputSrc {
pub fn bits(&self) -> u8 {
match self {
Self::Hsi => 0b00,
Self::Hse => 0b01,
Self::Pll(_) => 0b10,
}
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum Prediv {
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 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,
Self::Div9 => 9,
Self::Div10 => 10,
Self::Div11 => 11,
Self::Div12 => 12,
Self::Div13 => 13,
Self::Div14 => 14,
Self::Div15 => 15,
Self::Div16 => 16,
}
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum PllMul {
Mul2 = 0b0000,
Mul3 = 0b0001,
Mul4 = 0b0010,
Mul5 = 0b0011,
Mul6 = 0b0100,
Mul7 = 0b0101,
Mul8 = 0b0110,
Mul9 = 0b0111,
Mul10 = 0b1000,
Mul11 = 0b1001,
Mul12 = 0b1010,
Mul13 = 0b1011,
Mul14 = 0b1100,
Mul15 = 0b1101,
Mul16 = 0b1110,
}
impl PllMul {
pub fn value(&self) -> u8 {
match self {
Self::Mul2 => 2,
Self::Mul3 => 3,
Self::Mul4 => 4,
Self::Mul5 => 5,
Self::Mul6 => 6,
Self::Mul7 => 7,
Self::Mul8 => 8,
Self::Mul9 => 9,
Self::Mul10 => 10,
Self::Mul11 => 11,
Self::Mul12 => 12,
Self::Mul13 => 13,
Self::Mul14 => 14,
Self::Mul15 => 15,
Self::Mul16 => 16,
}
}
}
#[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,
}
}
}
#[derive(Clone, Copy)]
#[repr(u8)]
pub enum UsbPrescaler {
Div1_5 = 0,
Div1 = 1,
}
impl UsbPrescaler {
pub fn bit(&self) -> bool {
match self {
Self::Div1_5 => false,
Self::Div1 => true,
}
}
pub fn value(&self) -> f32 {
match self {
Self::Div1_5 => 1.5,
Self::Div1 => 1.,
}
}
}
pub struct Clocks {
pub input_freq: u8,
pub input_src: InputSrc,
pub prediv: Prediv,
pub pll_mul: PllMul,
pub usb_pre: UsbPrescaler,
pub hclk_prescaler: HclkPrescaler,
pub apb1_prescaler: ApbPrescaler,
pub apb2_prescaler: ApbPrescaler,
pub hse_bypass: bool,
pub security_system: bool,
}
impl Clocks {
pub fn setup(&self, rcc: &mut RCC, flash: &mut FLASH) -> Result<(), SpeedError> {
if let Validation::NotValid = self.validate() {
return Err(SpeedError {});
}
match self.input_src {
InputSrc::Hse => {
rcc.cr.modify(|_, w| w.hseon().bit(true));
while rcc.cr.read().hserdy().is_not_ready() {}
}
InputSrc::Hsi => (),
InputSrc::Pll(pll_src) => {
if let PllSrc::Hse = pll_src {
rcc.cr.modify(|_, w| w.hseon().bit(true));
while rcc.cr.read().hserdy().is_not_ready() {}
}
}
}
rcc.cr.modify(|_, w| {
w.hsebyp().bit(self.hse_bypass);
w.pllon().off()
});
if let InputSrc::Pll(pll_src) = self.input_src {
rcc.cr.modify(|_, w| w.pllon().off());
while rcc.cr.read().pllrdy().is_ready() {}
rcc.cfgr.modify(|_, w| {
w.pllmul().bits(self.pll_mul as u8);
unsafe { w.pllsrc().bits(pll_src as u8) }
});
rcc.cfgr2.modify(|_, w| w.prediv().bits(self.prediv as u8));
rcc.cr.modify(|_, w| w.pllon().on());
while rcc.cr.read().pllrdy().is_not_ready() {}
}
rcc.cfgr.modify(|_, w| {
w.usbpre().bit(self.usb_pre.bit());
unsafe { w.ppre2().bits(self.apb2_prescaler as u8) };
unsafe { w.ppre1().bits(self.apb1_prescaler as u8) };
unsafe { w.hpre().bits(self.hclk_prescaler as u8) };
unsafe { w.sw().bits(self.input_src.bits()) }
});
rcc.cr.modify(|_, w| w.csson().bit(self.security_system));
let sysclk = match self.input_src {
InputSrc::Pll(_) => self.input_freq / self.prediv.value() * self.pll_mul.value(),
_ => self.input_freq,
};
let hclk = sysclk as f32 / self.hclk_prescaler.value() as f32;
flash.acr.modify(|_, w| {
if hclk <= 24. {
w.latency().ws0()
} else if hclk <= 48. {
w.latency().ws1()
} else {
w.latency().ws2()
}
});
Ok(())
}
pub fn calc_speeds(&self) -> Speeds {
let sysclk = match self.input_src {
InputSrc::Pll(_) => {
self.input_freq as f32 / self.prediv.value() as f32 * self.pll_mul.value() as f32
}
_ => self.input_freq as f32,
};
let usb = sysclk / self.usb_pre.value() as f32;
let hclk = sysclk / self.hclk_prescaler.value() as f32;
let systick = hclk;
let fclk = hclk;
let pclk1 = hclk / self.apb1_prescaler.value() as f32;
let timer1 = pclk1;
let pclk2 = hclk / self.apb2_prescaler.value() as f32;
let timer2 = pclk2;
Speeds {
sysclk,
usb,
hclk,
systick,
fclk,
pclk1,
timer1,
pclk2,
timer2,
}
}
pub fn validate(&self) -> Validation {
validate(self.calc_speeds()).0
}
pub fn validate_usb(&self) -> Validation {
validate(self.calc_speeds()).1
}
pub fn make_rcc_clocks(&self) -> rcc::Clocks {
let speeds = self.calc_speeds();
rcc::Clocks {
hclk: (speeds.hclk as u32).mhz().into(),
pclk1: (speeds.pclk1 as u32).mhz().into(),
pclk2: (speeds.pclk2 as u32).mhz().into(),
ppre1: self.apb1_prescaler.value(),
ppre2: self.apb2_prescaler.value(),
sysclk: (speeds.sysclk as u32).mhz().into(),
usbclk_valid: true,
}
}
pub fn full_speed() -> Self {
Self {
input_freq: 8,
input_src: InputSrc::Pll(PllSrc::Hse),
prediv: Prediv::Div1,
pll_mul: PllMul::Mul9,
usb_pre: UsbPrescaler::Div1_5,
hclk_prescaler: HclkPrescaler::Div1,
apb1_prescaler: ApbPrescaler::Div2,
apb2_prescaler: ApbPrescaler::Div1,
hse_bypass: false,
security_system: false,
}
}
}
impl Default for Clocks {
fn default() -> Self {
Self {
input_freq: 8,
input_src: InputSrc::Pll(PllSrc::Hse),
prediv: Prediv::Div1,
pll_mul: PllMul::Mul6,
usb_pre: UsbPrescaler::Div1,
hclk_prescaler: HclkPrescaler::Div1,
apb1_prescaler: ApbPrescaler::Div2,
apb2_prescaler: ApbPrescaler::Div1,
hse_bypass: false,
security_system: false,
}
}
}
pub fn validate(speeds: Speeds) -> (Validation, Validation) {
let mut main = Validation::Valid;
let mut usb = Validation::Valid;
if speeds.sysclk > 72. || speeds.sysclk < 16. {
main = Validation::NotValid;
}
if speeds.hclk > 72. || speeds.sysclk < 0. {
main = Validation::NotValid;
}
if speeds.pclk1 > 36. || speeds.pclk1 < 10. {
main = Validation::NotValid;
}
if speeds.pclk2 > 72. || speeds.pclk2 < 0. {
main = Validation::NotValid;
}
if speeds.usb as u8 != 48 {
usb = Validation::NotValid;
}
(main, usb)
}