738: Add split method to UarteWithIdle in nrf hal r=lulf a=ZoeyR

I needed this method because I was writing a driver for the sim7000 modem. Its a line based protocol so the read until idle was very useful to me. Unfortunately unlike the primary `Uarte` struct the `UarteWithIdle` didn't have `split()`. So I added it 😄 

Co-authored-by: Zoey Riordan <zoey@dos.cafe>
This commit is contained in:
bors[bot] 2022-04-28 16:25:36 +00:00 committed by GitHub
commit b7c510beb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -554,10 +554,8 @@ pub(in crate) fn drop_tx_rx(r: &pac::uarte0::RegisterBlock, s: &sealed::State) {
/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels, /// Interface to an UARTE peripheral that uses an additional timer and two PPI channels,
/// allowing it to implement the ReadUntilIdle trait. /// allowing it to implement the ReadUntilIdle trait.
pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
uarte: Uarte<'d, U>, tx: UarteTx<'d, U>,
timer: Timer<'d, T>, rx: UarteRxWithIdle<'d, U, T>,
ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>,
_ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>,
} }
impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
@ -628,7 +626,8 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
config: Config, config: Config,
) -> Self { ) -> Self {
let baudrate = config.baudrate; let baudrate = config.baudrate;
let uarte = Uarte::new_inner(uarte, irq, rxd, txd, cts, rts, config); let (tx, rx) = Uarte::new_inner(uarte, irq, rxd, txd, cts, rts, config).split();
let mut timer = Timer::new(timer); let mut timer = Timer::new(timer);
unborrow!(ppi_ch1, ppi_ch2); unborrow!(ppi_ch1, ppi_ch2);
@ -664,29 +663,64 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
ppi_ch2.enable(); ppi_ch2.enable();
Self { Self {
uarte, tx,
timer, rx: UarteRxWithIdle {
ppi_ch1: ppi_ch1, rx,
_ppi_ch2: ppi_ch2, timer,
ppi_ch1: ppi_ch1,
_ppi_ch2: ppi_ch2,
},
} }
} }
/// Split the Uarte into a transmitter and receiver, which is
/// particuarly useful when having two tasks correlating to
/// transmitting and receiving.
pub fn split(self) -> (UarteTx<'d, U>, UarteRxWithIdle<'d, U, T>) {
(self.tx, self.rx)
}
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.ppi_ch1.disable(); self.rx.read(buffer).await
self.uarte.read(buffer).await
} }
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
self.uarte.write(buffer).await self.tx.write(buffer).await
}
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.rx.blocking_read(buffer)
}
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
self.tx.blocking_write(buffer)
}
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
self.rx.read_until_idle(buffer).await
}
pub fn blocking_read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
self.rx.blocking_read_until_idle(buffer)
}
}
pub struct UarteRxWithIdle<'d, U: Instance, T: TimerInstance> {
rx: UarteRx<'d, U>,
timer: Timer<'d, T>,
ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>,
_ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>,
}
impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> {
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.ppi_ch1.disable();
self.rx.read(buffer).await
} }
pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.ppi_ch1.disable(); self.ppi_ch1.disable();
self.uarte.blocking_read(buffer) self.rx.blocking_read(buffer)
}
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
self.uarte.blocking_write(buffer)
} }
pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> {
@ -706,8 +740,6 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
self.ppi_ch1.enable(); self.ppi_ch1.enable();
let drop = OnDrop::new(|| { let drop = OnDrop::new(|| {
trace!("read drop: stopping");
self.timer.stop(); self.timer.stop();
r.intenclr.write(|w| w.endrx().clear()); r.intenclr.write(|w| w.endrx().clear());
@ -715,8 +747,6 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
while r.events_endrx.read().bits() == 0 {} while r.events_endrx.read().bits() == 0 {}
trace!("read drop: stopped");
}); });
r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
@ -785,7 +815,6 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
Ok(n) Ok(n)
} }
} }
pub(crate) mod sealed { pub(crate) mod sealed {
use core::sync::atomic::AtomicU8; use core::sync::atomic::AtomicU8;