py32_hal/rcc/
mco.rs

1// The following code is modified from embassy-stm32
2// https://github.com/embassy-rs/embassy/tree/main/embassy-stm32
3// Special thanks to the Embassy Project and its contributors for their work!
4
5use core::marker::PhantomData;
6
7use embassy_hal_internal::into_ref;
8
9use crate::gpio::{AfType, OutputType, Speed};
10pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
11pub use crate::pac::rcc::vals::Mcosel as McoSource;
12use crate::pac::RCC;
13use crate::{peripherals, Peripheral};
14
15pub(crate) trait SealedMcoInstance {}
16
17#[allow(private_bounds)]
18pub trait McoInstance: SealedMcoInstance + 'static {
19    type Source;
20
21    #[doc(hidden)]
22    unsafe fn _apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler);
23}
24
25pin_trait!(McoPin, McoInstance);
26
27macro_rules! impl_peri {
28    ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => {
29        impl SealedMcoInstance for peripherals::$peri {}
30        impl McoInstance for peripherals::$peri {
31            type Source = $source;
32
33            unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) {
34                RCC.cfgr().modify(|w| {
35                    w.$set_source(source);
36                    w.$set_prescaler(_prescaler);
37                });
38            }
39        }
40    };
41}
42
43#[cfg(mco)]
44impl_peri!(MCO, McoSource, set_mcosel, set_mcopre);
45
46pub struct Mco<'d, T: McoInstance> {
47    phantom: PhantomData<&'d mut T>,
48}
49
50impl<'d, T: McoInstance> Mco<'d, T> {
51    /// Create a new MCO instance.
52    pub fn new(
53        _peri: impl Peripheral<P = T> + 'd,
54        pin: impl Peripheral<P = impl McoPin<T>> + 'd,
55        source: T::Source,
56        prescaler: McoPrescaler,
57    ) -> Self {
58        into_ref!(pin);
59
60        critical_section::with(|_| unsafe {
61            T::_apply_clock_settings(source, prescaler);
62            pin.set_as_af(
63                pin.af_num(),
64                AfType::output(OutputType::PushPull, Speed::VeryHigh),
65            );
66        });
67
68        Self {
69            phantom: PhantomData,
70        }
71    }
72}