diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 10f268b51..580f0e3e6 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -133,6 +133,7 @@ embedded-io = { version = "0.6.0" } embedded-io-async = { version = "0.6.1" } defmt = { version = "0.3", optional = true } +bitflags = "2.4.2" log = { version = "0.4.14", optional = true } cortex-m-rt = ">=0.6.15,<0.8" cortex-m = "0.7.6" diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 95434e7a7..90d851139 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -52,6 +52,39 @@ impl Default for Config { } } +bitflags::bitflags! { + /// Error source flags + pub struct ErrorSource: u32 { + /// Buffer overrun + const OVERRUN = 0x01; + /// Parity error + const PARITY = 0x02; + /// Framing error + const FRAMING = 0x04; + /// Break condition + const BREAK = 0x08; + } +} + +impl TryFrom for () { + type Error = Error; + + #[inline] + fn try_from(errors: ErrorSource) -> Result { + if errors.contains(ErrorSource::OVERRUN) { + Err(Error::Overrun) + } else if errors.contains(ErrorSource::PARITY) { + Err(Error::Parity) + } else if errors.contains(ErrorSource::FRAMING) { + Err(Error::Framing) + } else if errors.contains(ErrorSource::BREAK) { + Err(Error::Break) + } else { + Ok(()) + } + } +} + /// UART error. #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -61,6 +94,14 @@ pub enum Error { BufferTooLong, /// The buffer is not in data RAM. It's most likely in flash, and nRF's DMA cannot access flash. BufferNotInRAM, + /// Framing Error + Framing, + /// Parity Error + Parity, + /// Buffer Overrun + Overrun, + /// Break condition + Break, } /// Interrupt handler. @@ -73,9 +114,16 @@ impl interrupt::typelevel::Handler for InterruptHandl let r = T::regs(); let s = T::state(); - if r.events_endrx.read().bits() != 0 { + let endrx = r.events_endrx.read().bits(); + let error = r.events_error.read().bits(); + if endrx != 0 || error != 0 { s.endrx_waker.wake(); - r.intenclr.write(|w| w.endrx().clear()); + if endrx != 0 { + r.intenclr.write(|w| w.endrx().clear()); + } + if error != 0 { + r.intenclr.write(|w| w.error().clear()); + } } if r.events_endtx.read().bits() != 0 { s.endtx_waker.wake(); @@ -486,6 +534,13 @@ impl<'d, T: Instance> UarteRx<'d, T> { Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config) } + fn read_and_clear_errors(&mut self) -> Result<(), Error> { + let r = T::regs(); + let err_bits = r.errorsrc.read().bits(); + r.errorsrc.write(|w| unsafe { w.bits(err_bits) }); + ErrorSource::from_bits_truncate(err_bits).try_into() + } + fn new_inner( uarte: impl Peripheral

+ 'd, rxd: PeripheralRef<'d, AnyPin>, @@ -572,7 +627,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { /// Read bytes until the buffer is filled. pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - if buffer.len() == 0 { + if buffer.is_empty() { return Ok(()); } if buffer.len() > EASY_DMA_SIZE { @@ -588,8 +643,13 @@ impl<'d, T: Instance> UarteRx<'d, T> { let drop = OnDrop::new(move || { trace!("read drop: stopping"); - r.intenclr.write(|w| w.endrx().clear()); + r.intenclr.write(|w| { + w.endrx().clear(); + w.error().clear() + }); r.events_rxto.reset(); + r.events_error.reset(); + r.errorsrc.reset(); r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); while r.events_endrx.read().bits() == 0 {} @@ -601,17 +661,26 @@ impl<'d, T: Instance> UarteRx<'d, T> { r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); r.events_endrx.reset(); - r.intenset.write(|w| w.endrx().set()); + r.events_error.reset(); + r.intenset.write(|w| { + w.endrx().set(); + w.error().set() + }); compiler_fence(Ordering::SeqCst); trace!("startrx"); r.tasks_startrx.write(|w| unsafe { w.bits(1) }); - poll_fn(|cx| { + let result = poll_fn(|cx| { s.endrx_waker.register(cx.waker()); + + let maybe_err = self.read_and_clear_errors(); + if let Err(e) = maybe_err { + return Poll::Ready(Err(e)); + } if r.events_endrx.read().bits() != 0 { - return Poll::Ready(()); + return Poll::Ready(Ok(())); } Poll::Pending }) @@ -621,7 +690,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { r.events_rxstarted.reset(); drop.defuse(); - Ok(()) + result } /// Read bytes until the buffer is filled. @@ -642,19 +711,23 @@ impl<'d, T: Instance> UarteRx<'d, T> { r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); r.events_endrx.reset(); - r.intenclr.write(|w| w.endrx().clear()); + r.events_error.reset(); + r.intenclr.write(|w| { + w.endrx().clear(); + w.error().clear() + }); compiler_fence(Ordering::SeqCst); trace!("startrx"); r.tasks_startrx.write(|w| unsafe { w.bits(1) }); - while r.events_endrx.read().bits() == 0 {} + while r.events_endrx.read().bits() == 0 && r.events_error.read().bits() == 0 {} compiler_fence(Ordering::SeqCst); r.events_rxstarted.reset(); - Ok(()) + self.read_and_clear_errors() } }