rp: Fix BufferedUart drop code

Only unregister the interrupt handler when both parts are inactive
This commit is contained in:
Timo Kröger 2023-01-01 22:02:45 +01:00
parent 68c186309f
commit a24037edf9
3 changed files with 31 additions and 26 deletions

View file

@ -81,6 +81,10 @@ impl RingBuffer {
Writer(self)
}
pub fn len(&self) -> usize {
self.len.load(Ordering::Relaxed)
}
pub fn is_full(&self) -> bool {
let len = self.len.load(Ordering::Relaxed);
let start = self.start.load(Ordering::Relaxed);

View file

@ -27,7 +27,8 @@ impl State {
}
pub struct BufferedUart<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
rx: BufferedUartRx<'d, T>,
tx: BufferedUartTx<'d, T>,
}
pub struct BufferedUartRx<'d, T: Instance> {
@ -91,7 +92,10 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
rx_buffer,
config,
);
Self { phantom: PhantomData }
Self {
rx: BufferedUartRx { phantom: PhantomData },
tx: BufferedUartTx { phantom: PhantomData },
}
}
pub fn new_with_rtscts(
@ -116,14 +120,14 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
rx_buffer,
config,
);
Self { phantom: PhantomData }
Self {
rx: BufferedUartRx { phantom: PhantomData },
tx: BufferedUartTx { phantom: PhantomData },
}
}
pub fn split(&mut self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) {
(
BufferedUartRx { phantom: PhantomData },
BufferedUartTx { phantom: PhantomData },
)
pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) {
(self.rx, self.tx)
}
}
@ -269,35 +273,32 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
}
}
impl<'d, T: Instance> Drop for BufferedUart<'d, T> {
fn drop(&mut self) {
unsafe {
T::Interrupt::steal().disable();
let state = T::state();
state.tx_buf.deinit();
state.rx_buf.deinit();
}
}
}
impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
fn drop(&mut self) {
unsafe {
T::Interrupt::steal().disable();
let state = T::state();
state.tx_buf.deinit();
unsafe {
state.rx_buf.deinit();
// TX is inactive if the the buffer is not available.
// We can now unregister the interrupt handler
if state.tx_buf.len() == 0 {
T::Interrupt::steal().disable();
}
}
}
}
impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
fn drop(&mut self) {
unsafe {
T::Interrupt::steal().disable();
let state = T::state();
unsafe {
state.tx_buf.deinit();
state.rx_buf.deinit();
// RX is inactive if the the buffer is not available.
// We can now unregister the interrupt handler
if state.rx_buf.len() == 0 {
T::Interrupt::steal().disable();
}
}
}
}

View file

@ -29,7 +29,7 @@ async fn main(spawner: Spawner) {
let irq = interrupt::take!(UART0_IRQ);
let tx_buf = &mut singleton!([0u8; 16])[..];
let rx_buf = &mut singleton!([0u8; 16])[..];
let mut uart = BufferedUart::new(uart, irq, tx_pin, rx_pin, tx_buf, rx_buf, Config::default());
let uart = BufferedUart::new(uart, irq, tx_pin, rx_pin, tx_buf, rx_buf, Config::default());
let (rx, mut tx) = uart.split();
unwrap!(spawner.spawn(reader(rx)));