stm32: implement MCO for all chips.
This commit is contained in:
@ -1,16 +1,8 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use embassy_hal_internal::into_ref;
|
||||
use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre};
|
||||
|
||||
use crate::gpio::sealed::AFType;
|
||||
use crate::gpio::Speed;
|
||||
use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
|
||||
use crate::pac::{FLASH, PWR, RCC};
|
||||
use crate::rcc::bd::{BackupDomain, RtcClockSource};
|
||||
use crate::rcc::{set_freqs, Clocks};
|
||||
use crate::time::Hertz;
|
||||
use crate::{peripherals, Peripheral};
|
||||
|
||||
/// HSI speed
|
||||
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
||||
@ -197,164 +189,6 @@ fn setup_pll(
|
||||
}
|
||||
}
|
||||
|
||||
pub enum McoClock {
|
||||
DIV1,
|
||||
DIV2,
|
||||
DIV3,
|
||||
DIV4,
|
||||
DIV5,
|
||||
}
|
||||
|
||||
impl McoClock {
|
||||
fn into_raw(&self) -> Mcopre {
|
||||
match self {
|
||||
McoClock::DIV1 => Mcopre::DIV1,
|
||||
McoClock::DIV2 => Mcopre::DIV2,
|
||||
McoClock::DIV3 => Mcopre::DIV3,
|
||||
McoClock::DIV4 => Mcopre::DIV4,
|
||||
McoClock::DIV5 => Mcopre::DIV5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Mco1Source {
|
||||
Hsi,
|
||||
Lse,
|
||||
Hse,
|
||||
Pll,
|
||||
}
|
||||
|
||||
impl Default for Mco1Source {
|
||||
fn default() -> Self {
|
||||
Self::Hsi
|
||||
}
|
||||
}
|
||||
|
||||
pub trait McoSource {
|
||||
type Raw;
|
||||
|
||||
fn into_raw(&self) -> Self::Raw;
|
||||
}
|
||||
|
||||
impl McoSource for Mco1Source {
|
||||
type Raw = Mco1;
|
||||
fn into_raw(&self) -> Self::Raw {
|
||||
match self {
|
||||
Mco1Source::Hsi => Mco1::HSI,
|
||||
Mco1Source::Lse => Mco1::LSE,
|
||||
Mco1Source::Hse => Mco1::HSE,
|
||||
Mco1Source::Pll => Mco1::PLL,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Mco2Source {
|
||||
SysClk,
|
||||
Plli2s,
|
||||
Hse,
|
||||
Pll,
|
||||
}
|
||||
|
||||
impl Default for Mco2Source {
|
||||
fn default() -> Self {
|
||||
Self::SysClk
|
||||
}
|
||||
}
|
||||
|
||||
impl McoSource for Mco2Source {
|
||||
type Raw = Mco2;
|
||||
fn into_raw(&self) -> Self::Raw {
|
||||
match self {
|
||||
Mco2Source::SysClk => Mco2::SYSCLK,
|
||||
Mco2Source::Plli2s => Mco2::PLLI2S,
|
||||
Mco2Source::Hse => Mco2::HSE,
|
||||
Mco2Source::Pll => Mco2::PLL,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
use stm32_metapac::rcc::vals::Mcopre;
|
||||
pub trait McoInstance {
|
||||
type Source;
|
||||
unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait McoInstance: sealed::McoInstance + 'static {}
|
||||
|
||||
pin_trait!(McoPin, McoInstance);
|
||||
|
||||
impl sealed::McoInstance for peripherals::MCO1 {
|
||||
type Source = Mco1;
|
||||
unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) {
|
||||
RCC.cfgr().modify(|w| {
|
||||
w.set_mco1(source);
|
||||
w.set_mco1pre(prescaler);
|
||||
});
|
||||
match source {
|
||||
Mco1::PLL => {
|
||||
RCC.cr().modify(|w| w.set_pllon(true));
|
||||
while !RCC.cr().read().pllrdy() {}
|
||||
}
|
||||
Mco1::HSI => {
|
||||
RCC.cr().modify(|w| w.set_hsion(true));
|
||||
while !RCC.cr().read().hsirdy() {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl McoInstance for peripherals::MCO1 {}
|
||||
|
||||
impl sealed::McoInstance for peripherals::MCO2 {
|
||||
type Source = Mco2;
|
||||
unsafe fn apply_clock_settings(source: Self::Source, prescaler: Mcopre) {
|
||||
RCC.cfgr().modify(|w| {
|
||||
w.set_mco2(source);
|
||||
w.set_mco2pre(prescaler);
|
||||
});
|
||||
match source {
|
||||
Mco2::PLL => {
|
||||
RCC.cr().modify(|w| w.set_pllon(true));
|
||||
while !RCC.cr().read().pllrdy() {}
|
||||
}
|
||||
#[cfg(not(stm32f410))]
|
||||
Mco2::PLLI2S => {
|
||||
RCC.cr().modify(|w| w.set_plli2son(true));
|
||||
while !RCC.cr().read().plli2srdy() {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl McoInstance for peripherals::MCO2 {}
|
||||
|
||||
pub struct Mco<'d, T: McoInstance> {
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
}
|
||||
|
||||
impl<'d, T: McoInstance> Mco<'d, T> {
|
||||
pub fn new(
|
||||
_peri: impl Peripheral<P = T> + 'd,
|
||||
pin: impl Peripheral<P = impl McoPin<T>> + 'd,
|
||||
source: impl McoSource<Raw = T::Source>,
|
||||
prescaler: McoClock,
|
||||
) -> Self {
|
||||
into_ref!(pin);
|
||||
|
||||
critical_section::with(|_| unsafe {
|
||||
T::apply_clock_settings(source.into_raw(), prescaler.into_raw());
|
||||
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
|
||||
pin.set_speed(Speed::VeryHigh);
|
||||
});
|
||||
|
||||
Self { phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
fn flash_setup(sysclk: u32) {
|
||||
use crate::pac::flash::vals::Latency;
|
||||
|
||||
|
Reference in New Issue
Block a user