1use 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 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}