use core::cmp::min;
use core::future::{Future, poll_fn};
use core::marker::PhantomData;
use core::slice;
use core::sync::atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering, compiler_fence};
use core::task::Poll;
use embassy_hal_internal::Peri;
use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
use pac::uarte::vals;
pub use pac::uarte::vals::{Baudrate, ConfigParity as Parity};
use crate::gpio::{AnyPin, Pin as GpioPin};
use crate::interrupt::InterruptExt;
use crate::interrupt::typelevel::Interrupt;
use crate::ppi::{
self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task,
};
use crate::timer::{Instance as TimerInstance, Timer};
use crate::uarte::{Config, Instance as UarteInstance, configure, configure_rx_pins, configure_tx_pins, drop_tx_rx};
use crate::{EASY_DMA_SIZE, interrupt, pac};
pub(crate) struct State {
tx_buf: RingBuffer,
tx_count: AtomicUsize,
rx_buf: RingBuffer,
rx_started: AtomicBool,
rx_started_count: AtomicU8,
rx_ended_count: AtomicU8,
rx_ppi_ch: AtomicU8,
rx_overrun: AtomicBool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Error {
Overrun,
}
impl State {
pub(crate) const fn new() -> Self {
Self {
tx_buf: RingBuffer::new(),
tx_count: AtomicUsize::new(0),
rx_buf: RingBuffer::new(),
rx_started: AtomicBool::new(false),
rx_started_count: AtomicU8::new(0),
rx_ended_count: AtomicU8::new(0),
rx_ppi_ch: AtomicU8::new(0),
rx_overrun: AtomicBool::new(false),
}
}
}
pub struct InterruptHandler<U: UarteInstance> {
_phantom: PhantomData<U>,
}
impl<U: UarteInstance> interrupt::typelevel::Handler<U::Interrupt> for InterruptHandler<U> {
unsafe fn on_interrupt() {
let r = U::regs();
let ss = U::state();
let s = U::buffered_state();
if let Some(mut rx) = unsafe { s.rx_buf.try_writer() } {
let buf_len = s.rx_buf.len();
let half_len = buf_len / 2;
if r.events_error().read() != 0 {
r.events_error().write_value(0);
let errs = r.errorsrc().read();
r.errorsrc().write_value(errs);
if errs.overrun() {
s.rx_overrun.store(true, Ordering::Release);
ss.rx_waker.wake();
}
}
if r.inten().read().rxdrdy() && r.events_rxdrdy().read() != 0 {
r.intenclr().write(|w| w.set_rxdrdy(true));
r.events_rxdrdy().write_value(0);
ss.rx_waker.wake();
}
if r.events_dma().rx().end().read() != 0 {
r.events_dma().rx().end().write_value(0);
let val = s.rx_ended_count.load(Ordering::Relaxed);
s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed);
}
if r.events_dma().rx().ready().read() != 0 || !s.rx_started.load(Ordering::Relaxed) {
let (ptr, len) = rx.push_buf();
if len >= half_len {
r.events_dma().rx().ready().write_value(0);
r.dma().rx().ptr().write_value(ptr as u32);
r.dma().rx().maxcnt().write(|w| w.set_maxcnt(half_len as _));
let chn = s.rx_ppi_ch.load(Ordering::Relaxed);
ppi::regs().chenset().write(|w| w.0 = 1 << chn);
if r.events_dma().rx().end().read() != 0 {
r.events_dma().rx().end().write_value(0);
let val = s.rx_ended_count.load(Ordering::Relaxed);
s.rx_ended_count.store(val.wrapping_add(1), Ordering::Relaxed);
}
let rx_ended = s.rx_ended_count.load(Ordering::Relaxed);
let rx_started = s.rx_started_count.load(Ordering::Relaxed);
let rxend_happened = rx_started == rx_ended;
let ppi_ch_enabled = ppi::regs().chen().read().ch(chn as _);
if rxend_happened && ppi_ch_enabled {
ppi::regs().chenclr().write(|w| w.set_ch(chn as _, true));
r.tasks_dma().rx().start().write_value(1);
}
rx.push_done(half_len);
s.rx_started_count.store(rx_started.wrapping_add(1), Ordering::Relaxed);
s.rx_started.store(true, Ordering::Relaxed);
} else {
r.intenclr().write(|w| w.set_dmarxready(true));
}
}
}
if let Some(mut tx) = unsafe { s.tx_buf.try_reader() } {
if r.events_dma().tx().end().read() != 0 {
r.events_dma().tx().end().write_value(0);
let n = s.tx_count.load(Ordering::Relaxed);
tx.pop_done(n);
ss.tx_waker.wake();
s.tx_count.store(0, Ordering::Relaxed);
}
if s.tx_count.load(Ordering::Relaxed) == 0 {
let (ptr, len) = tx.pop_buf();
let len = len.min(EASY_DMA_SIZE);
if len != 0 {
s.tx_count.store(len, Ordering::Relaxed);
r.dma().tx().ptr().write_value(ptr as u32);
r.dma().tx().maxcnt().write(|w| w.set_maxcnt(len as _));
r.tasks_dma().tx().start().write_value(1);
}
}
}
}
}
pub struct BufferedUarte<'d> {
tx: BufferedUarteTx<'d>,
rx: BufferedUarteRx<'d>,
}
impl<'d> Unpin for BufferedUarte<'d> {}
impl<'d> BufferedUarte<'d> {
#[allow(clippy::too_many_arguments)]
pub fn new<U: UarteInstance, T: TimerInstance>(
uarte: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, impl ConfigurableChannel>,
ppi_ch2: Peri<'d, impl ConfigurableChannel>,
ppi_group: Peri<'d, impl Group>,
rxd: Peri<'d, impl GpioPin>,
txd: Peri<'d, impl GpioPin>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
config: Config,
rx_buffer: &'d mut [u8],
tx_buffer: &'d mut [u8],
) -> Self {
Self::new_inner(
uarte,
timer,
ppi_ch1.into(),
ppi_ch2.into(),
ppi_group.into(),
rxd.into(),
txd.into(),
None,
None,
config,
rx_buffer,
tx_buffer,
)
}
#[allow(clippy::too_many_arguments)]
pub fn new_with_rtscts<U: UarteInstance, T: TimerInstance>(
uarte: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, impl ConfigurableChannel>,
ppi_ch2: Peri<'d, impl ConfigurableChannel>,
ppi_group: Peri<'d, impl Group>,
rxd: Peri<'d, impl GpioPin>,
txd: Peri<'d, impl GpioPin>,
cts: Peri<'d, impl GpioPin>,
rts: Peri<'d, impl GpioPin>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
config: Config,
rx_buffer: &'d mut [u8],
tx_buffer: &'d mut [u8],
) -> Self {
Self::new_inner(
uarte,
timer,
ppi_ch1.into(),
ppi_ch2.into(),
ppi_group.into(),
rxd.into(),
txd.into(),
Some(cts.into()),
Some(rts.into()),
config,
rx_buffer,
tx_buffer,
)
}
#[allow(clippy::too_many_arguments)]
fn new_inner<U: UarteInstance, T: TimerInstance>(
peri: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, AnyConfigurableChannel>,
ppi_ch2: Peri<'d, AnyConfigurableChannel>,
ppi_group: Peri<'d, AnyGroup>,
rxd: Peri<'d, AnyPin>,
txd: Peri<'d, AnyPin>,
cts: Option<Peri<'d, AnyPin>>,
rts: Option<Peri<'d, AnyPin>>,
config: Config,
rx_buffer: &'d mut [u8],
tx_buffer: &'d mut [u8],
) -> Self {
let r = U::regs();
let irq = U::Interrupt::IRQ;
let state = U::state();
configure(r, config, cts.is_some());
let tx = BufferedUarteTx::new_innerer(unsafe { peri.clone_unchecked() }, txd, cts, tx_buffer);
let rx = BufferedUarteRx::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer);
r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
irq.pend();
unsafe { irq.enable() };
state.tx_rx_refcount.store(2, Ordering::Relaxed);
Self { tx, rx }
}
pub fn set_baudrate(&mut self, baudrate: Baudrate) {
self.tx.set_baudrate(baudrate);
}
pub fn split(self) -> (BufferedUarteRx<'d>, BufferedUarteTx<'d>) {
(self.rx, self.tx)
}
pub fn split_by_ref(&mut self) -> (&mut BufferedUarteRx<'d>, &mut BufferedUarteTx<'d>) {
(&mut self.rx, &mut self.tx)
}
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
self.rx.read(buf).await
}
pub async fn fill_buf(&mut self) -> Result<&[u8], Error> {
self.rx.fill_buf().await
}
pub fn consume(&mut self, amt: usize) {
self.rx.consume(amt)
}
pub async fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
self.tx.write(buf).await
}
pub fn try_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
self.tx.try_write(buf)
}
pub async fn flush(&mut self) -> Result<(), Error> {
self.tx.flush().await
}
}
pub struct BufferedUarteTx<'d> {
r: pac::uarte::Uarte,
_irq: interrupt::Interrupt,
state: &'static crate::uarte::State,
buffered_state: &'static State,
_p: PhantomData<&'d ()>,
}
impl<'d> BufferedUarteTx<'d> {
pub fn new<U: UarteInstance>(
uarte: Peri<'d, U>,
txd: Peri<'d, impl GpioPin>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
config: Config,
tx_buffer: &'d mut [u8],
) -> Self {
Self::new_inner(uarte, txd.into(), None, config, tx_buffer)
}
pub fn new_with_cts<U: UarteInstance>(
uarte: Peri<'d, U>,
txd: Peri<'d, impl GpioPin>,
cts: Peri<'d, impl GpioPin>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
config: Config,
tx_buffer: &'d mut [u8],
) -> Self {
Self::new_inner(uarte, txd.into(), Some(cts.into()), config, tx_buffer)
}
fn new_inner<U: UarteInstance>(
peri: Peri<'d, U>,
txd: Peri<'d, AnyPin>,
cts: Option<Peri<'d, AnyPin>>,
config: Config,
tx_buffer: &'d mut [u8],
) -> Self {
let r = U::regs();
let irq = U::Interrupt::IRQ;
let state = U::state();
let _buffered_state = U::buffered_state();
configure(r, config, cts.is_some());
let this = Self::new_innerer(peri, txd, cts, tx_buffer);
r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
irq.pend();
unsafe { irq.enable() };
state.tx_rx_refcount.store(1, Ordering::Relaxed);
this
}
fn new_innerer<U: UarteInstance>(
_peri: Peri<'d, U>,
txd: Peri<'d, AnyPin>,
cts: Option<Peri<'d, AnyPin>>,
tx_buffer: &'d mut [u8],
) -> Self {
let r = U::regs();
let irq = U::Interrupt::IRQ;
let state = U::state();
let buffered_state = U::buffered_state();
configure_tx_pins(r, txd, cts);
buffered_state.tx_count.store(0, Ordering::Relaxed);
let len = tx_buffer.len();
unsafe { buffered_state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
r.events_dma().tx().ready().write_value(0);
r.intenset().write(|w| {
w.set_dmatxend(true);
});
Self {
r,
_irq: irq,
state,
buffered_state,
_p: PhantomData,
}
}
pub fn write<'a>(&'a mut self, buf: &'a [u8]) -> impl Future<Output = Result<usize, Error>> + 'a + use<'a, 'd> {
poll_fn(move |cx| {
let ss = self.state;
let s = self.buffered_state;
let mut tx = unsafe { s.tx_buf.writer() };
let tx_buf = tx.push_slice();
if tx_buf.is_empty() {
ss.tx_waker.register(cx.waker());
return Poll::Pending;
}
let n = min(tx_buf.len(), buf.len());
tx_buf[..n].copy_from_slice(&buf[..n]);
tx.push_done(n);
compiler_fence(Ordering::SeqCst);
self._irq.pend();
Poll::Ready(Ok(n))
})
}
pub fn try_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
let s = self.buffered_state;
let mut tx = unsafe { s.tx_buf.writer() };
let tx_buf = tx.push_slice();
if tx_buf.is_empty() {
return Ok(0);
}
let n = min(tx_buf.len(), buf.len());
tx_buf[..n].copy_from_slice(&buf[..n]);
tx.push_done(n);
compiler_fence(Ordering::SeqCst);
self._irq.pend();
Ok(n)
}
pub fn flush(&mut self) -> impl Future<Output = Result<(), Error>> + '_ {
let ss = self.state;
let s = self.buffered_state;
poll_fn(move |cx| {
if !s.tx_buf.is_empty() {
ss.tx_waker.register(cx.waker());
return Poll::Pending;
}
Poll::Ready(Ok(()))
})
}
pub fn set_baudrate(&mut self, baudrate: Baudrate) {
self.r.baudrate().write(|w| w.set_baudrate(baudrate));
}
}
impl<'a> Drop for BufferedUarteTx<'a> {
fn drop(&mut self) {
let r = self.r;
r.intenclr().write(|w| {
w.set_txdrdy(true);
w.set_dmatxready(true);
w.set_txstopped(true);
});
r.events_txstopped().write_value(0);
r.tasks_dma().tx().stop().write_value(1);
while r.events_txstopped().read() == 0 {}
let s = self.buffered_state;
unsafe { s.tx_buf.deinit() }
let s = self.state;
drop_tx_rx(r, s);
}
}
pub struct BufferedUarteRx<'d> {
r: pac::uarte::Uarte,
state: &'static crate::uarte::State,
buffered_state: &'static State,
timer: Timer<'d>,
_ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 1>,
_ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 2>,
_ppi_group: PpiGroup<'d, AnyGroup>,
_p: PhantomData<&'d ()>,
}
impl<'d> BufferedUarteRx<'d> {
#[allow(clippy::too_many_arguments)]
pub fn new<U: UarteInstance, T: TimerInstance>(
uarte: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, impl ConfigurableChannel>,
ppi_ch2: Peri<'d, impl ConfigurableChannel>,
ppi_group: Peri<'d, impl Group>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
rxd: Peri<'d, impl GpioPin>,
config: Config,
rx_buffer: &'d mut [u8],
) -> Self {
Self::new_inner(
uarte,
timer,
ppi_ch1.into(),
ppi_ch2.into(),
ppi_group.into(),
rxd.into(),
None,
config,
rx_buffer,
)
}
#[allow(clippy::too_many_arguments)]
pub fn new_with_rts<U: UarteInstance, T: TimerInstance>(
uarte: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, impl ConfigurableChannel>,
ppi_ch2: Peri<'d, impl ConfigurableChannel>,
ppi_group: Peri<'d, impl Group>,
rxd: Peri<'d, impl GpioPin>,
rts: Peri<'d, impl GpioPin>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
config: Config,
rx_buffer: &'d mut [u8],
) -> Self {
Self::new_inner(
uarte,
timer,
ppi_ch1.into(),
ppi_ch2.into(),
ppi_group.into(),
rxd.into(),
Some(rts.into()),
config,
rx_buffer,
)
}
#[allow(clippy::too_many_arguments)]
fn new_inner<U: UarteInstance, T: TimerInstance>(
peri: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, AnyConfigurableChannel>,
ppi_ch2: Peri<'d, AnyConfigurableChannel>,
ppi_group: Peri<'d, AnyGroup>,
rxd: Peri<'d, AnyPin>,
rts: Option<Peri<'d, AnyPin>>,
config: Config,
rx_buffer: &'d mut [u8],
) -> Self {
let r = U::regs();
let irq = U::Interrupt::IRQ;
let state = U::state();
let _buffered_state = U::buffered_state();
configure(r, config, rts.is_some());
let this = Self::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer);
r.enable().write(|w| w.set_enable(vals::Enable::ENABLED));
irq.pend();
unsafe { irq.enable() };
state.tx_rx_refcount.store(1, Ordering::Relaxed);
this
}
#[allow(clippy::too_many_arguments)]
fn new_innerer<U: UarteInstance, T: TimerInstance>(
_peri: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, AnyConfigurableChannel>,
ppi_ch2: Peri<'d, AnyConfigurableChannel>,
ppi_group: Peri<'d, AnyGroup>,
rxd: Peri<'d, AnyPin>,
rts: Option<Peri<'d, AnyPin>>,
rx_buffer: &'d mut [u8],
) -> Self {
assert!(rx_buffer.len() % 2 == 0);
let r = U::regs();
let state = U::state();
let buffered_state = U::buffered_state();
configure_rx_pins(r, rxd, rts);
buffered_state.rx_started_count.store(0, Ordering::Relaxed);
buffered_state.rx_ended_count.store(0, Ordering::Relaxed);
buffered_state.rx_started.store(false, Ordering::Relaxed);
buffered_state.rx_overrun.store(false, Ordering::Relaxed);
let rx_len = rx_buffer.len().min(EASY_DMA_SIZE * 2);
unsafe { buffered_state.rx_buf.init(rx_buffer.as_mut_ptr(), rx_len) };
let errors = r.errorsrc().read();
r.errorsrc().write_value(errors);
r.events_dma().rx().ready().write_value(0);
r.events_error().write_value(0);
r.events_dma().rx().end().write_value(0);
r.intenset().write(|w| {
w.set_dmatxend(true);
w.set_dmarxready(true);
w.set_error(true);
w.set_dmarxend(true);
});
let timer = Timer::new_counter(timer);
timer.cc(1).write(rx_len as u32 * 2);
timer.cc(1).short_compare_clear();
timer.clear();
timer.start();
let mut ppi_ch1 = Ppi::new_one_to_one(ppi_ch1, Event::from_reg(r.events_rxdrdy()), timer.task_count());
ppi_ch1.enable();
buffered_state
.rx_ppi_ch
.store(ppi_ch2.number() as u8, Ordering::Relaxed);
let mut ppi_group = PpiGroup::new(ppi_group);
let mut ppi_ch2 = Ppi::new_one_to_two(
ppi_ch2,
Event::from_reg(r.events_dma().rx().end()),
Task::from_reg(r.tasks_dma().rx().start()),
ppi_group.task_disable_all(),
);
ppi_ch2.disable();
ppi_group.add_channel(&ppi_ch2);
Self {
r,
state,
buffered_state,
timer,
_ppi_ch1: ppi_ch1,
_ppi_ch2: ppi_ch2,
_ppi_group: ppi_group,
_p: PhantomData,
}
}
fn get_rxdrdy_counter(&self) -> usize {
let s = self.buffered_state;
let timer = &self.timer;
timer.cc(0).capture();
let mut rxdrdy = timer.cc(0).read() as usize;
if rxdrdy > s.rx_buf.len() * 2 {
rxdrdy = 0;
}
rxdrdy
}
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let data = self.fill_buf().await?;
let n = data.len().min(buf.len());
buf[..n].copy_from_slice(&data[..n]);
self.consume(n);
Ok(n)
}
pub fn fill_buf(&mut self) -> impl Future<Output = Result<&'_ [u8], Error>> {
let r = self.r;
let s = self.buffered_state;
let ss = self.state;
poll_fn(move |cx| {
compiler_fence(Ordering::SeqCst);
if s.rx_overrun.swap(false, Ordering::Acquire) {
return Poll::Ready(Err(Error::Overrun));
}
let mut end = self.get_rxdrdy_counter();
let mut start = s.rx_buf.start.load(Ordering::Relaxed);
let len = s.rx_buf.len();
if start == end {
ss.rx_waker.register(cx.waker());
r.intenset().write(|w| w.set_rxdrdy(true));
return Poll::Pending;
}
if start >= len {
start -= len
}
if end >= len {
end -= len
}
let n = if end > start { end - start } else { len - start };
assert!(n != 0);
let buf = s.rx_buf.buf.load(Ordering::Relaxed);
Poll::Ready(Ok(unsafe { slice::from_raw_parts(buf.add(start), n) }))
})
}
pub fn consume(&mut self, amt: usize) {
if amt == 0 {
return;
}
let s = self.buffered_state;
let mut rx = unsafe { s.rx_buf.reader() };
rx.pop_done(amt);
self.r.intenset().write(|w| w.set_dmarxready(true));
}
fn read_ready(&self) -> Result<bool, Error> {
let state = self.buffered_state;
if state.rx_overrun.swap(false, Ordering::Acquire) {
return Err(Error::Overrun);
}
let start = state.rx_buf.start.load(Ordering::Relaxed);
let end = self.get_rxdrdy_counter();
Ok(start != end)
}
}
impl<'a> Drop for BufferedUarteRx<'a> {
fn drop(&mut self) {
self._ppi_group.disable_all();
let r = self.r;
self.timer.stop();
r.intenclr().write(|w| {
w.set_rxdrdy(true);
w.set_dmarxready(true);
w.set_rxto(true);
});
r.events_rxto().write_value(0);
r.tasks_dma().rx().stop().write_value(1);
while r.events_rxto().read() == 0 {}
let s = self.buffered_state;
unsafe { s.rx_buf.deinit() }
let s = self.state;
drop_tx_rx(r, s);
}
}
impl core::fmt::Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match *self {
Error::Overrun => write!(f, "Buffer Overrun"),
}
}
}
impl core::error::Error for Error {}
mod _embedded_io {
use super::*;
impl embedded_io_async::Error for Error {
fn kind(&self) -> embedded_io_async::ErrorKind {
match *self {
Error::Overrun => embedded_io_async::ErrorKind::OutOfMemory,
}
}
}
impl<'d> embedded_io_async::ErrorType for BufferedUarte<'d> {
type Error = Error;
}
impl<'d> embedded_io_async::ErrorType for BufferedUarteRx<'d> {
type Error = Error;
}
impl<'d> embedded_io_async::ErrorType for BufferedUarteTx<'d> {
type Error = Error;
}
impl<'d> embedded_io_async::Read for BufferedUarte<'d> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.read(buf).await
}
}
impl<'d> embedded_io_async::Read for BufferedUarteRx<'d> {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.read(buf).await
}
}
impl<'d> embedded_io_async::ReadReady for BufferedUarte<'d> {
fn read_ready(&mut self) -> Result<bool, Self::Error> {
self.rx.read_ready()
}
}
impl<'d> embedded_io_async::ReadReady for BufferedUarteRx<'d> {
fn read_ready(&mut self) -> Result<bool, Self::Error> {
let state = self.buffered_state;
Ok(!state.rx_buf.is_empty())
}
}
impl<'d> embedded_io_async::BufRead for BufferedUarte<'d> {
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
self.fill_buf().await
}
fn consume(&mut self, amt: usize) {
self.consume(amt)
}
}
impl<'d> embedded_io_async::BufRead for BufferedUarteRx<'d> {
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
self.fill_buf().await
}
fn consume(&mut self, amt: usize) {
self.consume(amt)
}
}
impl<'d> embedded_io_async::Write for BufferedUarte<'d> {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write(buf).await
}
async fn flush(&mut self) -> Result<(), Self::Error> {
self.flush().await
}
}
impl<'d> embedded_io_async::Write for BufferedUarteTx<'d> {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write(buf).await
}
async fn flush(&mut self) -> Result<(), Self::Error> {
self.flush().await
}
}
}