embassy_stm32/vrefbuf/
mod.rs

1//! Voltage Reference Buffer (VREFBUF)
2use core::marker::PhantomData;
3
4use embassy_hal_internal::PeripheralType;
5use stm32_metapac::vrefbuf::vals::*;
6
7use crate::Peri;
8
9/// Voltage Reference (VREFBUF) driver.
10pub struct VoltageReferenceBuffer<'d, T: Instance> {
11    vrefbuf: PhantomData<&'d mut T>,
12}
13
14#[cfg(rcc_wba)]
15fn get_refbuf_trim(voltage_scale: Vrs) -> usize {
16    match voltage_scale {
17        Vrs::VREF0 => 0x0BFA_07A8usize,
18        Vrs::VREF1 => 0x0BFA_07A9usize,
19        Vrs::VREF2 => 0x0BFA_07AAusize,
20        Vrs::VREF3 => 0x0BFA_07ABusize,
21        _ => panic!("Incorrect Vrs setting!"),
22    }
23}
24
25impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> {
26    /// Creates an VREFBUF (Voltage Reference) instance with a voltage scale and impedance mode.
27    ///
28    /// [Self] has to be started with [Self::new()].
29    pub fn new(_instance: Peri<'d, T>, voltage_scale: Vrs, impedance_mode: Hiz) -> Self {
30        #[cfg(rcc_wba)]
31        {
32            use crate::pac::RCC;
33            RCC.apb7enr().modify(|w| w.set_vrefen(true));
34            // This is an errata for WBA6 devices. VREFBUF_TRIM value isn't set correctly
35            // [Link explaining it](https://www.st.com/resource/en/errata_sheet/es0644-stm32wba6xxx-device-errata-stmicroelectronics.pdf)
36            unsafe {
37                use crate::pac::VREFBUF;
38                let addr = get_refbuf_trim(voltage_scale);
39                let buf_trim_ptr = core::ptr::with_exposed_provenance::<u32>(addr);
40                let trim_val = core::ptr::read_volatile(buf_trim_ptr);
41                VREFBUF.ccr().write(|w| w.set_trim((trim_val & 0x3F) as u8));
42            }
43        }
44        #[cfg(any(rcc_u5, rcc_h50, rcc_h5))]
45        {
46            use crate::pac::RCC;
47            RCC.apb3enr().modify(|w| w.set_vrefen(true));
48        }
49        #[cfg(any(rcc_h7rs, rcc_h7rm0433, rcc_h7ab, rcc_h7))]
50        {
51            use crate::pac::RCC;
52            RCC.apb4enr().modify(|w| w.set_vrefen(true));
53        }
54        let vrefbuf = T::regs();
55        vrefbuf.csr().modify(|w| {
56            w.set_hiz(impedance_mode);
57            w.set_envr(true);
58            w.set_vrs(voltage_scale);
59        });
60        while vrefbuf.csr().read().vrr() != false {
61            // wait...
62        }
63        trace!(
64            "Vrefbuf configured with voltage scale {} and impedance mode {}",
65            voltage_scale as u8,
66            impedance_mode as u8,
67        );
68        VoltageReferenceBuffer { vrefbuf: PhantomData }
69    }
70}
71
72trait SealedInstance {
73    fn regs() -> crate::pac::vrefbuf::Vrefbuf;
74}
75
76/// VREFBUF instance trait.
77#[allow(private_bounds)]
78pub trait Instance: SealedInstance + PeripheralType {}
79
80foreach_peripheral!(
81    (vrefbuf, $inst:ident) => {
82        impl SealedInstance for crate::peripherals::$inst {
83            fn regs() -> crate::pac::vrefbuf::Vrefbuf {
84                crate::pac::$inst
85            }
86        }
87
88        impl Instance for crate::peripherals::$inst {}
89    };
90);