From a7c03e4cb6a9d39d0139cb88d224a0f80fd21820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Sun, 3 Jan 2021 11:12:11 +0100 Subject: [PATCH] uarte: Only stop RX forcefully when a reception is running The STOPRX task always triggers a timeout of ~55bit times until the RXTO event is generated. Before we disabled the receiver only after the timeout. With this change the receiver is stopped right after reception has ended because the DMA buffer is full. For forced RX aborts like `stop()` or on drop still need to wait for the RXTO event before disabling the receiver. --- embassy-nrf/src/uarte.rs | 43 ++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 494b92df..895ac11c 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -170,6 +170,13 @@ where trace!("endrx"); let len = uarte.rxd.amount.read().bits(); compiler_fence(Ordering::SeqCst); + + if uarte.events_rxstarted.read().bits() != 0 { + // The ENDRX was signal triggered because DMA buffer is full. + uarte.events_rxstarted.reset(); + try_disable = true; + } + T::state().rx_done.signal(len); } @@ -227,6 +234,7 @@ impl embassy::uart::Uart for Uarte { // `mem::forget()` on a previous future after polling it once. assert!(!self.rx_started()); + T::state().rx_done.reset(); self.enable(); ReceiveFuture { @@ -334,27 +342,28 @@ where fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { uarte, buf } = unsafe { self.get_unchecked_mut() }; - if !uarte.rx_started() { - let uarte = &uarte.instance; + match T::state().rx_done.poll_wait(cx) { + Poll::Pending if !uarte.rx_started() => { + let uarte = &uarte.instance; - T::state().rx_done.reset(); + let ptr = buf.as_ptr(); + let len = buf.len(); + assert!(len <= EASY_DMA_SIZE); - let ptr = buf.as_ptr(); - let len = buf.len(); - assert!(len <= EASY_DMA_SIZE); + compiler_fence(Ordering::SeqCst); + uarte.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); + uarte + .rxd + .maxcnt + .write(|w| unsafe { w.maxcnt().bits(len as _) }); - compiler_fence(Ordering::SeqCst); - uarte.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); - uarte - .rxd - .maxcnt - .write(|w| unsafe { w.maxcnt().bits(len as _) }); - - trace!("startrx"); - uarte.tasks_startrx.write(|w| unsafe { w.bits(1) }); + trace!("startrx"); + uarte.tasks_startrx.write(|w| unsafe { w.bits(1) }); + Poll::Pending + } + Poll::Pending => Poll::Pending, + Poll::Ready(_) => Poll::Ready(Ok(())), } - - T::state().rx_done.poll_wait(cx).map(|_| Ok(())) } }