use core::future::{poll_fn, Future};
use core::slice;
use core::task::Poll;
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
use embassy_hal_common::atomic_ring_buffer::RingBuffer;
use embassy_sync::waitqueue::AtomicWaker;
use super::*;
pub struct State {
tx_waker: AtomicWaker,
tx_buf: RingBuffer,
rx_waker: AtomicWaker,
rx_buf: RingBuffer,
}
impl State {
pub const fn new() -> Self {
Self {
rx_buf: RingBuffer::new(),
tx_buf: RingBuffer::new(),
rx_waker: AtomicWaker::new(),
tx_waker: AtomicWaker::new(),
}
}
}
pub struct BufferedUart<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
}
pub struct BufferedUartRx<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
}
pub struct BufferedUartTx<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
}
impl<'d, T: Instance> BufferedUart<'d, T> {
pub fn new(
_uart: impl Peripheral
+ 'd,
irq: impl Peripheral
+ 'd,
tx: impl Peripheral
> + 'd,
rx: impl Peripheral
> + 'd,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(tx, rx);
Self::new_inner(
irq,
tx.map_into(),
rx.map_into(),
None,
None,
tx_buffer,
rx_buffer,
config,
)
}
pub fn new_with_rtscts(
_uart: impl Peripheral
+ 'd,
irq: impl Peripheral
+ 'd,
tx: impl Peripheral
> + 'd,
rx: impl Peripheral
> + 'd,
rts: impl Peripheral
> + 'd,
cts: impl Peripheral
> + 'd,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(tx, rx, cts, rts);
Self::new_inner(
irq,
tx.map_into(),
rx.map_into(),
Some(rts.map_into()),
Some(cts.map_into()),
tx_buffer,
rx_buffer,
config,
)
}
fn new_inner(
irq: impl Peripheral
+ 'd,
mut tx: PeripheralRef<'d, AnyPin>,
mut rx: PeripheralRef<'d, AnyPin>,
mut rts: Option>,
mut cts: Option>,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(irq);
super::Uart::<'d, T, Async>::init(
Some(tx.reborrow()),
Some(rx.reborrow()),
rts.as_mut().map(|x| x.reborrow()),
cts.as_mut().map(|x| x.reborrow()),
config,
);
let state = T::state();
let regs = T::regs();
let len = tx_buffer.len();
unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
let len = rx_buffer.len();
unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
unsafe {
regs.uartimsc().modify(|w| {
w.set_rxim(true);
w.set_rtim(true);
w.set_txim(true);
});
}
irq.set_handler(on_interrupt::);
irq.unpend();
irq.enable();
Self { phantom: PhantomData }
}
pub fn split(&mut self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) {
(
BufferedUartRx { phantom: PhantomData },
BufferedUartTx { phantom: PhantomData },
)
}
}
impl<'d, T: Instance> BufferedUartRx<'d, T> {
pub fn new(
_uart: impl Peripheral + 'd,
irq: impl Peripheral
+ 'd,
rx: impl Peripheral
> + 'd,
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(rx);
Self::new_inner(irq, rx.map_into(), None, rx_buffer, config)
}
pub fn new_with_rts(
_uart: impl Peripheral
+ 'd,
irq: impl Peripheral
+ 'd,
rx: impl Peripheral
> + 'd,
rts: impl Peripheral
> + 'd,
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(rx, rts);
Self::new_inner(irq, rx.map_into(), Some(rts.map_into()), rx_buffer, config)
}
fn new_inner(
irq: impl Peripheral
+ 'd,
mut rx: PeripheralRef<'d, AnyPin>,
mut rts: Option>,
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(irq);
super::Uart::<'d, T, Async>::init(
None,
Some(rx.reborrow()),
rts.as_mut().map(|x| x.reborrow()),
None,
config,
);
let state = T::state();
let regs = T::regs();
let len = rx_buffer.len();
unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
unsafe {
regs.uartimsc().modify(|w| {
w.set_rxim(true);
w.set_rtim(true);
});
}
irq.set_handler(on_interrupt::);
irq.unpend();
irq.enable();
Self { phantom: PhantomData }
}
fn read<'a>(buf: &'a mut [u8]) -> impl Future