Merge pull request #4155 from marcemmers/remove-instance-from-rp-uart-type

[embassy-rp] Remove <T: Instance> from Uart and BufferedUart
This commit is contained in:
Ulf Lilleengen 2025-05-09 19:34:52 +02:00 committed by GitHub
commit f9f20ae217
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 344 additions and 290 deletions

View File

@ -34,28 +34,29 @@ impl State {
}
/// Buffered UART driver.
pub struct BufferedUart<'d, T: Instance> {
pub(crate) rx: BufferedUartRx<'d, T>,
pub(crate) tx: BufferedUartTx<'d, T>,
pub struct BufferedUart {
pub(super) rx: BufferedUartRx,
pub(super) tx: BufferedUartTx,
}
/// Buffered UART RX handle.
pub struct BufferedUartRx<'d, T: Instance> {
pub(crate) phantom: PhantomData<&'d mut T>,
pub struct BufferedUartRx {
pub(super) info: &'static Info,
pub(super) state: &'static State,
}
/// Buffered UART TX handle.
pub struct BufferedUartTx<'d, T: Instance> {
pub(crate) phantom: PhantomData<&'d mut T>,
pub struct BufferedUartTx {
pub(super) info: &'static Info,
pub(super) state: &'static State,
}
pub(crate) fn init_buffers<'d, T: Instance + 'd>(
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
pub(super) fn init_buffers<'d>(
info: &Info,
state: &State,
tx_buffer: Option<&'d mut [u8]>,
rx_buffer: Option<&'d mut [u8]>,
) {
let state = T::buffered_state();
if let Some(tx_buffer) = tx_buffer {
let len = tx_buffer.len();
unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
@ -76,61 +77,73 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>(
// This means we can leave the interrupt enabled the whole time as long as
// we clear it after it happens. The downside is that the we manually have
// to pend the ISR when we want data transmission to start.
let regs = T::regs();
regs.uartimsc().write(|w| {
info.regs.uartimsc().write(|w| {
w.set_rxim(true);
w.set_rtim(true);
w.set_txim(true);
});
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
info.interrupt.unpend();
unsafe { info.interrupt.enable() };
}
impl<'d, T: Instance> BufferedUart<'d, T> {
impl BufferedUart {
/// Create a buffered UART instance.
pub fn new(
pub fn new<'d, T: Instance>(
_uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
super::Uart::<'d, T, Async>::init(Some(tx.into()), Some(rx.into()), None, None, config);
init_buffers::<T>(irq, Some(tx_buffer), Some(rx_buffer));
super::Uart::<'d, Async>::init(T::info(), Some(tx.into()), Some(rx.into()), None, None, config);
init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), Some(rx_buffer));
Self {
rx: BufferedUartRx { phantom: PhantomData },
tx: BufferedUartTx { phantom: PhantomData },
rx: BufferedUartRx {
info: T::info(),
state: T::buffered_state(),
},
tx: BufferedUartTx {
info: T::info(),
state: T::buffered_state(),
},
}
}
/// Create a buffered UART instance with flow control.
pub fn new_with_rtscts(
pub fn new_with_rtscts<'d, T: Instance>(
_uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
rts: Peri<'d, impl RtsPin<T>>,
cts: Peri<'d, impl CtsPin<T>>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
super::Uart::<'d, T, Async>::init(
super::Uart::<'d, Async>::init(
T::info(),
Some(tx.into()),
Some(rx.into()),
Some(rts.into()),
Some(cts.into()),
config,
);
init_buffers::<T>(irq, Some(tx_buffer), Some(rx_buffer));
init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), Some(rx_buffer));
Self {
rx: BufferedUartRx { phantom: PhantomData },
tx: BufferedUartTx { phantom: PhantomData },
rx: BufferedUartRx {
info: T::info(),
state: T::buffered_state(),
},
tx: BufferedUartTx {
info: T::info(),
state: T::buffered_state(),
},
}
}
@ -160,68 +173,75 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
}
/// sets baudrate on runtime
pub fn set_baudrate(&mut self, baudrate: u32) {
super::Uart::<'d, T, Async>::set_baudrate_inner(baudrate);
pub fn set_baudrate<'d>(&mut self, baudrate: u32) {
super::Uart::<'d, Async>::set_baudrate_inner(self.rx.info, baudrate);
}
/// Split into separate RX and TX handles.
pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
pub fn split(self) -> (BufferedUartTx, BufferedUartRx) {
(self.tx, self.rx)
}
/// Split the Uart into a transmitter and receiver by mutable reference,
/// which is particularly useful when having two tasks correlating to
/// transmitting and receiving.
pub fn split_ref(&mut self) -> (&mut BufferedUartTx<'d, T>, &mut BufferedUartRx<'d, T>) {
pub fn split_ref(&mut self) -> (&mut BufferedUartTx, &mut BufferedUartRx) {
(&mut self.tx, &mut self.rx)
}
}
impl<'d, T: Instance> BufferedUartRx<'d, T> {
impl BufferedUartRx {
/// Create a new buffered UART RX.
pub fn new(
pub fn new<'d, T: Instance>(
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
rx: Peri<'d, impl RxPin<T>>,
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
super::Uart::<'d, T, Async>::init(None, Some(rx.into()), None, None, config);
init_buffers::<T>(irq, None, Some(rx_buffer));
super::Uart::<'d, Async>::init(T::info(), None, Some(rx.into()), None, None, config);
init_buffers(T::info(), T::buffered_state(), None, Some(rx_buffer));
Self { phantom: PhantomData }
Self {
info: T::info(),
state: T::buffered_state(),
}
}
/// Create a new buffered UART RX with flow control.
pub fn new_with_rts(
pub fn new_with_rts<'d, T: Instance>(
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
rx: Peri<'d, impl RxPin<T>>,
rts: Peri<'d, impl RtsPin<T>>,
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
super::Uart::<'d, T, Async>::init(None, Some(rx.into()), Some(rts.into()), None, config);
init_buffers::<T>(irq, None, Some(rx_buffer));
super::Uart::<'d, Async>::init(T::info(), None, Some(rx.into()), Some(rts.into()), None, config);
init_buffers(T::info(), T::buffered_state(), None, Some(rx_buffer));
Self { phantom: PhantomData }
Self {
info: T::info(),
state: T::buffered_state(),
}
}
fn read<'a>(buf: &'a mut [u8]) -> impl Future<Output = Result<usize, Error>> + 'a
where
T: 'd,
{
fn read<'a>(
info: &'static Info,
state: &'static State,
buf: &'a mut [u8],
) -> impl Future<Output = Result<usize, Error>> + 'a {
poll_fn(move |cx| {
if let Poll::Ready(r) = Self::try_read(buf) {
if let Poll::Ready(r) = Self::try_read(info, state, buf) {
return Poll::Ready(r);
}
T::buffered_state().rx_waker.register(cx.waker());
state.rx_waker.register(cx.waker());
Poll::Pending
})
}
fn get_rx_error() -> Option<Error> {
let errs = T::buffered_state().rx_error.swap(0, Ordering::Relaxed);
fn get_rx_error(state: &State) -> Option<Error> {
let errs = state.rx_error.swap(0, Ordering::Relaxed);
if errs & RXE_OVERRUN != 0 {
Some(Error::Overrun)
} else if errs & RXE_BREAK != 0 {
@ -235,15 +255,11 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
}
}
fn try_read(buf: &mut [u8]) -> Poll<Result<usize, Error>>
where
T: 'd,
{
fn try_read(info: &Info, state: &State, buf: &mut [u8]) -> Poll<Result<usize, Error>> {
if buf.is_empty() {
return Poll::Ready(Ok(0));
}
let state = T::buffered_state();
let mut rx_reader = unsafe { state.rx_buf.reader() };
let n = rx_reader.pop(|data| {
let n = data.len().min(buf.len());
@ -252,7 +268,7 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
});
let result = if n == 0 {
match Self::get_rx_error() {
match Self::get_rx_error(state) {
None => return Poll::Pending,
Some(e) => Err(e),
}
@ -262,8 +278,7 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
// (Re-)Enable the interrupt to receive more data in case it was
// disabled because the buffer was full or errors were detected.
let regs = T::regs();
regs.uartimsc().write_set(|w| {
info.regs.uartimsc().write_set(|w| {
w.set_rxim(true);
w.set_rtim(true);
});
@ -274,23 +289,19 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
/// Read from UART RX buffer blocking execution until done.
pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
loop {
match Self::try_read(buf) {
match Self::try_read(self.info, self.state, buf) {
Poll::Ready(res) => return res,
Poll::Pending => continue,
}
}
}
fn fill_buf<'a>() -> impl Future<Output = Result<&'a [u8], Error>>
where
T: 'd,
{
fn fill_buf<'a>(state: &'static State) -> impl Future<Output = Result<&'a [u8], Error>> {
poll_fn(move |cx| {
let state = T::buffered_state();
let mut rx_reader = unsafe { state.rx_buf.reader() };
let (p, n) = rx_reader.pop_buf();
let result = if n == 0 {
match Self::get_rx_error() {
match Self::get_rx_error(state) {
None => {
state.rx_waker.register(cx.waker());
return Poll::Pending;
@ -306,64 +317,70 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
})
}
fn consume(amt: usize) {
let state = T::buffered_state();
fn consume(info: &Info, state: &State, amt: usize) {
let mut rx_reader = unsafe { state.rx_buf.reader() };
rx_reader.pop_done(amt);
// (Re-)Enable the interrupt to receive more data in case it was
// disabled because the buffer was full or errors were detected.
let regs = T::regs();
regs.uartimsc().write_set(|w| {
info.regs.uartimsc().write_set(|w| {
w.set_rxim(true);
w.set_rtim(true);
});
}
/// we are ready to read if there is data in the buffer
fn read_ready() -> Result<bool, Error> {
let state = T::buffered_state();
fn read_ready(state: &State) -> Result<bool, Error> {
Ok(!state.rx_buf.is_empty())
}
}
impl<'d, T: Instance> BufferedUartTx<'d, T> {
impl BufferedUartTx {
/// Create a new buffered UART TX.
pub fn new(
pub fn new<'d, T: Instance>(
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: Peri<'d, impl TxPin<T>>,
tx_buffer: &'d mut [u8],
config: Config,
) -> Self {
super::Uart::<'d, T, Async>::init(Some(tx.into()), None, None, None, config);
init_buffers::<T>(irq, Some(tx_buffer), None);
super::Uart::<'d, Async>::init(T::info(), Some(tx.into()), None, None, None, config);
init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), None);
Self { phantom: PhantomData }
Self {
info: T::info(),
state: T::buffered_state(),
}
}
/// Create a new buffered UART TX with flow control.
pub fn new_with_cts(
pub fn new_with_cts<'d, T: Instance>(
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: Peri<'d, impl TxPin<T>>,
cts: Peri<'d, impl CtsPin<T>>,
tx_buffer: &'d mut [u8],
config: Config,
) -> Self {
super::Uart::<'d, T, Async>::init(Some(tx.into()), None, None, Some(cts.into()), config);
init_buffers::<T>(irq, Some(tx_buffer), None);
super::Uart::<'d, Async>::init(T::info(), Some(tx.into()), None, None, Some(cts.into()), config);
init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), None);
Self { phantom: PhantomData }
Self {
info: T::info(),
state: T::buffered_state(),
}
}
fn write(buf: &[u8]) -> impl Future<Output = Result<usize, Error>> + '_ {
fn write<'d>(
info: &'static Info,
state: &'static State,
buf: &'d [u8],
) -> impl Future<Output = Result<usize, Error>> + 'd {
poll_fn(move |cx| {
if buf.is_empty() {
return Poll::Ready(Ok(0));
}
let state = T::buffered_state();
let mut tx_writer = unsafe { state.tx_buf.writer() };
let n = tx_writer.push(|data| {
let n = data.len().min(buf.len());
@ -379,14 +396,13 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
// FIFO and the number of bytes drops below a threshold. When the
// FIFO was empty we have to manually pend the interrupt to shovel
// TX data from the buffer into the FIFO.
T::Interrupt::pend();
info.interrupt.pend();
Poll::Ready(Ok(n))
})
}
fn flush() -> impl Future<Output = Result<(), Error>> {
fn flush(state: &'static State) -> impl Future<Output = Result<(), Error>> {
poll_fn(move |cx| {
let state = T::buffered_state();
if !state.tx_buf.is_empty() {
state.tx_waker.register(cx.waker());
return Poll::Pending;
@ -403,8 +419,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
}
loop {
let state = T::buffered_state();
let mut tx_writer = unsafe { state.tx_buf.writer() };
let mut tx_writer = unsafe { self.state.tx_buf.writer() };
let n = tx_writer.push(|data| {
let n = data.len().min(buf.len());
data[..n].copy_from_slice(&buf[..n]);
@ -416,7 +431,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
// FIFO and the number of bytes drops below a threshold. When the
// FIFO was empty we have to manually pend the interrupt to shovel
// TX data from the buffer into the FIFO.
T::Interrupt::pend();
self.info.interrupt.pend();
return Ok(n);
}
}
@ -425,8 +440,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
/// Flush UART TX blocking execution until done.
pub fn blocking_flush(&mut self) -> Result<(), Error> {
loop {
let state = T::buffered_state();
if state.tx_buf.is_empty() {
if self.state.tx_buf.is_empty() {
return Ok(());
}
}
@ -434,7 +448,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
/// Check if UART is busy.
pub fn busy(&self) -> bool {
T::regs().uartfr().read().busy()
self.info.regs.uartfr().read().busy()
}
/// Assert a break condition after waiting for the transmit buffers to empty,
@ -445,7 +459,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
/// This method may block for a long amount of time since it has to wait
/// for the transmit fifo to empty, which may take a while on slow links.
pub async fn send_break(&mut self, bits: u32) {
let regs = T::regs();
let regs = self.info.regs;
let bits = bits.max({
let lcr = regs.uartlcr_h().read();
let width = lcr.wlen() as u32 + 5;
@ -458,7 +472,7 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
let div_clk = clk_peri_freq() as u64 * 64;
let wait_usecs = (1_000_000 * bits as u64 * divx64 * 16 + div_clk - 1) / div_clk;
Self::flush().await.unwrap();
Self::flush(self.state).await.unwrap();
while self.busy() {}
regs.uartlcr_h().write_set(|w| w.set_brk(true));
Timer::after_micros(wait_usecs).await;
@ -466,28 +480,26 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
}
}
impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
impl Drop for BufferedUartRx {
fn drop(&mut self) {
let state = T::buffered_state();
unsafe { state.rx_buf.deinit() }
unsafe { self.state.rx_buf.deinit() }
// TX is inactive if the buffer is not available.
// We can now unregister the interrupt handler
if !state.tx_buf.is_available() {
T::Interrupt::disable();
if !self.state.tx_buf.is_available() {
self.info.interrupt.disable();
}
}
}
impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
impl Drop for BufferedUartTx {
fn drop(&mut self) {
let state = T::buffered_state();
unsafe { state.tx_buf.deinit() }
unsafe { self.state.tx_buf.deinit() }
// RX is inactive if the buffer is not available.
// We can now unregister the interrupt handler
if !state.rx_buf.is_available() {
T::Interrupt::disable();
if !self.state.rx_buf.is_available() {
self.info.interrupt.disable();
}
}
}
@ -499,7 +511,7 @@ pub struct BufferedInterruptHandler<T: Instance> {
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for BufferedInterruptHandler<T> {
unsafe fn on_interrupt() {
let r = T::regs();
let r = T::info().regs;
if r.uartdmacr().read().rxdmae() {
return;
}
@ -603,95 +615,95 @@ impl embedded_io::Error for Error {
}
}
impl<'d, T: Instance> embedded_io_async::ErrorType for BufferedUart<'d, T> {
impl embedded_io_async::ErrorType for BufferedUart {
type Error = Error;
}
impl<'d, T: Instance> embedded_io_async::ErrorType for BufferedUartRx<'d, T> {
impl embedded_io_async::ErrorType for BufferedUartRx {
type Error = Error;
}
impl<'d, T: Instance> embedded_io_async::ErrorType for BufferedUartTx<'d, T> {
impl embedded_io_async::ErrorType for BufferedUartTx {
type Error = Error;
}
impl<'d, T: Instance + 'd> embedded_io_async::Read for BufferedUart<'d, T> {
impl embedded_io_async::Read for BufferedUart {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
BufferedUartRx::<'d, T>::read(buf).await
BufferedUartRx::read(self.rx.info, self.rx.state, buf).await
}
}
impl<'d, T: Instance + 'd> embedded_io_async::Read for BufferedUartRx<'d, T> {
impl embedded_io_async::Read for BufferedUartRx {
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
Self::read(buf).await
Self::read(self.info, self.state, buf).await
}
}
impl<'d, T: Instance + 'd> embedded_io_async::ReadReady for BufferedUart<'d, T> {
impl embedded_io_async::ReadReady for BufferedUart {
fn read_ready(&mut self) -> Result<bool, Self::Error> {
BufferedUartRx::<'d, T>::read_ready()
BufferedUartRx::read_ready(self.rx.state)
}
}
impl<'d, T: Instance + 'd> embedded_io_async::ReadReady for BufferedUartRx<'d, T> {
impl embedded_io_async::ReadReady for BufferedUartRx {
fn read_ready(&mut self) -> Result<bool, Self::Error> {
Self::read_ready()
Self::read_ready(self.state)
}
}
impl<'d, T: Instance + 'd> embedded_io_async::BufRead for BufferedUart<'d, T> {
impl embedded_io_async::BufRead for BufferedUart {
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
BufferedUartRx::<'d, T>::fill_buf().await
BufferedUartRx::fill_buf(self.rx.state).await
}
fn consume(&mut self, amt: usize) {
BufferedUartRx::<'d, T>::consume(amt)
BufferedUartRx::consume(self.rx.info, self.rx.state, amt)
}
}
impl<'d, T: Instance + 'd> embedded_io_async::BufRead for BufferedUartRx<'d, T> {
impl embedded_io_async::BufRead for BufferedUartRx {
async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
Self::fill_buf().await
Self::fill_buf(self.state).await
}
fn consume(&mut self, amt: usize) {
Self::consume(amt)
Self::consume(self.info, self.state, amt)
}
}
impl<'d, T: Instance + 'd> embedded_io_async::Write for BufferedUart<'d, T> {
impl embedded_io_async::Write for BufferedUart {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
BufferedUartTx::<'d, T>::write(buf).await
BufferedUartTx::write(self.tx.info, self.tx.state, buf).await
}
async fn flush(&mut self) -> Result<(), Self::Error> {
BufferedUartTx::<'d, T>::flush().await
BufferedUartTx::flush(self.tx.state).await
}
}
impl<'d, T: Instance + 'd> embedded_io_async::Write for BufferedUartTx<'d, T> {
impl embedded_io_async::Write for BufferedUartTx {
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
Self::write(buf).await
Self::write(self.info, self.state, buf).await
}
async fn flush(&mut self) -> Result<(), Self::Error> {
Self::flush().await
Self::flush(self.state).await
}
}
impl<'d, T: Instance + 'd> embedded_io::Read for BufferedUart<'d, T> {
impl embedded_io::Read for BufferedUart {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.rx.blocking_read(buf)
}
}
impl<'d, T: Instance + 'd> embedded_io::Read for BufferedUartRx<'d, T> {
impl embedded_io::Read for BufferedUartRx {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
self.blocking_read(buf)
}
}
impl<'d, T: Instance + 'd> embedded_io::Write for BufferedUart<'d, T> {
impl embedded_io::Write for BufferedUart {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.tx.blocking_write(buf)
}
@ -701,7 +713,7 @@ impl<'d, T: Instance + 'd> embedded_io::Write for BufferedUart<'d, T> {
}
}
impl<'d, T: Instance + 'd> embedded_io::Write for BufferedUartTx<'d, T> {
impl embedded_io::Write for BufferedUartTx {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.blocking_write(buf)
}
@ -711,11 +723,11 @@ impl<'d, T: Instance + 'd> embedded_io::Write for BufferedUartTx<'d, T> {
}
}
impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d, T> {
impl embedded_hal_02::serial::Read<u8> for BufferedUartRx {
type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
let r = T::regs();
let r = self.info.regs;
if r.uartfr().read().rxfe() {
return Err(nb::Error::WouldBlock);
}
@ -736,7 +748,7 @@ impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d, T
}
}
impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx<'d, T> {
impl embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx {
type Error = Error;
fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> {
@ -755,7 +767,7 @@ impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedU
}
}
impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d, T> {
impl embedded_hal_02::serial::Read<u8> for BufferedUart {
type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
@ -763,7 +775,7 @@ impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d, T>
}
}
impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUart<'d, T> {
impl embedded_hal_02::blocking::serial::Write<u8> for BufferedUart {
type Error = Error;
fn bwrite_all(&mut self, mut buffer: &[u8]) -> Result<(), Self::Error> {
@ -782,25 +794,25 @@ impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedU
}
}
impl<'d, T: Instance> embedded_hal_nb::serial::ErrorType for BufferedUartRx<'d, T> {
impl embedded_hal_nb::serial::ErrorType for BufferedUartRx {
type Error = Error;
}
impl<'d, T: Instance> embedded_hal_nb::serial::ErrorType for BufferedUartTx<'d, T> {
impl embedded_hal_nb::serial::ErrorType for BufferedUartTx {
type Error = Error;
}
impl<'d, T: Instance> embedded_hal_nb::serial::ErrorType for BufferedUart<'d, T> {
impl embedded_hal_nb::serial::ErrorType for BufferedUart {
type Error = Error;
}
impl<'d, T: Instance> embedded_hal_nb::serial::Read for BufferedUartRx<'d, T> {
impl embedded_hal_nb::serial::Read for BufferedUartRx {
fn read(&mut self) -> nb::Result<u8, Self::Error> {
embedded_hal_02::serial::Read::read(self)
}
}
impl<'d, T: Instance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, T> {
impl embedded_hal_nb::serial::Write for BufferedUartTx {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other)
}
@ -810,13 +822,13 @@ impl<'d, T: Instance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, T> {
}
}
impl<'d, T: Instance> embedded_hal_nb::serial::Read for BufferedUart<'d, T> {
impl embedded_hal_nb::serial::Read for BufferedUart {
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
embedded_hal_02::serial::Read::read(&mut self.rx)
}
}
impl<'d, T: Instance> embedded_hal_nb::serial::Write for BufferedUart<'d, T> {
impl embedded_hal_nb::serial::Write for BufferedUart {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map(drop).map_err(nb::Error::Other)
}

View File

@ -13,7 +13,8 @@ use pac::uart::regs::Uartris;
use crate::clocks::clk_peri_freq;
use crate::dma::{AnyChannel, Channel};
use crate::gpio::{AnyPin, SealedPin};
use crate::interrupt::typelevel::{Binding, Interrupt};
use crate::interrupt::typelevel::{Binding, Interrupt as _};
use crate::interrupt::{Interrupt, InterruptExt};
use crate::pac::io::vals::{Inover, Outover};
use crate::{interrupt, pac, peripherals, RegExt};
@ -135,37 +136,41 @@ pub struct DmaState {
}
/// UART driver.
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>,
}
/// UART TX driver.
pub struct UartTx<'d, T: Instance, M: Mode> {
pub struct UartTx<'d, M: Mode> {
info: &'static Info,
tx_dma: Option<Peri<'d, AnyChannel>>,
phantom: PhantomData<(&'d mut T, M)>,
phantom: PhantomData<M>,
}
/// UART RX driver.
pub struct UartRx<'d, T: Instance, M: Mode> {
pub struct UartRx<'d, M: Mode> {
info: &'static Info,
dma_state: &'static DmaState,
rx_dma: Option<Peri<'d, AnyChannel>>,
phantom: PhantomData<(&'d mut T, M)>,
phantom: PhantomData<M>,
}
impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
impl<'d, M: Mode> UartTx<'d, M> {
/// Create a new DMA-enabled UART which can only send data
pub fn new(
pub fn new<T: Instance>(
_uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
tx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
Uart::<T, M>::init(Some(tx.into()), None, None, None, config);
Self::new_inner(Some(tx_dma.into()))
Uart::<M>::init(T::info(), Some(tx.into()), None, None, None, config);
Self::new_inner(T::info(), Some(tx_dma.into()))
}
fn new_inner(tx_dma: Option<Peri<'d, AnyChannel>>) -> Self {
fn new_inner(info: &'static Info, tx_dma: Option<Peri<'d, AnyChannel>>) -> Self {
Self {
info,
tx_dma,
phantom: PhantomData,
}
@ -173,7 +178,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
/// Transmit the provided buffer blocking execution until done.
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let r = T::regs();
let r = self.info.regs;
for &b in buffer {
while r.uartfr().read().txff() {}
r.uartdr().write(|w| w.set_data(b));
@ -183,14 +188,13 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
/// Flush UART TX blocking execution until done.
pub fn blocking_flush(&mut self) -> Result<(), Error> {
let r = T::regs();
while !r.uartfr().read().txfe() {}
while !self.info.regs.uartfr().read().txfe() {}
Ok(())
}
/// Check if UART is busy transmitting.
pub fn busy(&self) -> bool {
T::regs().uartfr().read().busy()
self.info.regs.uartfr().read().busy()
}
/// Assert a break condition after waiting for the transmit buffers to empty,
@ -201,7 +205,7 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
/// This method may block for a long amount of time since it has to wait
/// for the transmit fifo to empty, which may take a while on slow links.
pub async fn send_break(&mut self, bits: u32) {
let regs = T::regs();
let regs = self.info.regs;
let bits = bits.max({
let lcr = regs.uartlcr_h().read();
let width = lcr.wlen() as u32 + 5;
@ -222,65 +226,80 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
}
}
impl<'d, T: Instance> UartTx<'d, T, Blocking> {
impl<'d> UartTx<'d, Blocking> {
/// Create a new UART TX instance for blocking mode operations.
pub fn new_blocking(_uart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self {
Uart::<T, Blocking>::init(Some(tx.into()), None, None, None, config);
Self::new_inner(None)
pub fn new_blocking<T: Instance>(_uart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self {
Uart::<Blocking>::init(T::info(), Some(tx.into()), None, None, None, config);
Self::new_inner(T::info(), None)
}
/// Convert this uart TX instance into a buffered uart using the provided
/// irq and transmit buffer.
pub fn into_buffered(
pub fn into_buffered<T: Instance>(
self,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx_buffer: &'d mut [u8],
) -> BufferedUartTx<'d, T> {
buffered::init_buffers::<T>(irq, Some(tx_buffer), None);
) -> BufferedUartTx {
buffered::init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), None);
BufferedUartTx { phantom: PhantomData }
BufferedUartTx {
info: T::info(),
state: T::buffered_state(),
}
}
}
impl<'d, T: Instance> UartTx<'d, T, Async> {
impl<'d> UartTx<'d, Async> {
/// Write to UART TX from the provided buffer using DMA.
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let ch = self.tx_dma.as_mut().unwrap().reborrow();
let transfer = unsafe {
T::regs().uartdmacr().write_set(|reg| {
self.info.regs.uartdmacr().write_set(|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().as_ptr() as *mut _, T::TX_DREQ.into())
crate::dma::write(
ch,
buffer,
self.info.regs.uartdr().as_ptr() as *mut _,
self.info.tx_dreq.into(),
)
};
transfer.await;
Ok(())
}
}
impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
impl<'d, M: Mode> UartRx<'d, M> {
/// Create a new DMA-enabled UART which can only receive data
pub fn new(
pub fn new<T: Instance>(
_uart: Peri<'d, T>,
rx: Peri<'d, impl RxPin<T>>,
_irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
rx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
Uart::<T, M>::init(None, Some(rx.into()), None, None, config);
Self::new_inner(true, Some(rx_dma.into()))
Uart::<M>::init(T::info(), None, Some(rx.into()), None, None, config);
Self::new_inner(T::info(), T::dma_state(), true, Some(rx_dma.into()))
}
fn new_inner(has_irq: bool, rx_dma: Option<Peri<'d, AnyChannel>>) -> Self {
fn new_inner(
info: &'static Info,
dma_state: &'static DmaState,
has_irq: bool,
rx_dma: Option<Peri<'d, AnyChannel>>,
) -> Self {
debug_assert_eq!(has_irq, rx_dma.is_some());
if has_irq {
// disable all error interrupts initially
T::regs().uartimsc().write(|w| w.0 = 0);
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
info.regs.uartimsc().write(|w| w.0 = 0);
info.interrupt.unpend();
unsafe { info.interrupt.enable() };
}
Self {
info,
dma_state,
rx_dma,
phantom: PhantomData,
}
@ -299,7 +318,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
/// encountered. in both cases, `len` is the number of *good* bytes copied into
/// `buffer`.
fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, (usize, Error)> {
let r = T::regs();
let r = self.info.regs;
for (i, b) in buffer.iter_mut().enumerate() {
if r.uartfr().read().rxfe() {
return Ok(i);
@ -323,12 +342,12 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
}
}
impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
impl<'d, M: Mode> Drop for UartRx<'d, M> {
fn drop(&mut self) {
if self.rx_dma.is_some() {
T::Interrupt::disable();
self.info.interrupt.disable();
// clear dma flags. irq handlers use these to disambiguate among themselves.
T::regs().uartdmacr().write_clear(|reg| {
self.info.regs.uartdmacr().write_clear(|reg| {
reg.set_rxdmae(true);
reg.set_txdmae(true);
reg.set_dmaonerr(true);
@ -337,23 +356,26 @@ impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
}
}
impl<'d, T: Instance> UartRx<'d, T, Blocking> {
impl<'d> UartRx<'d, Blocking> {
/// Create a new UART RX instance for blocking mode operations.
pub fn new_blocking(_uart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self {
Uart::<T, Blocking>::init(None, Some(rx.into()), None, None, config);
Self::new_inner(false, None)
pub fn new_blocking<T: Instance>(_uart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self {
Uart::<Blocking>::init(T::info(), None, Some(rx.into()), None, None, config);
Self::new_inner(T::info(), T::dma_state(), false, None)
}
/// Convert this uart RX instance into a buffered uart using the provided
/// irq and receive buffer.
pub fn into_buffered(
pub fn into_buffered<T: Instance>(
self,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
rx_buffer: &'d mut [u8],
) -> BufferedUartRx<'d, T> {
buffered::init_buffers::<T>(irq, None, Some(rx_buffer));
) -> BufferedUartRx {
buffered::init_buffers(T::info(), T::buffered_state(), None, Some(rx_buffer));
BufferedUartRx { phantom: PhantomData }
BufferedUartRx {
info: T::info(),
state: T::buffered_state(),
}
}
}
@ -364,7 +386,7 @@ pub struct InterruptHandler<T: Instance> {
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() {
let uart = T::regs();
let uart = T::info().regs;
if !uart.uartdmacr().read().rxdmae() {
return;
}
@ -380,13 +402,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
}
}
impl<'d, T: Instance> UartRx<'d, T, Async> {
impl<'d> UartRx<'d, Async> {
/// Read from UART RX into the provided buffer.
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
// clear error flags before we drain the fifo. errors that have accumulated
// in the flags will also be present in the fifo.
T::dma_state().rx_errs.store(0, Ordering::Relaxed);
T::regs().uarticr().write(|w| {
self.dma_state.rx_errs.store(0, Ordering::Relaxed);
self.info.regs.uarticr().write(|w| {
w.set_oeic(true);
w.set_beic(true);
w.set_peic(true);
@ -408,28 +430,33 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
// interrupt flags will have been raised, and those will be picked up immediately
// by the interrupt handler.
let ch = self.rx_dma.as_mut().unwrap().reborrow();
T::regs().uartimsc().write_set(|w| {
self.info.regs.uartimsc().write_set(|w| {
w.set_oeim(true);
w.set_beim(true);
w.set_peim(true);
w.set_feim(true);
});
T::regs().uartdmacr().write_set(|reg| {
self.info.regs.uartdmacr().write_set(|reg| {
reg.set_rxdmae(true);
reg.set_dmaonerr(true);
});
let transfer = unsafe {
// 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().as_ptr() as *const _, buffer, T::RX_DREQ.into())
crate::dma::read(
ch,
self.info.regs.uartdr().as_ptr() as *const _,
buffer,
self.info.rx_dreq.into(),
)
};
// wait for either the transfer to complete or an error to happen.
let transfer_result = select(
transfer,
poll_fn(|cx| {
T::dma_state().rx_err_waker.register(cx.waker());
match T::dma_state().rx_errs.swap(0, Ordering::Relaxed) {
self.dma_state.rx_err_waker.register(cx.waker());
match self.dma_state.rx_errs.swap(0, Ordering::Relaxed) {
0 => Poll::Pending,
e => Poll::Ready(Uartris(e as u32)),
}
@ -441,7 +468,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
Either::First(()) => {
// We're here because the DMA finished, BUT if an error occurred on the LAST
// byte, then we may still need to grab the error state!
Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32)
Uartris(self.dma_state.rx_errs.swap(0, Ordering::Relaxed) as u32)
}
Either::Second(e) => {
// We're here because we errored, which means this is the error that
@ -521,8 +548,8 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
) -> Result<usize, ReadToBreakError> {
// clear error flags before we drain the fifo. errors that have accumulated
// in the flags will also be present in the fifo.
T::dma_state().rx_errs.store(0, Ordering::Relaxed);
T::regs().uarticr().write(|w| {
self.dma_state.rx_errs.store(0, Ordering::Relaxed);
self.info.regs.uarticr().write(|w| {
w.set_oeic(true);
w.set_beic(true);
w.set_peic(true);
@ -555,13 +582,13 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
// interrupt flags will have been raised, and those will be picked up immediately
// by the interrupt handler.
let ch = self.rx_dma.as_mut().unwrap();
T::regs().uartimsc().write_set(|w| {
self.info.regs.uartimsc().write_set(|w| {
w.set_oeim(true);
w.set_beim(true);
w.set_peim(true);
w.set_feim(true);
});
T::regs().uartdmacr().write_set(|reg| {
self.info.regs.uartdmacr().write_set(|reg| {
reg.set_rxdmae(true);
reg.set_dmaonerr(true);
});
@ -572,9 +599,9 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
// is held across an await and makes the future non-Send.
crate::dma::read(
ch.reborrow(),
T::regs().uartdr().as_ptr() as *const _,
self.info.regs.uartdr().as_ptr() as *const _,
sbuffer,
T::RX_DREQ.into(),
self.info.rx_dreq.into(),
)
};
@ -582,8 +609,8 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
let transfer_result = select(
transfer,
poll_fn(|cx| {
T::dma_state().rx_err_waker.register(cx.waker());
match T::dma_state().rx_errs.swap(0, Ordering::Relaxed) {
self.dma_state.rx_err_waker.register(cx.waker());
match self.dma_state.rx_errs.swap(0, Ordering::Relaxed) {
0 => Poll::Pending,
e => Poll::Ready(Uartris(e as u32)),
}
@ -596,7 +623,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
Either::First(()) => {
// We're here because the DMA finished, BUT if an error occurred on the LAST
// byte, then we may still need to grab the error state!
Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32)
Uartris(self.dma_state.rx_errs.swap(0, Ordering::Relaxed) as u32)
}
Either::Second(e) => {
// We're here because we errored, which means this is the error that
@ -635,7 +662,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
continue;
}
let regs = T::regs();
let regs = self.info.regs;
let all_full = next_addr == eval;
// NOTE: This is off label usage of RSR! See the issue below for
@ -685,9 +712,9 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
}
}
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(
pub fn new_blocking<T: Instance>(
uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
@ -697,7 +724,7 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
}
/// Create a new UART with hardware flow control (RTS/CTS)
pub fn new_with_rtscts_blocking(
pub fn new_with_rtscts_blocking<T: Instance>(
uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
@ -720,24 +747,30 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
/// Convert this uart instance into a buffered uart using the provided
/// irq, transmit and receive buffers.
pub fn into_buffered(
pub fn into_buffered<T: Instance>(
self,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
_irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
) -> BufferedUart<'d, T> {
buffered::init_buffers::<T>(irq, Some(tx_buffer), Some(rx_buffer));
) -> BufferedUart {
buffered::init_buffers(T::info(), T::buffered_state(), Some(tx_buffer), Some(rx_buffer));
BufferedUart {
rx: BufferedUartRx { phantom: PhantomData },
tx: BufferedUartTx { phantom: PhantomData },
rx: BufferedUartRx {
info: T::info(),
state: T::buffered_state(),
},
tx: BufferedUartTx {
info: T::info(),
state: T::buffered_state(),
},
}
}
}
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(
pub fn new<T: Instance>(
uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
@ -760,7 +793,7 @@ 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(
pub fn new_with_rtscts<T: Instance>(
uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
@ -785,8 +818,8 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
}
}
impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
fn new_inner(
impl<'d, M: Mode> Uart<'d, M> {
fn new_inner<T: Instance>(
_uart: Peri<'d, T>,
mut tx: Peri<'d, AnyPin>,
mut rx: Peri<'d, AnyPin>,
@ -798,6 +831,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
config: Config,
) -> Self {
Self::init(
T::info(),
Some(tx.reborrow()),
Some(rx.reborrow()),
rts.as_mut().map(|x| x.reborrow()),
@ -806,19 +840,20 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
);
Self {
tx: UartTx::new_inner(tx_dma),
rx: UartRx::new_inner(has_irq, rx_dma),
tx: UartTx::new_inner(T::info(), tx_dma),
rx: UartRx::new_inner(T::info(), T::dma_state(), has_irq, rx_dma),
}
}
fn init(
info: &Info,
tx: Option<Peri<'_, AnyPin>>,
rx: Option<Peri<'_, AnyPin>>,
rts: Option<Peri<'_, AnyPin>>,
cts: Option<Peri<'_, AnyPin>>,
config: Config,
) {
let r = T::regs();
let r = info.regs;
if let Some(pin) = &tx {
let funcsel = {
let pin_number = ((pin.gpio().as_ptr() as u32) & 0x1FF) / 8;
@ -896,7 +931,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
});
}
Self::set_baudrate_inner(config.baudrate);
Self::set_baudrate_inner(info, config.baudrate);
let (pen, eps) = match config.parity {
Parity::ParityNone => (false, false),
@ -926,8 +961,8 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
});
}
fn lcr_modify<R>(f: impl FnOnce(&mut crate::pac::uart::regs::UartlcrH) -> R) -> R {
let r = T::regs();
fn lcr_modify<R>(info: &Info, f: impl FnOnce(&mut crate::pac::uart::regs::UartlcrH) -> R) -> R {
let r = info.regs;
// Notes from PL011 reference manual:
//
@ -978,11 +1013,11 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
/// sets baudrate on runtime
pub fn set_baudrate(&mut self, baudrate: u32) {
Self::set_baudrate_inner(baudrate);
Self::set_baudrate_inner(self.tx.info, baudrate);
}
fn set_baudrate_inner(baudrate: u32) {
let r = T::regs();
fn set_baudrate_inner(info: &Info, baudrate: u32) {
let r = info.regs;
let clk_base = crate::clocks::clk_peri_freq();
@ -1002,11 +1037,11 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
r.uartibrd().write_value(pac::uart::regs::Uartibrd(baud_ibrd));
r.uartfbrd().write_value(pac::uart::regs::Uartfbrd(baud_fbrd));
Self::lcr_modify(|_| {});
Self::lcr_modify(info, |_| {});
}
}
impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
impl<'d, M: Mode> Uart<'d, M> {
/// Transmit the provided buffer blocking execution until done.
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
self.tx.blocking_write(buffer)
@ -1034,19 +1069,19 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
/// Split the Uart into a transmitter and receiver, which is particularly
/// 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)
}
/// Split the Uart into a transmitter and receiver by mutable reference,
/// which is particularly useful when having two tasks correlating to
/// transmitting and receiving.
pub fn split_ref(&mut self) -> (&mut UartTx<'d, T, M>, &mut UartRx<'d, T, M>) {
pub fn split_ref(&mut self) -> (&mut UartTx<'d, M>, &mut UartRx<'d, M>) {
(&mut self.tx, &mut self.rx)
}
}
impl<'d, T: Instance> Uart<'d, T, Async> {
impl<'d> Uart<'d, Async> {
/// Write to UART TX from the provided buffer.
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
self.tx.write(buffer).await
@ -1076,10 +1111,10 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
}
}
impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, M> {
impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, M> {
type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
let r = T::regs();
let r = self.info.regs;
if r.uartfr().read().rxfe() {
return Err(nb::Error::WouldBlock);
}
@ -1100,11 +1135,11 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d,
}
}
impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for UartTx<'d, T, M> {
impl<'d, M: Mode> embedded_hal_02::serial::Write<u8> for UartTx<'d, M> {
type Error = Error;
fn write(&mut self, word: u8) -> Result<(), nb::Error<Self::Error>> {
let r = T::regs();
let r = self.info.regs;
if r.uartfr().read().txff() {
return Err(nb::Error::WouldBlock);
}
@ -1114,7 +1149,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for UartTx<'d,
}
fn flush(&mut self) -> Result<(), nb::Error<Self::Error>> {
let r = T::regs();
let r = self.info.regs;
if !r.uartfr().read().txfe() {
return Err(nb::Error::WouldBlock);
}
@ -1122,7 +1157,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for UartTx<'d,
}
}
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> {
impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, M> {
type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
@ -1134,7 +1169,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for
}
}
impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> {
impl<'d, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, M> {
type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
@ -1142,7 +1177,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T,
}
}
impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for Uart<'d, T, M> {
impl<'d, M: Mode> embedded_hal_02::serial::Write<u8> for Uart<'d, M> {
type Error = Error;
fn write(&mut self, word: u8) -> Result<(), nb::Error<Self::Error>> {
@ -1154,7 +1189,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::serial::Write<u8> for Uart<'d, T
}
}
impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> {
impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, M> {
type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
@ -1177,21 +1212,21 @@ impl embedded_hal_nb::serial::Error for Error {
}
}
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, M> {
impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, M> {
type Error = Error;
}
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, M> {
impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, M> {
type Error = Error;
}
impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, T, M> {
impl<'d, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'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<u8, Self::Error> {
let r = T::regs();
let r = self.info.regs;
if r.uartfr().read().rxfe() {
return Err(nb::Error::WouldBlock);
}
@ -1212,7 +1247,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M
}
}
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)
}
@ -1222,11 +1257,11 @@ impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, T,
}
}
impl<'d, T: Instance> embedded_io::ErrorType for UartTx<'d, T, Blocking> {
impl<'d> embedded_io::ErrorType for UartTx<'d, Blocking> {
type Error = Error;
}
impl<'d, T: Instance> embedded_io::Write for UartTx<'d, T, Blocking> {
impl<'d> embedded_io::Write for UartTx<'d, Blocking> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.blocking_write(buf).map(|_| buf.len())
}
@ -1236,13 +1271,13 @@ impl<'d, T: Instance> embedded_io::Write for UartTx<'d, T, Blocking> {
}
}
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<u8, nb::Error<Self::Error>> {
embedded_hal_02::serial::Read::read(&mut self.rx)
}
}
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)
}
@ -1252,11 +1287,11 @@ impl<'d, T: Instance, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, T, M>
}
}
impl<'d, T: Instance> embedded_io::ErrorType for Uart<'d, T, Blocking> {
impl<'d> embedded_io::ErrorType for Uart<'d, Blocking> {
type Error = Error;
}
impl<'d, T: Instance> embedded_io::Write for Uart<'d, T, Blocking> {
impl<'d> embedded_io::Write for Uart<'d, Blocking> {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.blocking_write(buf).map(|_| buf.len())
}
@ -1266,13 +1301,17 @@ impl<'d, T: Instance> embedded_io::Write for Uart<'d, T, Blocking> {
}
}
struct Info {
regs: pac::uart::Uart,
tx_dreq: pac::dma::vals::TreqSel,
rx_dreq: pac::dma::vals::TreqSel,
interrupt: Interrupt,
}
trait SealedMode {}
trait SealedInstance {
const TX_DREQ: pac::dma::vals::TreqSel;
const RX_DREQ: pac::dma::vals::TreqSel;
fn regs() -> pac::uart::Uart;
fn info() -> &'static Info;
fn buffered_state() -> &'static buffered::State;
@ -1308,11 +1347,14 @@ pub trait Instance: SealedInstance + PeripheralType {
macro_rules! impl_instance {
($inst:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => {
impl SealedInstance for peripherals::$inst {
const TX_DREQ: pac::dma::vals::TreqSel = $tx_dreq;
const RX_DREQ: pac::dma::vals::TreqSel = $rx_dreq;
fn regs() -> pac::uart::Uart {
pac::$inst
fn info() -> &'static Info {
static INFO: Info = Info {
regs: pac::$inst,
tx_dreq: $tx_dreq,
rx_dreq: $rx_dreq,
interrupt: crate::interrupt::typelevel::$irq::IRQ,
};
&INFO
}
fn buffered_state() -> &'static buffered::State {

View File

@ -31,7 +31,7 @@ use rand::RngCore;
use static_cell::{ConstStaticCell, StaticCell};
use {defmt_rtt as _, panic_probe as _};
type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, UART0, uart::Async>>;
type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, uart::Async>>;
struct MyType {
inner: u32,

View File

@ -48,7 +48,7 @@ async fn main(spawner: Spawner) {
}
#[embassy_executor::task]
async fn reader(mut rx: BufferedUartRx<'static, UART0>) {
async fn reader(mut rx: BufferedUartRx) {
info!("Reading...");
loop {
let mut buf = [0; 31];

View File

@ -39,7 +39,7 @@ async fn main(spawner: Spawner) {
}
#[embassy_executor::task]
async fn reader(mut rx: UartRx<'static, UART1, Async>) {
async fn reader(mut rx: UartRx<'static, Async>) {
info!("Reading...");
loop {
// read a total of 4 transmissions (32 / 8) and then print the result

View File

@ -31,7 +31,7 @@ use rand::RngCore;
use static_cell::{ConstStaticCell, StaticCell};
use {defmt_rtt as _, panic_probe as _};
type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, UART0, uart::Async>>;
type UartAsyncMutex = mutex::Mutex<CriticalSectionRawMutex, UartTx<'static, uart::Async>>;
struct MyType {
inner: u32,

View File

@ -48,7 +48,7 @@ async fn main(spawner: Spawner) {
}
#[embassy_executor::task]
async fn reader(mut rx: BufferedUartRx<'static, UART0>) {
async fn reader(mut rx: BufferedUartRx) {
info!("Reading...");
loop {
let mut buf = [0; 31];

View File

@ -39,7 +39,7 @@ async fn main(spawner: Spawner) {
}
#[embassy_executor::task]
async fn reader(mut rx: UartRx<'static, UART1, Async>) {
async fn reader(mut rx: UartRx<'static, Async>) {
info!("Reading...");
loop {
// read a total of 4 transmissions (32 / 8) and then print the result

View File

@ -8,17 +8,17 @@ teleprobe_meta::target!(b"pimoroni-pico-plus-2");
use defmt::{assert_eq, *};
use embassy_executor::Spawner;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::uart::{Blocking, Config, Error, Instance, Parity, Uart, UartRx};
use embassy_rp::uart::{Blocking, Config, Error, Parity, Uart, UartRx};
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
fn read<const N: usize>(uart: &mut Uart<'_, Blocking>) -> Result<[u8; N], Error> {
let mut buf = [255; N];
uart.blocking_read(&mut buf)?;
Ok(buf)
}
fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Blocking>) -> Result<[u8; N], Error> {
fn read1<const N: usize>(uart: &mut UartRx<'_, Blocking>) -> Result<[u8; N], Error> {
let mut buf = [255; N];
uart.blocking_read(&mut buf)?;
Ok(buf)

View File

@ -10,7 +10,7 @@ use embassy_executor::Spawner;
use embassy_rp::bind_interrupts;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::peripherals::UART0;
use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Parity};
use embassy_time::Timer;
use embedded_io_async::{Read, ReadExactError, Write};
use {defmt_rtt as _, panic_probe as _};
@ -19,7 +19,7 @@ bind_interrupts!(struct Irqs {
UART0_IRQ => BufferedInterruptHandler<UART0>;
});
async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> {
async fn read<const N: usize>(uart: &mut BufferedUart) -> Result<[u8; N], Error> {
let mut buf = [255; N];
match uart.read_exact(&mut buf).await {
Ok(()) => Ok(buf),
@ -29,7 +29,7 @@ async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Res
}
}
async fn read1<const N: usize>(uart: &mut BufferedUartRx<'_, impl Instance>) -> Result<[u8; N], Error> {
async fn read1<const N: usize>(uart: &mut BufferedUartRx) -> Result<[u8; N], Error> {
let mut buf = [255; N];
match uart.read_exact(&mut buf).await {
Ok(()) => Ok(buf),

View File

@ -10,7 +10,7 @@ use embassy_executor::Spawner;
use embassy_rp::bind_interrupts;
use embassy_rp::gpio::{Level, Output};
use embassy_rp::peripherals::UART0;
use embassy_rp::uart::{Async, Config, Error, Instance, InterruptHandler, Parity, Uart, UartRx};
use embassy_rp::uart::{Async, Config, Error, InterruptHandler, Parity, Uart, UartRx};
use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _};
@ -18,13 +18,13 @@ bind_interrupts!(struct Irqs {
UART0_IRQ => InterruptHandler<UART0>;
});
async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
async fn read<const N: usize>(uart: &mut Uart<'_, Async>) -> Result<[u8; N], Error> {
let mut buf = [255; N];
uart.read(&mut buf).await?;
Ok(buf)
}
async fn read1<const N: usize>(uart: &mut UartRx<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
async fn read1<const N: usize>(uart: &mut UartRx<'_, Async>) -> Result<[u8; N], Error> {
let mut buf = [255; N];
uart.read(&mut buf).await?;
Ok(buf)