1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
use core::future::poll_fn;
use core::mem;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_embedded_hal::SetConfig;
use embassy_hal_internal::PeripheralRef;
use futures::future::{select, Either};
use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, RxDma, UartRx};
use crate::dma::ReadableRingBuffer;
use crate::usart::{Regs, Sr};
/// Rx-only Ring-buffered UART Driver
pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> {
_peri: PeripheralRef<'d, T>,
ring_buf: ReadableRingBuffer<'d, RxDma, u8>,
}
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> SetConfig for RingBufferedUartRx<'d, T, RxDma> {
type Config = Config;
type ConfigError = ConfigError;
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
self.set_config(config)
}
}
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
/// Turn the `UartRx` into a buffered uart which can continously receive in the background
/// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the
/// DMA controller, and must be large enough to prevent overflows.
pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T, RxDma> {
assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
let request = self.rx_dma.request();
let opts = Default::default();
// Safety: we forget the struct before this function returns.
let rx_dma = unsafe { self.rx_dma.clone_unchecked() };
let _peri = unsafe { self._peri.clone_unchecked() };
let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(T::regs()), dma_buf, opts) };
// Don't disable the clock
mem::forget(self);
RingBufferedUartRx { _peri, ring_buf }
}
}
impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> {
/// 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)
}
/// Cleanly stop and reconfigure the driver
pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
self.teardown_uart();
reconfigure::<T>(config)
}
/// Start uart background receive
fn setup_uart(&mut self) {
// fence before starting DMA.
compiler_fence(Ordering::SeqCst);
// start the dma controller
self.ring_buf.start();
let r = T::regs();
// clear all interrupts and DMA Rx Request
r.cr1().modify(|w| {
// disable RXNE interrupt
w.set_rxneie(false);
// enable parity interrupt if not ParityNone
w.set_peie(w.pce());
// enable idle line interrupt
w.set_idleie(true);
});
r.cr3().modify(|w| {
// enable Error Interrupt: (Frame error, Noise error, Overrun error)
w.set_eie(true);
// enable DMA Rx Request
w.set_dmar(true);
});
}
/// Stop uart background receive
fn teardown_uart(&mut self) {
self.ring_buf.request_stop();
let r = T::regs();
// clear all interrupts and DMA Rx Request
r.cr1().modify(|w| {
// disable RXNE interrupt
w.set_rxneie(false);
// disable parity interrupt
w.set_peie(false);
// disable idle line interrupt
w.set_idleie(false);
});
r.cr3().modify(|w| {
// disable Error Interrupt: (Frame error, Noise error, Overrun error)
w.set_eie(false);
// disable DMA Rx Request
w.set_dmar(false);
});
compiler_fence(Ordering::SeqCst);
}
/// Read bytes that are readily available in the ring buffer.
/// If no bytes are currently available in the buffer the call waits until the some
/// bytes are available (at least one byte and at most half the buffer size)
///
/// Background receive is started if `start()` has not been previously called.
///
/// Receive in the background is terminated if an error is returned.
/// It must then manually be started again by calling `start()` or by re-calling `read()`.
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let r = T::regs();
// Start background receive if it was not already started
if !r.cr3().read().dmar() {
self.start()?;
}
check_for_errors(clear_idle_flag(T::regs()))?;
loop {
match self.ring_buf.read(buf) {
Ok((0, _)) => {}
Ok((len, _)) => {
return Ok(len);
}
Err(_) => {
return self.stop(Error::Overrun);
}
}
match self.wait_for_data_or_idle().await {
Ok(_) => {}
Err(err) => {
return self.stop(err);
}
}
}
}
/// Wait for uart idle or dma half-full or full
async fn wait_for_data_or_idle(&mut self) -> Result<(), Error> {
compiler_fence(Ordering::SeqCst);
let mut dma_init = false;
// Future which completes when there is dma is half full or full
let dma = poll_fn(|cx| {
self.ring_buf.set_waker(cx.waker());
let status = match dma_init {
false => Poll::Pending,
true => Poll::Ready(()),
};
dma_init = true;
status
});
// Future which completes when idle line is detected
let uart = poll_fn(|cx| {
let s = T::state();
s.rx_waker.register(cx.waker());
compiler_fence(Ordering::SeqCst);
// Critical section is needed so that IDLE isn't set after
// our read but before we clear it.
let sr = critical_section::with(|_| clear_idle_flag(T::regs()));
check_for_errors(sr)?;
if sr.idle() {
// Idle line is detected
Poll::Ready(Ok(()))
} else {
Poll::Pending
}
});
match select(dma, uart).await {
Either::Left(((), _)) => Ok(()),
Either::Right((result, _)) => result,
}
}
}
impl<T: BasicInstance, RxDma: super::RxDma<T>> Drop for RingBufferedUartRx<'_, T, RxDma> {
fn drop(&mut self) {
self.teardown_uart();
T::disable();
}
}
/// Return an error result if the Sr register has errors
fn check_for_errors(s: Sr) -> Result<(), Error> {
if s.pe() {
Err(Error::Parity)
} else if s.fe() {
Err(Error::Framing)
} else if s.ne() {
Err(Error::Noise)
} else if s.ore() {
Err(Error::Overrun)
} else {
Ok(())
}
}
/// Clear IDLE and return the Sr register
fn clear_idle_flag(r: Regs) -> Sr {
// SAFETY: read only and we only use Rx related flags
let sr = sr(r).read();
// This read also clears the error and idle interrupt flags on v1.
unsafe { rdr(r).read_volatile() };
clear_interrupt_flags(r, sr);
r.cr1().modify(|w| w.set_idleie(true));
sr
}
impl<T, Rx> embedded_io_async::ErrorType for RingBufferedUartRx<'_, T, Rx>
where
T: BasicInstance,
Rx: RxDma<T>,
{
type Error = Error;
}
impl<T, Rx> embedded_io_async::Read for RingBufferedUartRx<'_, T, Rx>
where
T: BasicInstance,
Rx: RxDma<T>,
{
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.read(buf).await
}
}