aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs49
1 files changed, 38 insertions, 11 deletions
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index 600e72582..3a7c3adf4 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -133,6 +133,20 @@ impl<'d> RingBufferedUartRx<'d> {
133 compiler_fence(Ordering::SeqCst); 133 compiler_fence(Ordering::SeqCst);
134 } 134 }
135 135
136 /// (Re-)start DMA and Uart if it is not running (has not been started yet or has failed), and
137 /// check for errors in status register. Error flags are cleared in `start_uart()` so they need
138 /// to be read first without returning yet.
139 fn start_dma_or_check_errors(&mut self) -> Result<(), Error> {
140 let r = self.info.regs;
141
142 let sr = clear_idle_flag(r);
143 let res = check_for_errors(sr);
144 if !r.cr3().read().dmar() {
145 self.start_uart();
146 }
147 res
148 }
149
136 /// Read bytes that are readily available in the ring buffer. 150 /// Read bytes that are readily available in the ring buffer.
137 /// If no bytes are currently available in the buffer the call waits until the some 151 /// If no bytes are currently available in the buffer the call waits until the some
138 /// bytes are available (at least one byte and at most half the buffer size) 152 /// bytes are available (at least one byte and at most half the buffer size)
@@ -142,17 +156,7 @@ impl<'d> RingBufferedUartRx<'d> {
142 /// Receive in the background is terminated if an error is returned. 156 /// Receive in the background is terminated if an error is returned.
143 /// It must then manually be started again by calling `start()` or by re-calling `read()`. 157 /// It must then manually be started again by calling `start()` or by re-calling `read()`.
144 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 158 pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
145 let r = self.info.regs; 159 self.start_dma_or_check_errors()?;
146
147 // (Re-)start DMA and Uart if it is not running (has not been started yet or has failed),
148 // and check for errors in status register. Error flags are cleared in `start_uart()` so
149 // they need to be read first without returning yet.
150 let sr = clear_idle_flag(r);
151 let res = check_for_errors(sr);
152 if !r.cr3().read().dmar() {
153 self.start_uart();
154 }
155 res?;
156 160
157 loop { 161 loop {
158 match self.ring_buf.read(buf) { 162 match self.ring_buf.read(buf) {
@@ -281,6 +285,29 @@ impl embedded_io_async::Read for RingBufferedUartRx<'_> {
281 } 285 }
282} 286}
283 287
288impl embedded_hal_nb::serial::Read for RingBufferedUartRx<'_> {
289 fn read(&mut self) -> nb::Result<u8, Self::Error> {
290 self.start_dma_or_check_errors()?;
291
292 let mut buf = [0u8; 1];
293 match self.ring_buf.read(&mut buf) {
294 Ok((0, _)) => Err(nb::Error::WouldBlock),
295 Ok((len, _)) => {
296 assert!(len == 1);
297 Ok(buf[0])
298 }
299 Err(_) => {
300 self.stop_uart();
301 Err(nb::Error::Other(Error::Overrun))
302 }
303 }
304 }
305}
306
307impl embedded_hal_nb::serial::ErrorType for RingBufferedUartRx<'_> {
308 type Error = Error;
309}
310
284impl ReadReady for RingBufferedUartRx<'_> { 311impl ReadReady for RingBufferedUartRx<'_> {
285 fn read_ready(&mut self) -> Result<bool, Self::Error> { 312 fn read_ready(&mut self) -> Result<bool, Self::Error> {
286 let len = self.ring_buf.len().map_err(|e| match e { 313 let len = self.ring_buf.len().map_err(|e| match e {