diff --git a/embassy-hal-common/src/atomic_ring_buffer.rs b/embassy-hal-common/src/atomic_ring_buffer.rs new file mode 100644 index 00000000..58cf2a3e --- /dev/null +++ b/embassy-hal-common/src/atomic_ring_buffer.rs @@ -0,0 +1,154 @@ +use core::slice; +use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; + +pub struct RingBuffer { + buf: AtomicPtr, + len: AtomicUsize, + start: AtomicUsize, + end: AtomicUsize, +} + +pub struct Reader<'a>(&'a RingBuffer); +pub struct Writer<'a>(&'a RingBuffer); + +impl RingBuffer { + pub const fn new() -> Self { + Self { + buf: AtomicPtr::new(core::ptr::null_mut()), + len: AtomicUsize::new(0), + start: AtomicUsize::new(0), + end: AtomicUsize::new(0), + } + } + + /// # Safety + /// - The buffer (`buf .. buf+len`) must be valid memory until `deinit` is called. + /// - Must not be called concurrently with any other methods. + pub unsafe fn init(&self, buf: *mut u8, len: usize) { + self.buf.store(buf, Ordering::Relaxed); + self.len.store(len, Ordering::Relaxed); + self.start.store(0, Ordering::Relaxed); + self.end.store(0, Ordering::Relaxed); + } + + pub unsafe fn deinit(&self) { + self.len.store(0, Ordering::Relaxed); + } + + pub unsafe fn reader(&self) -> Reader<'_> { + Reader(self) + } + + pub unsafe fn writer(&self) -> Writer<'_> { + Writer(self) + } + + pub fn is_full(&self) -> bool { + let start = self.start.load(Ordering::Relaxed); + let end = self.end.load(Ordering::Relaxed); + + self.wrap(end + 1) == start + } + + pub fn is_empty(&self) -> bool { + let start = self.start.load(Ordering::Relaxed); + let end = self.end.load(Ordering::Relaxed); + + start == end + } + + pub fn wrap(&self, n: usize) -> usize { + let len = self.len.load(Ordering::Relaxed); + + assert!(n <= len); + if n == len { + 0 + } else { + n + } + } +} + +impl<'a> Writer<'a> { + pub fn push(&self, f: impl FnOnce(&mut [u8]) -> usize) -> usize { + let (p, n) = self.push_buf(); + let buf = unsafe { slice::from_raw_parts_mut(p, n) }; + let n = f(buf); + self.push_done(n); + n + } + + pub fn push_one(&self, val: u8) -> bool { + let n = self.push(|f| match f { + [] => 0, + [x, ..] => { + *x = val; + 1 + } + }); + n != 0 + } + + pub fn push_buf(&self) -> (*mut u8, usize) { + let start = self.0.start.load(Ordering::Acquire); + let buf = self.0.buf.load(Ordering::Relaxed); + let len = self.0.len.load(Ordering::Relaxed); + let end = self.0.end.load(Ordering::Relaxed); + + let n = if start <= end { + len - end - (start == 0) as usize + } else { + start - end - 1 + }; + + trace!(" ringbuf: push_buf {:?}..{:?}", end, end + n); + (unsafe { buf.add(end) }, n) + } + + pub fn push_done(&self, n: usize) { + trace!(" ringbuf: push {:?}", n); + let end = self.0.end.load(Ordering::Relaxed); + self.0.end.store(self.0.wrap(end + n), Ordering::Release); + } +} + +impl<'a> Reader<'a> { + pub fn pop(&self, f: impl FnOnce(&[u8]) -> usize) -> usize { + let (p, n) = self.pop_buf(); + let buf = unsafe { slice::from_raw_parts(p, n) }; + let n = f(buf); + self.pop_done(n); + n + } + + pub fn pop_one(&self) -> Option { + let mut res = None; + self.pop(|f| match f { + &[] => 0, + &[x, ..] => { + res = Some(x); + 1 + } + }); + res + } + + pub fn pop_buf(&self) -> (*mut u8, usize) { + let end = self.0.end.load(Ordering::Acquire); + let buf = self.0.buf.load(Ordering::Relaxed); + let len = self.0.len.load(Ordering::Relaxed); + let start = self.0.start.load(Ordering::Relaxed); + + let n = if end < start { len - start } else { end - start }; + + trace!(" ringbuf: pop_buf {:?}..{:?}", start, start + n); + (unsafe { buf.add(start) }, n) + } + + pub fn pop_done(&self, n: usize) { + trace!(" ringbuf: pop {:?}", n); + + let start = self.0.start.load(Ordering::Relaxed); + self.0.start.store(self.0.wrap(start + n), Ordering::Release); + } +} diff --git a/embassy-hal-common/src/lib.rs b/embassy-hal-common/src/lib.rs index 5d2649d0..b2a35cd3 100644 --- a/embassy-hal-common/src/lib.rs +++ b/embassy-hal-common/src/lib.rs @@ -4,6 +4,7 @@ // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; +pub mod atomic_ring_buffer; pub mod drop; mod macros; mod peripheral; diff --git a/embassy-rp/src/interrupt.rs b/embassy-rp/src/interrupt.rs index f21a5433..065890f0 100644 --- a/embassy-rp/src/interrupt.rs +++ b/embassy-rp/src/interrupt.rs @@ -34,3 +34,27 @@ declare!(ADC_IRQ_FIFO); declare!(I2C0_IRQ); declare!(I2C1_IRQ); declare!(RTC_IRQ); + +pub trait InterruptFunction { + fn on_interrupt(); +} + +// Marker trait +pub unsafe trait Registration {} + +#[macro_export] +macro_rules! register_interrupts { + ($name:ident: $($irq:ident),*) => { + struct $name; + + $( + #[allow(non_snake_case)] + #[no_mangle] + extern "C" fn $irq() { + <$crate::interrupt::$irq as $crate::interrupt::InterruptFunction>::on_interrupt(); + } + + unsafe impl $crate::interrupt::Registration<$crate::interrupt::$irq> for $name {} + )* + }; +} diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index 4f0a5553..be281a1b 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs @@ -1,339 +1,335 @@ use core::future::{poll_fn, Future}; -use core::task::{Poll, Waker}; +use core::slice; +use core::task::Poll; -use atomic_polyfill::{compiler_fence, Ordering}; -use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; -use embassy_hal_common::ring_buffer::RingBuffer; -use embassy_sync::waitqueue::WakerRegistration; +use cortex_m::peripheral::NVIC; +use embassy_hal_common::atomic_ring_buffer::RingBuffer; +use embassy_sync::waitqueue::AtomicWaker; use super::*; +use crate::interrupt::Registration; -pub struct State<'d, T: Instance>(StateStorage>); -impl<'d, T: Instance> State<'d, T> { +pub(crate) struct State { + tx_waker: AtomicWaker, + tx_buf: RingBuffer, + rx_waker: AtomicWaker, + rx_buf: RingBuffer, +} + +impl State { pub const fn new() -> Self { - Self(StateStorage::new()) + Self { + rx_buf: RingBuffer::new(), + tx_buf: RingBuffer::new(), + rx_waker: AtomicWaker::new(), + tx_waker: AtomicWaker::new(), + } } } -pub struct RxState<'d, T: Instance>(StateStorage>); -impl<'d, T: Instance> RxState<'d, T> { - pub const fn new() -> Self { - Self(StateStorage::new()) - } +pub struct BufferedUart<'d> { + info: &'static Info, + phantom: PhantomData<&'d mut ()>, } -pub struct TxState<'d, T: Instance>(StateStorage>); -impl<'d, T: Instance> TxState<'d, T> { - pub const fn new() -> Self { - Self(StateStorage::new()) - } +pub struct BufferedUartRx<'d> { + info: &'static Info, + phantom: PhantomData<&'d mut ()>, } -struct RxStateInner<'d, T: Instance> { - phantom: PhantomData<&'d mut T>, - - waker: WakerRegistration, - buf: RingBuffer<'d>, +pub struct BufferedUartTx<'d> { + info: &'static Info, + phantom: PhantomData<&'d mut ()>, } -struct TxStateInner<'d, T: Instance> { - phantom: PhantomData<&'d mut T>, - - waker: WakerRegistration, - buf: RingBuffer<'d>, -} - -struct FullStateInner<'d, T: Instance> { - rx: RxStateInner<'d, T>, - tx: TxStateInner<'d, T>, -} - -unsafe impl<'d, T: Instance> Send for RxStateInner<'d, T> {} -unsafe impl<'d, T: Instance> Sync for RxStateInner<'d, T> {} - -unsafe impl<'d, T: Instance> Send for TxStateInner<'d, T> {} -unsafe impl<'d, T: Instance> Sync for TxStateInner<'d, T> {} - -unsafe impl<'d, T: Instance> Send for FullStateInner<'d, T> {} -unsafe impl<'d, T: Instance> Sync for FullStateInner<'d, T> {} - -pub struct BufferedUart<'d, T: Instance> { - inner: PeripheralMutex<'d, FullStateInner<'d, T>>, -} - -pub struct BufferedUartRx<'d, T: Instance> { - inner: PeripheralMutex<'d, RxStateInner<'d, T>>, -} - -pub struct BufferedUartTx<'d, T: Instance> { - inner: PeripheralMutex<'d, TxStateInner<'d, T>>, -} - -impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {} -impl<'d, T: Instance> Unpin for BufferedUartRx<'d, T> {} -impl<'d, T: Instance> Unpin for BufferedUartTx<'d, T> {} - -impl<'d, T: Instance> BufferedUart<'d, T> { - pub fn new( - state: &'d mut State<'d, T>, - _uart: Uart<'d, T, M>, - irq: impl Peripheral

+ 'd, +impl<'d> BufferedUart<'d> { + pub fn new( + _uart: impl Peripheral

+ 'd, + _irq: impl Registration, + tx: impl Peripheral

> + 'd, + rx: impl Peripheral

> + 'd, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], - ) -> BufferedUart<'d, T> { - into_ref!(irq); + config: Config, + ) -> Self { + into_ref!(tx, rx); + Self::new_inner( + T::info(), + tx.map_into(), + rx.map_into(), + None, + None, + tx_buffer, + rx_buffer, + config, + ) + } + + pub fn new_with_rtscts( + _uart: impl Peripheral

+ 'd, + _irq: impl Registration, + 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( + T::info(), + tx.map_into(), + rx.map_into(), + Some(rts.map_into()), + Some(cts.map_into()), + tx_buffer, + rx_buffer, + config, + ) + } + + fn new_inner( + info: &'static Info, + 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 { + init( + info, + Some(tx.reborrow()), + Some(rx.reborrow()), + rts.as_mut().map(|x| x.reborrow()), + cts.as_mut().map(|x| x.reborrow()), + config, + ); + + let len = tx_buffer.len(); + unsafe { info.state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; + let len = rx_buffer.len(); + unsafe { info.state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; - let r = T::regs(); unsafe { - r.uartimsc().modify(|w| { + info.regs.uartimsc().modify(|w| { w.set_rxim(true); w.set_rtim(true); w.set_txim(true); }); + + NVIC::unpend(info.irq); + NVIC::unmask(info.irq); + NVIC::pend(info.irq); } Self { - inner: PeripheralMutex::new(irq, &mut state.0, move || FullStateInner { - tx: TxStateInner { - phantom: PhantomData, - waker: WakerRegistration::new(), - buf: RingBuffer::new(tx_buffer), - }, - rx: RxStateInner { - phantom: PhantomData, - waker: WakerRegistration::new(), - buf: RingBuffer::new(rx_buffer), - }, - }), + info, + phantom: PhantomData, } } } -impl<'d, T: Instance> BufferedUartRx<'d, T> { - pub fn new( - state: &'d mut RxState<'d, T>, - _uart: UartRx<'d, T, M>, - irq: impl Peripheral

+ 'd, +impl<'d> BufferedUartRx<'d> { + pub fn new( + _uart: impl Peripheral

+ 'd, + irq: impl Registration, rx_buffer: &'d mut [u8], - ) -> BufferedUartRx<'d, T> { - into_ref!(irq); - - let r = T::regs(); + config: Config, + ) -> BufferedUartRx<'d> { + let info = T::info(); unsafe { - r.uartimsc().modify(|w| { + info.regs.uartimsc().modify(|w| { w.set_rxim(true); w.set_rtim(true); }); + + NVIC::unpend(info.irq); + NVIC::unmask(info.irq); } Self { - inner: PeripheralMutex::new(irq, &mut state.0, move || RxStateInner { - phantom: PhantomData, - - buf: RingBuffer::new(rx_buffer), - waker: WakerRegistration::new(), - }), + info, + phantom: PhantomData, } } } -impl<'d, T: Instance> BufferedUartTx<'d, T> { - pub fn new( - state: &'d mut TxState<'d, T>, - _uart: UartTx<'d, T, M>, - irq: impl Peripheral

+ 'd, +impl<'d> BufferedUartTx<'d> { + pub fn new( + _uart: impl Peripheral

+ 'd, + irq: impl Registration, tx_buffer: &'d mut [u8], - ) -> BufferedUartTx<'d, T> { - into_ref!(irq); - - let r = T::regs(); + config: Config, + ) -> BufferedUartTx<'d> { + let info = T::info(); unsafe { + info.regs.uartimsc().modify(|w| { + w.set_txim(true); + }); + + NVIC::unpend(info.irq); + NVIC::unmask(info.irq); + } + + Self { + info, + phantom: PhantomData, + } + } +} + +impl<'d> Drop for BufferedUart<'d> { + fn drop(&mut self) { + NVIC::mask(self.info.irq); + } +} + +impl<'d> Drop for BufferedUartRx<'d> { + fn drop(&mut self) { + NVIC::mask(self.info.irq); + } +} + +impl<'d> Drop for BufferedUartTx<'d> { + fn drop(&mut self) { + NVIC::mask(self.info.irq); + } +} + +pub(crate) fn on_interrupt(info: &'static Info) { + trace!("on_interrupt"); + + let r = info.regs; + let s = info.state; + + unsafe { + // RX + + let ris = r.uartris().read(); + // Clear interrupt flags + r.uarticr().write(|w| { + w.set_rxic(true); + w.set_rtic(true); + }); + + if ris.peris() { + warn!("Parity error"); + r.uarticr().write(|w| { + w.set_peic(true); + }); + } + if ris.feris() { + warn!("Framing error"); + r.uarticr().write(|w| { + w.set_feic(true); + }); + } + if ris.beris() { + warn!("Break error"); + r.uarticr().write(|w| { + w.set_beic(true); + }); + } + if ris.oeris() { + warn!("Overrun error"); + r.uarticr().write(|w| { + w.set_oeic(true); + }); + } + + let rx_writer = s.rx_buf.writer(); + if !r.uartfr().read().rxfe() { + let val = r.uartdr().read().data(); + if !rx_writer.push_one(val) { + warn!("RX buffer full, discard received byte"); + } + s.rx_waker.wake(); + } + + // TX + let tx_reader = s.tx_buf.reader(); + if let Some(val) = tx_reader.pop_one() { r.uartimsc().modify(|w| { w.set_txim(true); }); - } - - Self { - inner: PeripheralMutex::new(irq, &mut state.0, move || TxStateInner { - phantom: PhantomData, - - buf: RingBuffer::new(tx_buffer), - waker: WakerRegistration::new(), - }), - } - } -} - -impl<'d, T: Instance> PeripheralState for FullStateInner<'d, T> -where - Self: 'd, -{ - type Interrupt = T::Interrupt; - fn on_interrupt(&mut self) { - self.rx.on_interrupt(); - self.tx.on_interrupt(); - } -} - -impl<'d, T: Instance> RxStateInner<'d, T> -where - Self: 'd, -{ - fn read(&mut self, buf: &mut [u8], waker: &Waker) -> (Poll>, bool) { - // We have data ready in buffer? Return it. - let mut do_pend = false; - let data = self.buf.pop_buf(); - if !data.is_empty() { - let len = data.len().min(buf.len()); - buf[..len].copy_from_slice(&data[..len]); - - if self.buf.is_full() { - do_pend = true; - } - self.buf.pop(len); - - return (Poll::Ready(Ok(len)), do_pend); - } - - self.waker.register(waker); - (Poll::Pending, do_pend) - } - - fn fill_buf<'a>(&mut self, waker: &Waker) -> Poll> { - // We have data ready in buffer? Return it. - let buf = self.buf.pop_buf(); - if !buf.is_empty() { - let buf: &[u8] = buf; - // Safety: buffer lives as long as uart - let buf: &[u8] = unsafe { core::mem::transmute(buf) }; - return Poll::Ready(Ok(buf)); - } - - self.waker.register(waker); - Poll::Pending - } - - fn consume(&mut self, amt: usize) -> bool { - let full = self.buf.is_full(); - self.buf.pop(amt); - full - } -} - -impl<'d, T: Instance> PeripheralState for RxStateInner<'d, T> -where - Self: 'd, -{ - type Interrupt = T::Interrupt; - fn on_interrupt(&mut self) { - let r = T::regs(); - unsafe { - let ris = r.uartris().read(); - // Clear interrupt flags - r.uarticr().modify(|w| { - w.set_rxic(true); - w.set_rtic(true); + r.uartdr().write(|w| w.set_data(val)); + s.tx_waker.wake(); + } else { + // Disable interrupt until we have something to transmit again + r.uartimsc().modify(|w| { + w.set_txim(false); }); - - if ris.peris() { - warn!("Parity error"); - r.uarticr().modify(|w| { - w.set_peic(true); - }); - } - if ris.feris() { - warn!("Framing error"); - r.uarticr().modify(|w| { - w.set_feic(true); - }); - } - if ris.beris() { - warn!("Break error"); - r.uarticr().modify(|w| { - w.set_beic(true); - }); - } - if ris.oeris() { - warn!("Overrun error"); - r.uarticr().modify(|w| { - w.set_oeic(true); - }); - } - - if !r.uartfr().read().rxfe() { - let buf = self.buf.push_buf(); - if !buf.is_empty() { - buf[0] = r.uartdr().read().data(); - self.buf.push(1); - } else { - warn!("RX buffer full, discard received byte"); - } - - if self.buf.is_full() { - self.waker.wake(); - } - } - - if ris.rtris() { - self.waker.wake(); - }; } } } -impl<'d, T: Instance> TxStateInner<'d, T> -where - Self: 'd, -{ - fn write(&mut self, buf: &[u8], waker: &Waker) -> (Poll>, bool) { - let empty = self.buf.is_empty(); - let tx_buf = self.buf.push_buf(); - if tx_buf.is_empty() { - self.waker.register(waker); - return (Poll::Pending, empty); +fn read<'a>(info: &'static Info, buf: &'a mut [u8]) -> impl Future> + 'a { + poll_fn(move |cx| { + let rx_reader = unsafe { info.state.rx_buf.reader() }; + let n = rx_reader.pop(|data| { + let n = data.len().min(buf.len()); + buf[..n].copy_from_slice(&data[..n]); + n + }); + if n == 0 { + info.state.rx_waker.register(cx.waker()); + return Poll::Pending; } - let n = core::cmp::min(tx_buf.len(), buf.len()); - tx_buf[..n].copy_from_slice(&buf[..n]); - self.buf.push(n); + Poll::Ready(Ok(n)) + }) +} - (Poll::Ready(Ok(n)), empty) - } +fn fill_buf<'a>(info: &'static Info) -> impl Future> { + poll_fn(move |cx| { + let rx_reader = unsafe { info.state.rx_buf.reader() }; + let (p, n) = rx_reader.pop_buf(); + if n == 0 { + info.state.rx_waker.register(cx.waker()); + return Poll::Pending; + } - fn flush(&mut self, waker: &Waker) -> Poll> { - if !self.buf.is_empty() { - self.waker.register(waker); + let buf = unsafe { slice::from_raw_parts(p, n) }; + Poll::Ready(Ok(buf)) + }) +} + +fn consume(info: &'static Info, amt: usize) { + let rx_reader = unsafe { info.state.rx_buf.reader() }; + rx_reader.pop_done(amt) +} + +fn write<'a>(info: &'static Info, buf: &'a [u8]) -> impl Future> + 'a { + poll_fn(move |cx| { + let tx_writer = unsafe { info.state.tx_buf.writer() }; + let n = tx_writer.push(|data| { + let n = data.len().min(buf.len()); + data[..n].copy_from_slice(&buf[..n]); + n + }); + if n == 0 { + info.state.tx_waker.register(cx.waker()); + return Poll::Pending; + } else { + NVIC::pend(info.irq); + } + + Poll::Ready(Ok(n)) + }) +} + +fn flush(info: &'static Info) -> impl Future> { + poll_fn(move |cx| { + if !info.state.tx_buf.is_empty() { + info.state.tx_waker.register(cx.waker()); return Poll::Pending; } Poll::Ready(Ok(())) - } -} - -impl<'d, T: Instance> PeripheralState for TxStateInner<'d, T> -where - Self: 'd, -{ - type Interrupt = T::Interrupt; - fn on_interrupt(&mut self) { - let r = T::regs(); - unsafe { - let buf = self.buf.pop_buf(); - if !buf.is_empty() { - r.uartimsc().modify(|w| { - w.set_txim(true); - }); - r.uartdr().write(|w| w.set_data(buf[0].into())); - self.buf.pop(1); - self.waker.wake(); - } else { - // Disable interrupt until we have something to transmit again - r.uartimsc().modify(|w| { - w.set_txim(false); - }); - } - } - } + }) } impl embedded_io::Error for Error { @@ -342,117 +338,73 @@ impl embedded_io::Error for Error { } } -impl<'d, T: Instance> embedded_io::Io for BufferedUart<'d, T> { +impl<'d> embedded_io::Io for BufferedUart<'d> { type Error = Error; } -impl<'d, T: Instance> embedded_io::Io for BufferedUartRx<'d, T> { +impl<'d> embedded_io::Io for BufferedUartRx<'d> { type Error = Error; } -impl<'d, T: Instance> embedded_io::Io for BufferedUartTx<'d, T> { +impl<'d> embedded_io::Io for BufferedUartTx<'d> { type Error = Error; } -impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUart<'d, T> { +impl<'d> embedded_io::asynch::Read for BufferedUart<'d> { type ReadFuture<'a> = impl Future> + 'a where Self: 'a; fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { - poll_fn(move |cx| { - let (res, do_pend) = self.inner.with(|state| { - compiler_fence(Ordering::SeqCst); - state.rx.read(buf, cx.waker()) - }); - - if do_pend { - self.inner.pend(); - } - - res - }) + read(self.info, buf) } } -impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUartRx<'d, T> { +impl<'d> embedded_io::asynch::Read for BufferedUartRx<'d> { type ReadFuture<'a> = impl Future> + 'a where Self: 'a; fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { - poll_fn(move |cx| { - let (res, do_pend) = self.inner.with(|state| { - compiler_fence(Ordering::SeqCst); - state.read(buf, cx.waker()) - }); - - if do_pend { - self.inner.pend(); - } - - res - }) + read(self.info, buf) } } -impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUart<'d, T> { +impl<'d> embedded_io::asynch::BufRead for BufferedUart<'d> { type FillBufFuture<'a> = impl Future> + 'a where Self: 'a; fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> { - poll_fn(move |cx| { - self.inner.with(|state| { - compiler_fence(Ordering::SeqCst); - state.rx.fill_buf(cx.waker()) - }) - }) + fill_buf(self.info) } fn consume(&mut self, amt: usize) { - let signal = self.inner.with(|state| state.rx.consume(amt)); - if signal { - self.inner.pend(); - } + consume(self.info, amt) } } -impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUartRx<'d, T> { +impl<'d> embedded_io::asynch::BufRead for BufferedUartRx<'d> { type FillBufFuture<'a> = impl Future> + 'a where Self: 'a; fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> { - poll_fn(move |cx| { - self.inner.with(|state| { - compiler_fence(Ordering::SeqCst); - state.fill_buf(cx.waker()) - }) - }) + fill_buf(self.info) } fn consume(&mut self, amt: usize) { - let signal = self.inner.with(|state| state.consume(amt)); - if signal { - self.inner.pend(); - } + consume(self.info, amt) } } -impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> { +impl<'d> embedded_io::asynch::Write for BufferedUart<'d> { type WriteFuture<'a> = impl Future> + 'a where Self: 'a; fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { - poll_fn(move |cx| { - let (poll, empty) = self.inner.with(|state| state.tx.write(buf, cx.waker())); - if empty { - self.inner.pend(); - } - poll - }) + write(self.info, buf) } type FlushFuture<'a> = impl Future> + 'a @@ -460,23 +412,17 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> { Self: 'a; fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { - poll_fn(move |cx| self.inner.with(|state| state.tx.flush(cx.waker()))) + flush(self.info) } } -impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUartTx<'d, T> { +impl<'d> embedded_io::asynch::Write for BufferedUartTx<'d> { type WriteFuture<'a> = impl Future> + 'a where Self: 'a; fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { - poll_fn(move |cx| { - let (poll, empty) = self.inner.with(|state| state.write(buf, cx.waker())); - if empty { - self.inner.pend(); - } - poll - }) + write(self.info, buf) } type FlushFuture<'a> = impl Future> + 'a @@ -484,6 +430,6 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUartTx<'d, T> Self: 'a; fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> { - poll_fn(move |cx| self.inner.with(|state| state.flush(cx.waker()))) + flush(self.info) } } diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 56c25e18..b1fb1af1 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -5,7 +5,13 @@ use embassy_hal_common::{into_ref, PeripheralRef}; use crate::dma::{AnyChannel, Channel}; use crate::gpio::sealed::Pin; use crate::gpio::AnyPin; -use crate::{pac, peripherals, Peripheral}; +use crate::pac::uart as pac; +use crate::{peripherals, Peripheral}; + +#[cfg(feature = "nightly")] +mod buffered; +#[cfg(feature = "nightly")] +pub use buffered::*; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum DataBits { @@ -77,31 +83,26 @@ pub enum Error { Framing, } -pub struct Uart<'d, T: Instance, M: Mode> { - tx: UartTx<'d, T, M>, - rx: UartRx<'d, T, M>, +pub struct Uart<'d, M: Mode> { + tx: UartTx<'d, M>, + rx: UartRx<'d, M>, } -pub struct UartTx<'d, T: Instance, M: Mode> { +pub struct UartTx<'d, M: Mode> { + info: &'static Info, tx_dma: Option>, - phantom: PhantomData<(&'d mut T, M)>, + phantom: PhantomData, } -pub struct UartRx<'d, T: Instance, M: Mode> { +pub struct UartRx<'d, M: Mode> { + info: &'static Info, rx_dma: Option>, - phantom: PhantomData<(&'d mut T, M)>, + phantom: PhantomData, } -impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { - fn new(tx_dma: Option>) -> Self { - Self { - tx_dma, - phantom: PhantomData, - } - } - +impl<'d, M: Mode> UartTx<'d, M> { pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { - let r = T::regs(); + let r = self.info.regs; unsafe { for &b in buffer { while r.uartfr().read().txff() {} @@ -112,38 +113,31 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { } pub fn blocking_flush(&mut self) -> Result<(), Error> { - let r = T::regs(); + let r = self.info.regs; unsafe { while !r.uartfr().read().txfe() {} } Ok(()) } } -impl<'d, T: Instance> UartTx<'d, T, Async> { +impl<'d> UartTx<'d, Async> { pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { let ch = self.tx_dma.as_mut().unwrap(); let transfer = unsafe { - T::regs().uartdmacr().modify(|reg| { + self.info.regs.uartdmacr().modify(|reg| { reg.set_txdmae(true); }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::write(ch, buffer, T::regs().uartdr().ptr() as *mut _, T::TX_DREQ) + crate::dma::write(ch, buffer, self.info.regs.uartdr().ptr() as *mut _, self.info.tx_dreq) }; transfer.await; Ok(()) } } -impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { - fn new(rx_dma: Option>) -> Self { - Self { - rx_dma, - phantom: PhantomData, - } - } - +impl<'d, M: Mode> UartRx<'d, M> { pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { - let r = T::regs(); + let r = self.info.regs; unsafe { for b in buffer { *b = loop { @@ -171,37 +165,37 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { } } -impl<'d, T: Instance> UartRx<'d, T, Async> { +impl<'d> UartRx<'d, Async> { pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { let ch = self.rx_dma.as_mut().unwrap(); let transfer = unsafe { - T::regs().uartdmacr().modify(|reg| { + self.info.regs.uartdmacr().modify(|reg| { reg.set_rxdmae(true); }); // If we don't assign future to a variable, the data register pointer // is held across an await and makes the future non-Send. - crate::dma::read(ch, T::regs().uartdr().ptr() as *const _, buffer, T::RX_DREQ) + crate::dma::read(ch, self.info.regs.uartdr().ptr() as *const _, buffer, self.info.rx_dreq) }; transfer.await; Ok(()) } } -impl<'d, T: Instance> Uart<'d, T, Blocking> { +impl<'d> Uart<'d, Blocking> { /// Create a new UART without hardware flow control - pub fn new_blocking( - uart: impl Peripheral

+ 'd, + pub fn new_blocking( + _uart: impl Peripheral

+ 'd, tx: impl Peripheral

> + 'd, rx: impl Peripheral

> + 'd, config: Config, ) -> Self { into_ref!(tx, rx); - Self::new_inner(uart, rx.map_into(), tx.map_into(), None, None, None, None, config) + Self::new_inner(T::info(), tx.map_into(), rx.map_into(), None, None, None, None, config) } /// Create a new UART with hardware flow control (RTS/CTS) - pub fn new_with_rtscts_blocking( - uart: impl Peripheral

+ 'd, + pub fn new_with_rtscts_blocking( + _uart: impl Peripheral

+ 'd, tx: impl Peripheral

> + 'd, rx: impl Peripheral

> + 'd, rts: impl Peripheral

> + 'd, @@ -210,9 +204,9 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> { ) -> Self { into_ref!(tx, rx, cts, rts); Self::new_inner( - uart, - rx.map_into(), + T::info(), tx.map_into(), + rx.map_into(), Some(rts.map_into()), Some(cts.map_into()), None, @@ -222,10 +216,10 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> { } } -impl<'d, T: Instance> Uart<'d, T, Async> { +impl<'d> Uart<'d, Async> { /// Create a new DMA enabled UART without hardware flow control - pub fn new( - uart: impl Peripheral

+ 'd, + pub fn new( + _uart: impl Peripheral

+ 'd, tx: impl Peripheral

> + 'd, rx: impl Peripheral

> + 'd, tx_dma: impl Peripheral

+ 'd, @@ -234,9 +228,9 @@ impl<'d, T: Instance> Uart<'d, T, Async> { ) -> Self { into_ref!(tx, rx, tx_dma, rx_dma); Self::new_inner( - uart, - rx.map_into(), + T::info(), tx.map_into(), + rx.map_into(), None, None, Some(tx_dma.map_into()), @@ -246,8 +240,8 @@ impl<'d, T: Instance> Uart<'d, T, Async> { } /// Create a new DMA enabled UART with hardware flow control (RTS/CTS) - pub fn new_with_rtscts( - uart: impl Peripheral

+ 'd, + pub fn new_with_rtscts( + _uart: impl Peripheral

+ 'd, tx: impl Peripheral

> + 'd, rx: impl Peripheral

> + 'd, rts: impl Peripheral

> + 'd, @@ -258,7 +252,7 @@ impl<'d, T: Instance> Uart<'d, T, Async> { ) -> Self { into_ref!(tx, rx, cts, rts, tx_dma, rx_dma); Self::new_inner( - uart, + T::info(), rx.map_into(), tx.map_into(), Some(rts.map_into()), @@ -270,104 +264,120 @@ impl<'d, T: Instance> Uart<'d, T, Async> { } } -impl<'d, T: Instance, M: Mode> Uart<'d, T, M> { +impl<'d, M: Mode> Uart<'d, M> { fn new_inner( - _uart: impl Peripheral

+ 'd, - tx: PeripheralRef<'d, AnyPin>, - rx: PeripheralRef<'d, AnyPin>, - rts: Option>, - cts: Option>, + info: &'static Info, + mut tx: PeripheralRef<'d, AnyPin>, + mut rx: PeripheralRef<'d, AnyPin>, + mut rts: Option>, + mut cts: Option>, tx_dma: Option>, rx_dma: Option>, config: Config, ) -> Self { - into_ref!(_uart); - - unsafe { - let r = T::regs(); - - tx.io().ctrl().write(|w| w.set_funcsel(2)); - rx.io().ctrl().write(|w| w.set_funcsel(2)); - - tx.pad_ctrl().write(|w| { - w.set_ie(true); - }); - - rx.pad_ctrl().write(|w| { - w.set_ie(true); - }); - - if let Some(pin) = &cts { - pin.io().ctrl().write(|w| w.set_funcsel(2)); - pin.pad_ctrl().write(|w| { - w.set_ie(true); - }); - } - if let Some(pin) = &rts { - pin.io().ctrl().write(|w| w.set_funcsel(2)); - pin.pad_ctrl().write(|w| { - w.set_ie(true); - }); - } - - let clk_base = crate::clocks::clk_peri_freq(); - - let baud_rate_div = (8 * clk_base) / config.baudrate; - let mut baud_ibrd = baud_rate_div >> 7; - let mut baud_fbrd = ((baud_rate_div & 0x7f) + 1) / 2; - - if baud_ibrd == 0 { - baud_ibrd = 1; - baud_fbrd = 0; - } else if baud_ibrd >= 65535 { - baud_ibrd = 65535; - baud_fbrd = 0; - } - - // Load PL011's baud divisor registers - r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd)); - r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd)); - - let (pen, eps) = match config.parity { - Parity::ParityNone => (false, false), - Parity::ParityOdd => (true, false), - Parity::ParityEven => (true, true), - }; - - // PL011 needs a (dummy) line control register write to latch in the - // divisors. We don't want to actually change LCR contents here. - r.uartlcr_h().modify(|_| {}); - - r.uartlcr_h().write(|w| { - w.set_wlen(config.data_bits.bits()); - w.set_stp2(config.stop_bits == StopBits::STOP2); - w.set_pen(pen); - w.set_eps(eps); - w.set_fen(true); - }); - - r.uartifls().write(|w| { - w.set_rxiflsel(0b000); - w.set_txiflsel(0b000); - }); - - r.uartcr().write(|w| { - w.set_uarten(true); - w.set_rxe(true); - w.set_txe(true); - w.set_ctsen(cts.is_some()); - w.set_rtsen(rts.is_some()); - }); - } + init( + info, + Some(tx.reborrow()), + Some(rx.reborrow()), + rts.as_mut().map(|x| x.reborrow()), + cts.as_mut().map(|x| x.reborrow()), + config, + ); Self { - tx: UartTx::new(tx_dma), - rx: UartRx::new(rx_dma), + tx: UartTx { + info, + tx_dma, + phantom: PhantomData, + }, + rx: UartRx { + info, + rx_dma, + phantom: PhantomData, + }, } } } -impl<'d, T: Instance, M: Mode> Uart<'d, T, M> { +fn init( + info: &'static Info, + tx: Option>, + rx: Option>, + rts: Option>, + cts: Option>, + config: Config, +) { + let r = info.regs; + unsafe { + if let Some(pin) = &tx { + pin.io().ctrl().write(|w| w.set_funcsel(2)); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + if let Some(pin) = &rx { + pin.io().ctrl().write(|w| w.set_funcsel(2)); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + if let Some(pin) = &cts { + pin.io().ctrl().write(|w| w.set_funcsel(2)); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + if let Some(pin) = &rts { + pin.io().ctrl().write(|w| w.set_funcsel(2)); + pin.pad_ctrl().write(|w| w.set_ie(true)); + } + + let clk_base = crate::clocks::clk_peri_freq(); + + let baud_rate_div = (8 * clk_base) / config.baudrate; + let mut baud_ibrd = baud_rate_div >> 7; + let mut baud_fbrd = ((baud_rate_div & 0x7f) + 1) / 2; + + if baud_ibrd == 0 { + baud_ibrd = 1; + baud_fbrd = 0; + } else if baud_ibrd >= 65535 { + baud_ibrd = 65535; + baud_fbrd = 0; + } + + // Load PL011's baud divisor registers + r.uartibrd().write_value(pac::regs::Uartibrd(baud_ibrd)); + r.uartfbrd().write_value(pac::regs::Uartfbrd(baud_fbrd)); + + let (pen, eps) = match config.parity { + Parity::ParityNone => (false, false), + Parity::ParityOdd => (true, false), + Parity::ParityEven => (true, true), + }; + + // PL011 needs a (dummy) line control register write to latch in the + // divisors. We don't want to actually change LCR contents here. + r.uartlcr_h().modify(|_| {}); + + r.uartlcr_h().write(|w| { + w.set_wlen(config.data_bits.bits()); + w.set_stp2(config.stop_bits == StopBits::STOP2); + w.set_pen(pen); + w.set_eps(eps); + w.set_fen(true); + }); + + r.uartifls().write(|w| { + w.set_rxiflsel(0b000); + w.set_txiflsel(0b000); + }); + + r.uartcr().write(|w| { + w.set_uarten(true); + w.set_rxe(true); + w.set_txe(true); + w.set_ctsen(cts.is_some()); + w.set_rtsen(rts.is_some()); + }); + } +} + +impl<'d, M: Mode> Uart<'d, M> { pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { self.tx.blocking_write(buffer) } @@ -382,12 +392,12 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> { /// Split the Uart into a transmitter and receiver, which is particuarly /// useful when having two tasks correlating to transmitting and receiving. - pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) { + pub fn split(self) -> (UartTx<'d, M>, UartRx<'d, M>) { (self.tx, self.rx) } } -impl<'d, T: Instance> Uart<'d, T, Async> { +impl<'d> Uart<'d, Async> { pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { self.tx.write(buffer).await } @@ -400,10 +410,10 @@ impl<'d, T: Instance> Uart<'d, T, Async> { mod eh02 { use super::*; - impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read for UartRx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_02::serial::Read for UartRx<'d, M> { type Error = Error; fn read(&mut self) -> Result> { - let r = T::regs(); + let r = self.info.regs; unsafe { if r.uartfr().read().rxfe() { return Err(nb::Error::WouldBlock); @@ -426,7 +436,7 @@ mod eh02 { } } - impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write for UartTx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write for UartTx<'d, M> { type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { @@ -438,7 +448,7 @@ mod eh02 { } } - impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read for Uart<'d, T, M> { + impl<'d, M: Mode> embedded_hal_02::serial::Read for Uart<'d, M> { type Error = Error; fn read(&mut self) -> Result> { @@ -446,7 +456,7 @@ mod eh02 { } } - impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write for Uart<'d, T, M> { + impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write for Uart<'d, M> { type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { @@ -474,21 +484,21 @@ mod eh1 { } } - impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for Uart<'d, T, M> { + impl<'d, M: Mode> embedded_hal_1::serial::ErrorType for Uart<'d, M> { type Error = Error; } - impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartTx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_1::serial::ErrorType for UartTx<'d, M> { type Error = Error; } - impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, M> { type Error = Error; } - impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, M> { fn read(&mut self) -> nb::Result { - let r = T::regs(); + let r = self.info.regs; unsafe { let dr = r.uartdr().read(); @@ -509,7 +519,7 @@ mod eh1 { } } - impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::Write for UartTx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_1::serial::Write for UartTx<'d, M> { fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { self.blocking_write(buffer) } @@ -519,7 +529,7 @@ mod eh1 { } } - impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, M> { fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { self.blocking_write(&[char]).map_err(nb::Error::Other) } @@ -529,13 +539,13 @@ mod eh1 { } } - impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, T, M> { + impl<'d, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, M> { fn read(&mut self) -> Result> { embedded_hal_02::serial::Read::read(&mut self.rx) } } - impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::Write for Uart<'d, T, M> { + impl<'d, M: Mode> embedded_hal_1::serial::Write for Uart<'d, M> { fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { self.blocking_write(buffer) } @@ -545,7 +555,7 @@ mod eh1 { } } - impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, T, M> { + impl<'d, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, M> { fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { self.blocking_write(&[char]).map_err(nb::Error::Other) } @@ -566,7 +576,7 @@ mod eha { use super::*; - impl<'d, T: Instance, M: Mode> embedded_hal_async::serial::Write for UartTx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_async::serial::Write for UartTx<'d, M> { type WriteFuture<'a> = impl Future> + 'a where Self: 'a; fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { @@ -580,7 +590,7 @@ mod eha { } } - impl<'d, T: Instance, M: Mode> embedded_hal_async::serial::Read for UartRx<'d, T, M> { + impl<'d, M: Mode> embedded_hal_async::serial::Read for UartRx<'d, M> { type ReadFuture<'a> = impl Future> + 'a where Self: 'a; fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { @@ -588,7 +598,7 @@ mod eha { } } - impl<'d, T: Instance, M: Mode> embedded_hal_async::serial::Write for Uart<'d, T, M> { + impl<'d, M: Mode> embedded_hal_async::serial::Write for Uart<'d, M> { type WriteFuture<'a> = impl Future> + 'a where Self: 'a; fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { @@ -602,7 +612,7 @@ mod eha { } } - impl<'d, T: Instance, M: Mode> embedded_hal_async::serial::Read for Uart<'d, T, M> { + impl<'d, M: Mode> embedded_hal_async::serial::Read for Uart<'d, M> { type ReadFuture<'a> = impl Future> + 'a where Self: 'a; fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { @@ -611,30 +621,32 @@ mod eha { } } -#[cfg(feature = "nightly")] -mod buffered; -#[cfg(feature = "nightly")] -pub use buffered::*; - mod sealed { use super::*; pub trait Mode {} pub trait Instance { - const TX_DREQ: u8; - const RX_DREQ: u8; - type Interrupt: crate::interrupt::Interrupt; - - fn regs() -> pac::uart::Uart; + fn info() -> &'static Info; } pub trait TxPin {} pub trait RxPin {} pub trait CtsPin {} pub trait RtsPin {} + + /// Info about one concrete peripheral instance. + pub struct Info { + pub(crate) regs: pac::Uart, + pub(crate) tx_dreq: u8, + pub(crate) rx_dreq: u8, + pub(crate) irq: crate::pac::Interrupt, + pub(crate) state: &'static super::buffered::State, + } } +use sealed::Info; + pub trait Mode: sealed::Mode {} macro_rules! impl_mode { @@ -655,16 +667,27 @@ pub trait Instance: sealed::Instance {} macro_rules! impl_instance { ($inst:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => { impl sealed::Instance for peripherals::$inst { - const TX_DREQ: u8 = $tx_dreq; - const RX_DREQ: u8 = $rx_dreq; - type Interrupt = crate::interrupt::$irq; - fn regs() -> pac::uart::Uart { - pac::$inst + fn info() -> &'static Info { + static STATE: buffered::State = buffered::State::new(); + static INFO: Info = Info { + regs: crate::pac::$inst, + tx_dreq: $tx_dreq, + rx_dreq: $rx_dreq, + irq: crate::pac::Interrupt::$irq, + state: &STATE, + }; + &INFO } } impl Instance for peripherals::$inst {} + + impl crate::interrupt::InterruptFunction for crate::interrupt::$irq { + fn on_interrupt() { + buffered::on_interrupt(::info()) + } + } }; } diff --git a/examples/rp/src/bin/uart.rs b/examples/rp/src/bin/uart.rs index 05177a6b..355b5948 100644 --- a/examples/rp/src/bin/uart.rs +++ b/examples/rp/src/bin/uart.rs @@ -3,9 +3,11 @@ #![feature(type_alias_impl_trait)] use embassy_executor::Spawner; -use embassy_rp::uart; +use embassy_rp::{register_interrupts, uart}; use {defmt_rtt as _, panic_probe as _}; +register_interrupts!(Reg: UART0_IRQ); + #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); diff --git a/tests/rp/src/bin/uart_buffered.rs b/tests/rp/src/bin/uart_buffered.rs index 9cc20bb9..bf1c6bc3 100644 --- a/tests/rp/src/bin/uart_buffered.rs +++ b/tests/rp/src/bin/uart_buffered.rs @@ -4,11 +4,13 @@ use defmt::{assert_eq, *}; use embassy_executor::Spawner; -use embassy_rp::interrupt; -use embassy_rp::uart::{BufferedUart, Config, State, Uart}; +use embassy_rp::register_interrupts; +use embassy_rp::uart::{BufferedUart, Config}; use embedded_io::asynch::{Read, Write}; use {defmt_rtt as _, panic_probe as _}; +register_interrupts!(Irqs: UART0_IRQ); + #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_rp::init(Default::default()); @@ -16,26 +18,26 @@ async fn main(_spawner: Spawner) { let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0); - let config = Config::default(); - let uart = Uart::new_blocking(uart, tx, rx, config); - - let irq = interrupt::take!(UART0_IRQ); let tx_buf = &mut [0u8; 16]; let rx_buf = &mut [0u8; 16]; - let mut state = State::new(); - let mut uart = BufferedUart::new(&mut state, uart, irq, tx_buf, rx_buf); + let config = Config::default(); + let mut uart = BufferedUart::new(uart, Irqs, tx, rx, tx_buf, rx_buf, config); // Make sure we send more bytes than fits in the FIFO, to test the actual // bufferedUart. let data = [ 1_u8, 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, + 30, 31, + ]; + let data = [ + 1u8, 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, ]; uart.write_all(&data).await.unwrap(); info!("Done writing"); - let mut buf = [0; 32]; + let mut buf = [0; 31]; uart.read_exact(&mut buf).await.unwrap(); assert_eq!(buf, data);