stm32: Only check errors on running RingBufferedUartRx, reduce number of small one-time functions

This commit is contained in:
Peter Krull 2024-09-19 19:21:34 +02:00
parent 2a9cdaabaa
commit 4fcc8e39d6

View File

@ -71,33 +71,18 @@ impl<'d> UartRx<'d, Async> {
} }
impl<'d> RingBufferedUartRx<'d> { impl<'d> RingBufferedUartRx<'d> {
/// Clear the ring buffer and start receiving in the background
pub fn start(&mut self) -> Result<(), Error> {
// Clear the ring buffer so that it is ready to receive data
self.ring_buf.clear();
self.setup_uart();
Ok(())
}
fn stop(&mut self, err: Error) -> Result<usize, Error> {
self.teardown_uart();
Err(err)
}
/// Reconfigure the driver /// Reconfigure the driver
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
reconfigure(self.info, self.kernel_clock, config) reconfigure(self.info, self.kernel_clock, config)
} }
/// Start uart background receive /// Configure and start the DMA backed UART receiver
fn setup_uart(&mut self) { ///
// fence before starting DMA. /// Note: This is also done automatically by [`read()`] if required.
pub fn start_uart(&mut self) {
// Clear the buffer so that it is ready to receive data
self.ring_buf.clear();
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
// start the dma controller
self.ring_buf.start(); self.ring_buf.start();
let r = self.info.regs; let r = self.info.regs;
@ -118,8 +103,8 @@ impl<'d> RingBufferedUartRx<'d> {
}); });
} }
/// Stop uart background receive /// Stop DMA backed UART receiver
fn teardown_uart(&mut self) { fn stop_uart(&mut self) {
self.ring_buf.request_pause(); self.ring_buf.request_pause();
let r = self.info.regs; let r = self.info.regs;
@ -153,13 +138,15 @@ impl<'d> RingBufferedUartRx<'d> {
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let r = self.info.regs; let r = self.info.regs;
// Start background receive if it was not already started // Start DMA and Uart if it was not already started,
// otherwise check for errors in status register.
let sr = clear_idle_flag(r);
if !r.cr3().read().dmar() { if !r.cr3().read().dmar() {
self.start()?; self.start_uart();
} else {
check_for_errors(sr)?;
} }
check_for_errors(clear_idle_flag(r))?;
loop { loop {
match self.ring_buf.read(buf) { match self.ring_buf.read(buf) {
Ok((0, _)) => {} Ok((0, _)) => {}
@ -167,14 +154,16 @@ impl<'d> RingBufferedUartRx<'d> {
return Ok(len); return Ok(len);
} }
Err(_) => { Err(_) => {
return self.stop(Error::Overrun); self.stop_uart();
return Err(Error::Overrun);
} }
} }
match self.wait_for_data_or_idle().await { match self.wait_for_data_or_idle().await {
Ok(_) => {} Ok(_) => {}
Err(err) => { Err(err) => {
return self.stop(err); self.stop_uart();
return Err(err);
} }
} }
} }
@ -228,7 +217,7 @@ impl<'d> RingBufferedUartRx<'d> {
impl Drop for RingBufferedUartRx<'_> { impl Drop for RingBufferedUartRx<'_> {
fn drop(&mut self) { fn drop(&mut self) {
self.teardown_uart(); self.stop_uart();
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());
super::drop_tx_rx(self.info, self.state); super::drop_tx_rx(self.info, self.state);