embassy_stm32/rcc/
mco.rs

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    /// Create a new MCO instance.
94    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}