1use core::marker::PhantomData;
2
3use embassy_hal_internal::into_ref;
4
5use crate::gpio::{AfType, OutputType, Speed};
6#[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))]
7pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
8#[cfg(not(any(
9 rcc_f2,
10 rcc_f410,
11 rcc_f4,
12 rcc_f7,
13 rcc_h50,
14 rcc_h5,
15 rcc_h7ab,
16 rcc_h7rm0433,
17 rcc_h7,
18 rcc_h7rs
19)))]
20pub use crate::pac::rcc::vals::Mcosel as McoSource;
21#[cfg(any(
22 rcc_f2,
23 rcc_f410,
24 rcc_f4,
25 rcc_f7,
26 rcc_h50,
27 rcc_h5,
28 rcc_h7ab,
29 rcc_h7rm0433,
30 rcc_h7,
31 rcc_h7rs
32))]
33pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source};
34use crate::pac::RCC;
35use crate::{peripherals, Peripheral};
36
37#[cfg(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37))]
38#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
39pub enum McoPrescaler {
40 DIV1,
41}
42
43pub(crate) trait SealedMcoInstance {}
44
45#[allow(private_bounds)]
46pub trait McoInstance: SealedMcoInstance + 'static {
47 type Source;
48
49 #[doc(hidden)]
50 unsafe fn _apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler);
51}
52
53pin_trait!(McoPin, McoInstance);
54
55macro_rules! impl_peri {
56 ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => {
57 impl SealedMcoInstance for peripherals::$peri {}
58 impl McoInstance for peripherals::$peri {
59 type Source = $source;
60
61 unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) {
62 #[cfg(not(any(stm32u5, stm32wba)))]
63 let r = RCC.cfgr();
64 #[cfg(any(stm32u5, stm32wba))]
65 let r = RCC.cfgr1();
66
67 r.modify(|w| {
68 w.$set_source(source);
69 #[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))]
70 w.$set_prescaler(_prescaler);
71 });
72 }
73 }
74 };
75}
76
77#[cfg(any(rcc_c0, rcc_g0, rcc_u0))]
78#[allow(unused_imports)]
79use self::{McoSource as Mco1Source, McoSource as Mco2Source};
80
81#[cfg(mco)]
82impl_peri!(MCO, McoSource, set_mcosel, set_mcopre);
83#[cfg(mco1)]
84impl_peri!(MCO1, Mco1Source, set_mco1sel, set_mco1pre);
85#[cfg(mco2)]
86impl_peri!(MCO2, Mco2Source, set_mco2sel, set_mco2pre);
87
88pub struct Mco<'d, T: McoInstance> {
89 phantom: PhantomData<&'d mut T>,
90}
91
92impl<'d, T: McoInstance> Mco<'d, T> {
93 pub fn new(
95 _peri: impl Peripheral<P = T> + 'd,
96 pin: impl Peripheral<P = impl McoPin<T>> + 'd,
97 source: T::Source,
98 prescaler: McoPrescaler,
99 ) -> Self {
100 into_ref!(pin);
101
102 critical_section::with(|_| unsafe {
103 T::_apply_clock_settings(source, prescaler);
104 pin.set_as_af(pin.af_num(), AfType::output(OutputType::PushPull, Speed::VeryHigh));
105 });
106
107 Self { phantom: PhantomData }
108 }
109}