stm32: fix refcounts for usart, spi, and i2c

This commit is contained in:
xoviat 2023-09-04 15:47:33 -05:00
parent 3466c9cfa9
commit 274f63a879
7 changed files with 60 additions and 17 deletions

View File

@ -347,9 +347,7 @@ fn main() {
TokenStream::new() TokenStream::new()
}; };
let ptype = p let ptype = p.name.replace(|c| char::is_numeric(c), "");
.name
.replace(&['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'][..], "");
let pname = format_ident!("{}", p.name); let pname = format_ident!("{}", p.name);
let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase()); let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase());
let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
@ -363,16 +361,14 @@ fn main() {
( (
quote! { quote! {
use atomic_polyfill::Ordering; unsafe { refcount_statics::#refcount_static += 1 };
if unsafe { refcount_statics::#refcount_static } > 1 {
if refcount_statics::#refcount_static.fetch_add(1, Ordering::SeqCst) > 0 {
return; return;
} }
}, },
quote! { quote! {
use atomic_polyfill::Ordering; unsafe { refcount_statics::#refcount_static -= 1 };
if unsafe { refcount_statics::#refcount_static } > 0 {
if refcount_statics::#refcount_static.fetch_sub(1, Ordering::SeqCst) > 1 {
return; return;
} }
}, },
@ -416,14 +412,12 @@ fn main() {
let mut refcount_mod = TokenStream::new(); let mut refcount_mod = TokenStream::new();
for refcount_static in refcount_statics { for refcount_static in refcount_statics {
refcount_mod.extend(quote! { refcount_mod.extend(quote! {
pub(crate) static #refcount_static: AtomicU8 = AtomicU8::new(0); pub(crate) static mut #refcount_static: u8 = 0;
}); });
} }
g.extend(quote! { g.extend(quote! {
mod refcount_statics { mod refcount_statics {
use atomic_polyfill::AtomicU8;
#refcount_mod #refcount_mod
} }
}); });

View File

@ -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> { impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
type Error = Error; type Error = Error;

View File

@ -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 { mod eh02 {
use super::*; use super::*;

View File

@ -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.sck.as_ref().map(|x| x.set_as_disconnected());
self.mosi.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()); self.miso.as_ref().map(|x| x.set_as_disconnected());
T::disable();
} }
} }

View File

@ -124,6 +124,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> BufferedUart<'d, T> { ) -> BufferedUart<'d, T> {
// UartRx and UartTx have one refcount ea.
T::enable();
T::enable(); T::enable();
T::reset(); T::reset();
@ -143,6 +145,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
) -> BufferedUart<'d, T> { ) -> BufferedUart<'d, T> {
into_ref!(cts, rts); into_ref!(cts, rts);
// UartRx and UartTx have one refcount ea.
T::enable();
T::enable(); T::enable();
T::reset(); T::reset();
@ -169,6 +173,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
) -> BufferedUart<'d, T> { ) -> BufferedUart<'d, T> {
into_ref!(de); into_ref!(de);
// UartRx and UartTx have one refcount ea.
T::enable();
T::enable(); T::enable();
T::reset(); T::reset();
@ -382,6 +388,8 @@ impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> {
T::Interrupt::disable(); T::Interrupt::disable();
} }
} }
T::disable();
} }
} }
@ -397,6 +405,8 @@ impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> {
T::Interrupt::disable(); T::Interrupt::disable();
} }
} }
T::disable();
} }
} }

View File

@ -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> { impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
pub fn new( pub fn new(
peri: impl Peripheral<P = T> + 'd, 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, rx_dma: impl Peripheral<P = RxDma> + 'd,
config: Config, config: Config,
) -> Self { ) -> Self {
// UartRx and UartTx have one refcount ea.
T::enable();
T::enable(); T::enable();
T::reset(); T::reset();
@ -647,6 +661,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
) -> Self { ) -> Self {
into_ref!(cts, rts); into_ref!(cts, rts);
// UartRx and UartTx have one refcount ea.
T::enable();
T::enable(); T::enable();
T::reset(); T::reset();
@ -672,6 +688,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
) -> Self { ) -> Self {
into_ref!(de); into_ref!(de);
// UartRx and UartTx have one refcount ea.
T::enable();
T::enable(); T::enable();
T::reset(); T::reset();

View File

@ -1,4 +1,5 @@
use core::future::poll_fn; use core::future::poll_fn;
use core::mem;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll; 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 request = self.rx_dma.request();
let opts = Default::default(); 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 { let ring_buf = unsafe { ReadableRingBuffer::new_read(rx_dma, request, rdr(T::regs()), dma_buf, opts) };
_peri: self._peri,
ring_buf, // 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> { impl<T: BasicInstance, RxDma: super::RxDma<T>> Drop for RingBufferedUartRx<'_, T, RxDma> {
fn drop(&mut self) { fn drop(&mut self) {
self.teardown_uart(); self.teardown_uart();
T::disable();
} }
} }
/// Return an error result if the Sr register has errors /// Return an error result if the Sr register has errors