Cleanup BufferedUarte
This commit is contained in:
parent
3a4dbfa52e
commit
607e67f51a
@ -33,12 +33,25 @@ enum RxState {
|
|||||||
ReceivingReady,
|
ReceivingReady,
|
||||||
Stopping,
|
Stopping,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
enum TxState {
|
enum TxState {
|
||||||
Idle,
|
Idle,
|
||||||
Transmitting(usize),
|
Transmitting(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct State<'a, T: Instance> {
|
||||||
|
inner: T,
|
||||||
|
|
||||||
|
rx: RingBuffer<'a>,
|
||||||
|
rx_state: RxState,
|
||||||
|
rx_waker: WakerRegistration,
|
||||||
|
|
||||||
|
tx: RingBuffer<'a>,
|
||||||
|
tx_state: TxState,
|
||||||
|
tx_waker: WakerRegistration,
|
||||||
|
}
|
||||||
|
|
||||||
/// Interface to a UARTE instance
|
/// Interface to a UARTE instance
|
||||||
///
|
///
|
||||||
/// This is a very basic interface that comes with the following limitations:
|
/// This is a very basic interface that comes with the following limitations:
|
||||||
@ -145,6 +158,10 @@ impl<'a, T: Instance> BufferedUarte<'a, T> {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<T::Interrupt, State<'a, T>>> {
|
||||||
|
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Instance> Drop for BufferedUarte<'a, T> {
|
impl<'a, T: Instance> Drop for BufferedUarte<'a, T> {
|
||||||
@ -156,111 +173,71 @@ impl<'a, T: Instance> Drop for BufferedUarte<'a, T> {
|
|||||||
|
|
||||||
impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> {
|
impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> {
|
||||||
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
|
fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
|
||||||
let this = unsafe { self.get_unchecked_mut() };
|
self.inner().with(|_irq, state| {
|
||||||
let reg = unsafe { Pin::new_unchecked(&mut this.inner) };
|
// Conservative compiler fence to prevent optimizations that do not
|
||||||
reg.with(|_irq, state| {
|
// take in to account actions by DMA. The fence has been placed here,
|
||||||
let z: Poll<Result<&[u8]>> = state.poll_fill_buf(cx);
|
// before any DMA action has started
|
||||||
let z: Poll<Result<&[u8]>> = unsafe { mem::transmute(z) };
|
compiler_fence(Ordering::SeqCst);
|
||||||
z
|
trace!("poll_read");
|
||||||
|
|
||||||
|
// We have data ready in buffer? Return it.
|
||||||
|
let buf = state.rx.pop_buf();
|
||||||
|
if buf.len() != 0 {
|
||||||
|
trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len());
|
||||||
|
let buf: &[u8] = buf;
|
||||||
|
let buf: &[u8] = unsafe { mem::transmute(buf) };
|
||||||
|
return Poll::Ready(Ok(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
trace!(" empty");
|
||||||
|
|
||||||
|
if state.rx_state == RxState::ReceivingReady {
|
||||||
|
trace!(" stopping");
|
||||||
|
state.rx_state = RxState::Stopping;
|
||||||
|
state.inner.tasks_stoprx.write(|w| unsafe { w.bits(1) });
|
||||||
|
}
|
||||||
|
|
||||||
|
state.rx_waker.register(cx.waker());
|
||||||
|
Poll::<Result<&[u8]>>::Pending
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn consume(self: Pin<&mut Self>, amt: usize) {
|
fn consume(self: Pin<&mut Self>, amt: usize) {
|
||||||
let this = unsafe { self.get_unchecked_mut() };
|
self.inner().with(|irq, state| {
|
||||||
let reg = unsafe { Pin::new_unchecked(&mut this.inner) };
|
trace!("consume {:?}", amt);
|
||||||
reg.with(|irq, state| state.consume(irq, amt))
|
state.rx.pop(amt);
|
||||||
|
irq.pend();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Instance> AsyncWrite for BufferedUarte<'a, T> {
|
impl<'a, T: Instance> AsyncWrite for BufferedUarte<'a, T> {
|
||||||
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
|
fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
|
||||||
let this = unsafe { self.get_unchecked_mut() };
|
self.inner().with(|irq, state| {
|
||||||
let reg = unsafe { Pin::new_unchecked(&mut this.inner) };
|
trace!("poll_write: {:?}", buf.len());
|
||||||
reg.with(|irq, state| state.poll_write(irq, cx, buf))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================================
|
let tx_buf = state.tx.push_buf();
|
||||||
// ====================================
|
if tx_buf.len() == 0 {
|
||||||
// ====================================
|
trace!("poll_write: pending");
|
||||||
|
state.tx_waker.register(cx.waker());
|
||||||
|
return Poll::Pending;
|
||||||
|
}
|
||||||
|
|
||||||
// public because it needs to be used in Instance trait, but
|
let n = min(tx_buf.len(), buf.len());
|
||||||
// should not be used outside the module
|
tx_buf[..n].copy_from_slice(&buf[..n]);
|
||||||
#[doc(hidden)]
|
state.tx.push(n);
|
||||||
pub struct State<'a, T: Instance> {
|
|
||||||
inner: T,
|
|
||||||
|
|
||||||
rx: RingBuffer<'a>,
|
trace!("poll_write: queued {:?}", n);
|
||||||
rx_state: RxState,
|
|
||||||
rx_waker: WakerRegistration,
|
|
||||||
|
|
||||||
tx: RingBuffer<'a>,
|
// Conservative compiler fence to prevent optimizations that do not
|
||||||
tx_state: TxState,
|
// take in to account actions by DMA. The fence has been placed here,
|
||||||
tx_waker: WakerRegistration,
|
// before any DMA action has started
|
||||||
}
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
|
||||||
impl<'a, T: Instance> State<'a, T> {
|
irq.pend();
|
||||||
fn poll_fill_buf(&mut self, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
|
|
||||||
// Conservative compiler fence to prevent optimizations that do not
|
|
||||||
// take in to account actions by DMA. The fence has been placed here,
|
|
||||||
// before any DMA action has started
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
trace!("poll_read");
|
|
||||||
|
|
||||||
// We have data ready in buffer? Return it.
|
Poll::Ready(Ok(n))
|
||||||
let buf = self.rx.pop_buf();
|
})
|
||||||
if buf.len() != 0 {
|
|
||||||
trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len());
|
|
||||||
return Poll::Ready(Ok(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
trace!(" empty");
|
|
||||||
|
|
||||||
if self.rx_state == RxState::ReceivingReady {
|
|
||||||
trace!(" stopping");
|
|
||||||
self.rx_state = RxState::Stopping;
|
|
||||||
self.inner.tasks_stoprx.write(|w| unsafe { w.bits(1) });
|
|
||||||
}
|
|
||||||
|
|
||||||
self.rx_waker.register(cx.waker());
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consume(&mut self, irq: &mut T::Interrupt, amt: usize) {
|
|
||||||
trace!("consume {:?}", amt);
|
|
||||||
self.rx.pop(amt);
|
|
||||||
irq.pend();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll_write(
|
|
||||||
&mut self,
|
|
||||||
irq: &mut T::Interrupt,
|
|
||||||
cx: &mut Context<'_>,
|
|
||||||
buf: &[u8],
|
|
||||||
) -> Poll<Result<usize>> {
|
|
||||||
trace!("poll_write: {:?}", buf.len());
|
|
||||||
|
|
||||||
let tx_buf = self.tx.push_buf();
|
|
||||||
if tx_buf.len() == 0 {
|
|
||||||
trace!("poll_write: pending");
|
|
||||||
self.tx_waker.register(cx.waker());
|
|
||||||
return Poll::Pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
let n = min(tx_buf.len(), buf.len());
|
|
||||||
tx_buf[..n].copy_from_slice(&buf[..n]);
|
|
||||||
self.tx.push(n);
|
|
||||||
|
|
||||||
trace!("poll_write: queued {:?}", n);
|
|
||||||
|
|
||||||
// Conservative compiler fence to prevent optimizations that do not
|
|
||||||
// take in to account actions by DMA. The fence has been placed here,
|
|
||||||
// before any DMA action has started
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
|
||||||
|
|
||||||
irq.pend();
|
|
||||||
|
|
||||||
Poll::Ready(Ok(n))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user