Merge pull request #1862 from xoviat/rcc-refcount
stm32: refcount peripheral enable/disable
This commit is contained in:
commit
a03b6be693
7 changed files with 98 additions and 5 deletions
|
@ -308,6 +308,10 @@ fn main() {
|
|||
// ========
|
||||
// Generate RccPeripheral impls
|
||||
|
||||
// TODO: maybe get this from peripheral kind? Not sure
|
||||
let refcounted_peripherals = HashSet::from(["USART"]);
|
||||
let mut refcount_statics = HashSet::new();
|
||||
|
||||
for p in METADATA.peripherals {
|
||||
// generating RccPeripheral impl for H7 ADC3 would result in bad frequency
|
||||
if !singletons.contains(&p.name.to_string())
|
||||
|
@ -344,11 +348,36 @@ fn main() {
|
|||
TokenStream::new()
|
||||
};
|
||||
|
||||
let ptype = (if let Some(reg) = &p.registers { reg.kind } else { "" }).to_ascii_uppercase();
|
||||
let pname = format_ident!("{}", p.name);
|
||||
let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase());
|
||||
let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
|
||||
let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase());
|
||||
|
||||
let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype.as_str()) {
|
||||
let refcount_static =
|
||||
format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase());
|
||||
|
||||
refcount_statics.insert(refcount_static.clone());
|
||||
|
||||
(
|
||||
quote! {
|
||||
unsafe { refcount_statics::#refcount_static += 1 };
|
||||
if unsafe { refcount_statics::#refcount_static } > 1 {
|
||||
return;
|
||||
}
|
||||
},
|
||||
quote! {
|
||||
unsafe { refcount_statics::#refcount_static -= 1 };
|
||||
if unsafe { refcount_statics::#refcount_static } > 0 {
|
||||
return;
|
||||
}
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(TokenStream::new(), TokenStream::new())
|
||||
};
|
||||
|
||||
g.extend(quote! {
|
||||
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
|
||||
fn frequency() -> crate::time::Hertz {
|
||||
|
@ -356,6 +385,7 @@ fn main() {
|
|||
}
|
||||
fn enable() {
|
||||
critical_section::with(|_| {
|
||||
#before_enable
|
||||
#[cfg(feature = "low-power")]
|
||||
crate::rcc::clock_refcount_add();
|
||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
|
||||
|
@ -364,6 +394,7 @@ fn main() {
|
|||
}
|
||||
fn disable() {
|
||||
critical_section::with(|_| {
|
||||
#before_disable
|
||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
|
||||
#[cfg(feature = "low-power")]
|
||||
crate::rcc::clock_refcount_sub();
|
||||
|
@ -379,6 +410,19 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
let mut refcount_mod = TokenStream::new();
|
||||
for refcount_static in refcount_statics {
|
||||
refcount_mod.extend(quote! {
|
||||
pub(crate) static mut #refcount_static: u8 = 0;
|
||||
});
|
||||
}
|
||||
|
||||
g.extend(quote! {
|
||||
mod refcount_statics {
|
||||
#refcount_mod
|
||||
}
|
||||
});
|
||||
|
||||
// ========
|
||||
// Generate fns to enable GPIO, DMA in RCC
|
||||
|
||||
|
|
|
@ -339,6 +339,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
|
||||
fn drop(&mut self) {
|
||||
T::disable();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
|
||||
type Error = Error;
|
||||
|
||||
|
|
|
@ -838,6 +838,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
|
||||
fn drop(&mut self) {
|
||||
T::disable();
|
||||
}
|
||||
}
|
||||
|
||||
mod eh02 {
|
||||
use super::*;
|
||||
|
||||
|
|
|
@ -646,6 +646,8 @@ impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
|
|||
self.sck.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.mosi.as_ref().map(|x| x.set_as_disconnected());
|
||||
self.miso.as_ref().map(|x| x.set_as_disconnected());
|
||||
|
||||
T::disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||
rx_buffer: &'d mut [u8],
|
||||
config: Config,
|
||||
) -> BufferedUart<'d, T> {
|
||||
// UartRx and UartTx have one refcount ea.
|
||||
T::enable();
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
|
@ -143,6 +145,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||
) -> BufferedUart<'d, T> {
|
||||
into_ref!(cts, rts);
|
||||
|
||||
// UartRx and UartTx have one refcount ea.
|
||||
T::enable();
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
|
@ -169,6 +173,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
|
|||
) -> BufferedUart<'d, T> {
|
||||
into_ref!(de);
|
||||
|
||||
// UartRx and UartTx have one refcount ea.
|
||||
T::enable();
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
|
@ -382,6 +388,8 @@ impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> {
|
|||
T::Interrupt::disable();
|
||||
}
|
||||
}
|
||||
|
||||
T::disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -397,6 +405,8 @@ impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> {
|
|||
T::Interrupt::disable();
|
||||
}
|
||||
}
|
||||
|
||||
T::disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -618,6 +618,18 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'d, T: BasicInstance, TxDma> Drop for UartTx<'d, T, TxDma> {
|
||||
fn drop(&mut self) {
|
||||
T::disable();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> {
|
||||
fn drop(&mut self) {
|
||||
T::disable();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
||||
pub fn new(
|
||||
peri: impl Peripheral<P = T> + 'd,
|
||||
|
@ -628,6 +640,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||
rx_dma: impl Peripheral<P = RxDma> + 'd,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
// UartRx and UartTx have one refcount ea.
|
||||
T::enable();
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
|
@ -647,6 +661,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||
) -> Self {
|
||||
into_ref!(cts, rts);
|
||||
|
||||
// UartRx and UartTx have one refcount ea.
|
||||
T::enable();
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
|
@ -672,6 +688,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
|
|||
) -> Self {
|
||||
into_ref!(de);
|
||||
|
||||
// UartRx and UartTx have one refcount ea.
|
||||
T::enable();
|
||||
T::enable();
|
||||
T::reset();
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use core::future::poll_fn;
|
||||
use core::mem;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::Poll;
|
||||
|
||||
|
@ -24,12 +25,16 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
|
|||
let request = self.rx_dma.request();
|
||||
let opts = Default::default();
|
||||
|
||||
let ring_buf = unsafe { ReadableRingBuffer::new_read(self.rx_dma, request, rdr(T::regs()), dma_buf, opts) };
|
||||
// Safety: we forget the struct before this function returns.
|
||||
let rx_dma = unsafe { self.rx_dma.clone_unchecked() };
|
||||
let _peri = unsafe { self._peri.clone_unchecked() };
|
||||
|
||||
RingBufferedUartRx {
|
||||
_peri: self._peri,
|
||||
ring_buf,
|
||||
}
|
||||
let ring_buf = unsafe { ReadableRingBuffer::new_read(rx_dma, request, rdr(T::regs()), dma_buf, opts) };
|
||||
|
||||
// Don't disable the clock
|
||||
mem::forget(self);
|
||||
|
||||
RingBufferedUartRx { _peri, ring_buf }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,6 +191,8 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
|
|||
impl<T: BasicInstance, RxDma: super::RxDma<T>> Drop for RingBufferedUartRx<'_, T, RxDma> {
|
||||
fn drop(&mut self) {
|
||||
self.teardown_uart();
|
||||
|
||||
T::disable();
|
||||
}
|
||||
}
|
||||
/// Return an error result if the Sr register has errors
|
||||
|
|
Loading…
Reference in a new issue