Split_ref with shortened lifetime. When borrowed skip drop on rx and tx

This commit is contained in:
Kenneth Knudsen 2024-11-06 10:52:03 +01:00
parent aa453caa79
commit 72109a7bda

View File

@ -157,6 +157,7 @@ pub struct BufferedUartTx<'d> {
tx: Option<PeripheralRef<'d, AnyPin>>, tx: Option<PeripheralRef<'d, AnyPin>>,
cts: Option<PeripheralRef<'d, AnyPin>>, cts: Option<PeripheralRef<'d, AnyPin>>,
de: Option<PeripheralRef<'d, AnyPin>>, de: Option<PeripheralRef<'d, AnyPin>>,
is_borrowed: bool,
} }
/// Rx-only buffered UART /// Rx-only buffered UART
@ -168,6 +169,7 @@ pub struct BufferedUartRx<'d> {
kernel_clock: Hertz, kernel_clock: Hertz,
rx: Option<PeripheralRef<'d, AnyPin>>, rx: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>, rts: Option<PeripheralRef<'d, AnyPin>>,
is_borrowed: bool,
} }
impl<'d> SetConfig for BufferedUart<'d> { impl<'d> SetConfig for BufferedUart<'d> {
@ -341,6 +343,7 @@ impl<'d> BufferedUart<'d> {
kernel_clock, kernel_clock,
rx, rx,
rts, rts,
is_borrowed: false,
}, },
tx: BufferedUartTx { tx: BufferedUartTx {
info, info,
@ -349,6 +352,7 @@ impl<'d> BufferedUart<'d> {
tx, tx,
cts, cts,
de, de,
is_borrowed: false,
}, },
}; };
this.enable_and_configure(tx_buffer, rx_buffer, &config)?; this.enable_and_configure(tx_buffer, rx_buffer, &config)?;
@ -396,11 +400,29 @@ impl<'d> BufferedUart<'d> {
(self.tx, self.rx) (self.tx, self.rx)
} }
/// Split the Uart into a transmitter and receiver by mutable reference, /// Split the Uart into a transmitter and receiver,
/// which is particularly useful when having two tasks correlating to /// which is particularly useful when having two tasks correlating to
/// transmitting and receiving. /// transmitting and receiving.
pub fn split_ref(&mut self) -> (&mut BufferedUartTx<'d>, &mut BufferedUartRx<'d>) { pub fn split_ref(&mut self) -> (BufferedUartTx<'_>, BufferedUartRx<'_>) {
(&mut self.tx, &mut self.rx) (
BufferedUartTx {
info: self.tx.info,
state: self.tx.state,
kernel_clock: self.tx.kernel_clock,
tx: self.tx.tx.as_mut().map(PeripheralRef::reborrow),
cts: self.tx.cts.as_mut().map(PeripheralRef::reborrow),
de: self.tx.de.as_mut().map(PeripheralRef::reborrow),
is_borrowed: true,
},
BufferedUartRx {
info: self.rx.info,
state: self.rx.state,
kernel_clock: self.rx.kernel_clock,
rx: self.rx.rx.as_mut().map(PeripheralRef::reborrow),
rts: self.rx.rts.as_mut().map(PeripheralRef::reborrow),
is_borrowed: true,
},
)
} }
/// Reconfigure the driver /// Reconfigure the driver
@ -607,40 +629,44 @@ impl<'d> BufferedUartTx<'d> {
impl<'d> Drop for BufferedUartRx<'d> { impl<'d> Drop for BufferedUartRx<'d> {
fn drop(&mut self) { fn drop(&mut self) {
let state = self.state; if !self.is_borrowed {
unsafe { let state = self.state;
state.rx_buf.deinit(); unsafe {
state.rx_buf.deinit();
// TX is inactive if the the buffer is not available. // TX is inactive if the the buffer is not available.
// We can now unregister the interrupt handler // We can now unregister the interrupt handler
if state.tx_buf.len() == 0 { if state.tx_buf.len() == 0 {
self.info.interrupt.disable(); self.info.interrupt.disable();
}
} }
}
self.rx.as_ref().map(|x| x.set_as_disconnected()); self.rx.as_ref().map(|x| x.set_as_disconnected());
self.rts.as_ref().map(|x| x.set_as_disconnected()); self.rts.as_ref().map(|x| x.set_as_disconnected());
drop_tx_rx(self.info, state); drop_tx_rx(self.info, state);
}
} }
} }
impl<'d> Drop for BufferedUartTx<'d> { impl<'d> Drop for BufferedUartTx<'d> {
fn drop(&mut self) { fn drop(&mut self) {
let state = self.state; if !self.is_borrowed {
unsafe { let state = self.state;
state.tx_buf.deinit(); unsafe {
state.tx_buf.deinit();
// RX is inactive if the the buffer is not available. // RX is inactive if the the buffer is not available.
// We can now unregister the interrupt handler // We can now unregister the interrupt handler
if state.rx_buf.len() == 0 { if state.rx_buf.len() == 0 {
self.info.interrupt.disable(); self.info.interrupt.disable();
}
} }
}
self.tx.as_ref().map(|x| x.set_as_disconnected()); self.tx.as_ref().map(|x| x.set_as_disconnected());
self.cts.as_ref().map(|x| x.set_as_disconnected()); self.cts.as_ref().map(|x| x.set_as_disconnected());
self.de.as_ref().map(|x| x.set_as_disconnected()); self.de.as_ref().map(|x| x.set_as_disconnected());
drop_tx_rx(self.info, state); drop_tx_rx(self.info, state);
}
} }
} }