From b07192079f0fc6ce210104786540aa7be8938d40 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 27 Sep 2025 18:37:33 +0200 Subject: nrf/uart,timer: erase instance generics. --- embassy-nrf/src/buffered_uarte.rs | 229 ++++++++++++++++----------- embassy-nrf/src/timer.rs | 82 +++++----- embassy-nrf/src/twim.rs | 2 - embassy-nrf/src/uarte.rs | 148 ++++++++++------- examples/nrf52840/src/bin/uart_split.rs | 2 +- examples/nrf9160/src/bin/modem_tcp_client.rs | 2 +- 6 files changed, 274 insertions(+), 191 deletions(-) diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 29e126903..40c679190 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -23,6 +23,7 @@ pub use pac::uarte::vals::{Baudrate, ConfigParity as Parity}; use crate::gpio::{AnyPin, Pin as GpioPin}; use crate::interrupt::typelevel::Interrupt; +use crate::interrupt::InterruptExt; use crate::ppi::{ self, AnyConfigurableChannel, AnyGroup, Channel, ConfigurableChannel, Event, Group, Ppi, PpiGroup, Task, }; @@ -207,21 +208,21 @@ impl interrupt::typelevel::Handler for Interrupt } /// Buffered UARTE driver. -pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> { - tx: BufferedUarteTx<'d, U>, - rx: BufferedUarteRx<'d, U, T>, +pub struct BufferedUarte<'d> { + tx: BufferedUarteTx<'d>, + rx: BufferedUarteRx<'d>, } -impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {} +impl<'d> Unpin for BufferedUarte<'d> {} -impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { +impl<'d> BufferedUarte<'d> { /// Create a new BufferedUarte without hardware flow control. /// /// # Panics /// /// Panics if `rx_buffer.len()` is odd. #[allow(clippy::too_many_arguments)] - pub fn new( + pub fn new( uarte: Peri<'d, U>, timer: Peri<'d, T>, ppi_ch1: Peri<'d, impl ConfigurableChannel>, @@ -256,7 +257,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { /// /// Panics if `rx_buffer.len()` is odd. #[allow(clippy::too_many_arguments)] - pub fn new_with_rtscts( + pub fn new_with_rtscts( uarte: Peri<'d, U>, timer: Peri<'d, T>, ppi_ch1: Peri<'d, impl ConfigurableChannel>, @@ -288,7 +289,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { } #[allow(clippy::too_many_arguments)] - fn new_inner( + fn new_inner( peri: Peri<'d, U>, timer: Peri<'d, T>, ppi_ch1: Peri<'d, AnyConfigurableChannel>, @@ -302,30 +303,33 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { rx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8], ) -> Self { - configure(U::regs(), config, cts.is_some()); + let r = U::regs(); + let irq = U::Interrupt::IRQ; + let state = U::state(); + + configure(r, config, cts.is_some()); let tx = BufferedUarteTx::new_innerer(unsafe { peri.clone_unchecked() }, txd, cts, tx_buffer); let rx = BufferedUarteRx::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer); - U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED)); - U::Interrupt::pend(); - unsafe { U::Interrupt::enable() }; + r.enable().write(|w| w.set_enable(vals::Enable::ENABLED)); + irq.pend(); + unsafe { irq.enable() }; - U::state().tx_rx_refcount.store(2, Ordering::Relaxed); + state.tx_rx_refcount.store(2, Ordering::Relaxed); Self { tx, rx } } /// Adjust the baud rate to the provided value. pub fn set_baudrate(&mut self, baudrate: Baudrate) { - let r = U::regs(); - r.baudrate().write(|w| w.set_baudrate(baudrate)); + self.tx.set_baudrate(baudrate); } /// Split the UART in reader and writer parts. /// /// This allows reading and writing concurrently from independent tasks. - pub fn split(self) -> (BufferedUarteRx<'d, U, T>, BufferedUarteTx<'d, U>) { + pub fn split(self) -> (BufferedUarteRx<'d>, BufferedUarteTx<'d>) { (self.rx, self.tx) } @@ -333,7 +337,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { /// /// The returned halves borrow from `self`, so you can drop them and go back to using /// the "un-split" `self`. This allows temporarily splitting the UART. - pub fn split_by_ref(&mut self) -> (&mut BufferedUarteRx<'d, U, T>, &mut BufferedUarteTx<'d, U>) { + pub fn split_by_ref(&mut self) -> (&mut BufferedUarteRx<'d>, &mut BufferedUarteTx<'d>) { (&mut self.rx, &mut self.tx) } @@ -369,13 +373,17 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { } /// Reader part of the buffered UARTE driver. -pub struct BufferedUarteTx<'d, U: UarteInstance> { - _peri: Peri<'d, U>, +pub struct BufferedUarteTx<'d> { + r: pac::uarte::Uarte, + _irq: interrupt::Interrupt, + state: &'static crate::uarte::State, + buffered_state: &'static State, + _p: PhantomData<&'d ()>, } -impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { +impl<'d> BufferedUarteTx<'d> { /// Create a new BufferedUarteTx without hardware flow control. - pub fn new( + pub fn new( uarte: Peri<'d, U>, txd: Peri<'d, impl GpioPin>, _irq: impl interrupt::typelevel::Binding> + 'd, @@ -390,7 +398,7 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { /// # Panics /// /// Panics if `rx_buffer.len()` is odd. - pub fn new_with_cts( + pub fn new_with_cts( uarte: Peri<'d, U>, txd: Peri<'d, impl GpioPin>, cts: Peri<'d, impl GpioPin>, @@ -401,41 +409,48 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { Self::new_inner(uarte, txd.into(), Some(cts.into()), config, tx_buffer) } - fn new_inner( + fn new_inner( peri: Peri<'d, U>, txd: Peri<'d, AnyPin>, cts: Option>, config: Config, tx_buffer: &'d mut [u8], ) -> Self { - configure(U::regs(), config, cts.is_some()); + let r = U::regs(); + let irq = U::Interrupt::IRQ; + let state = U::state(); + let _buffered_state = U::buffered_state(); + + configure(r, config, cts.is_some()); let this = Self::new_innerer(peri, txd, cts, tx_buffer); - U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED)); - U::Interrupt::pend(); - unsafe { U::Interrupt::enable() }; + r.enable().write(|w| w.set_enable(vals::Enable::ENABLED)); + irq.pend(); + unsafe { irq.enable() }; - U::state().tx_rx_refcount.store(1, Ordering::Relaxed); + state.tx_rx_refcount.store(1, Ordering::Relaxed); this } - fn new_innerer( - peri: Peri<'d, U>, + fn new_innerer( + _peri: Peri<'d, U>, txd: Peri<'d, AnyPin>, cts: Option>, tx_buffer: &'d mut [u8], ) -> Self { let r = U::regs(); + let irq = U::Interrupt::IRQ; + let state = U::state(); + let buffered_state = U::buffered_state(); configure_tx_pins(r, txd, cts); // Initialize state - let s = U::buffered_state(); - s.tx_count.store(0, Ordering::Relaxed); + buffered_state.tx_count.store(0, Ordering::Relaxed); let len = tx_buffer.len(); - unsafe { s.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; + unsafe { buffered_state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; r.events_txstarted().write_value(0); @@ -444,15 +459,21 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { w.set_endtx(true); }); - Self { _peri: peri } + Self { + r, + _irq: irq, + state, + buffered_state, + _p: PhantomData, + } } /// Write a buffer into this writer, returning how many bytes were written. - pub fn write<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + 'a { + pub fn write<'a>(&'a mut self, buf: &'a [u8]) -> impl Future> + 'a + use<'a, 'd> { poll_fn(move |cx| { //trace!("poll_write: {:?}", buf.len()); - let ss = U::state(); - let s = U::buffered_state(); + let ss = self.state; + let s = self.buffered_state; let mut tx = unsafe { s.tx_buf.writer() }; let tx_buf = tx.push_slice(); @@ -469,7 +490,7 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { //trace!("poll_write: queued {:?}", n); compiler_fence(Ordering::SeqCst); - U::Interrupt::pend(); + self._irq.pend(); Poll::Ready(Ok(n)) }) @@ -478,7 +499,7 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { /// Try writing a buffer without waiting, returning how many bytes were written. pub fn try_write(&mut self, buf: &[u8]) -> Result { //trace!("poll_write: {:?}", buf.len()); - let s = U::buffered_state(); + let s = self.buffered_state; let mut tx = unsafe { s.tx_buf.writer() }; let tx_buf = tx.push_slice(); @@ -493,17 +514,17 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { //trace!("poll_write: queued {:?}", n); compiler_fence(Ordering::SeqCst); - U::Interrupt::pend(); + self._irq.pend(); Ok(n) } /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination. pub fn flush(&mut self) -> impl Future> + '_ { + let ss = self.state; + let s = self.buffered_state; poll_fn(move |cx| { //trace!("poll_flush"); - let ss = U::state(); - let s = U::buffered_state(); if !s.tx_buf.is_empty() { //trace!("poll_flush: pending"); ss.tx_waker.register(cx.waker()); @@ -513,11 +534,16 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> { Poll::Ready(Ok(())) }) } + + /// Adjust the baud rate to the provided value. + pub fn set_baudrate(&mut self, baudrate: Baudrate) { + self.r.baudrate().write(|w| w.set_baudrate(baudrate)); + } } -impl<'a, U: UarteInstance> Drop for BufferedUarteTx<'a, U> { +impl<'a> Drop for BufferedUarteTx<'a> { fn drop(&mut self) { - let r = U::regs(); + let r = self.r; r.intenclr().write(|w| { w.set_txdrdy(true); @@ -528,31 +554,34 @@ impl<'a, U: UarteInstance> Drop for BufferedUarteTx<'a, U> { r.tasks_stoptx().write_value(1); while r.events_txstopped().read() == 0 {} - let s = U::buffered_state(); + let s = self.buffered_state; unsafe { s.tx_buf.deinit() } - let s = U::state(); + let s = self.state; drop_tx_rx(r, s); } } /// Reader part of the buffered UARTE driver. -pub struct BufferedUarteRx<'d, U: UarteInstance, T: TimerInstance> { - _peri: Peri<'d, U>, - timer: Timer<'d, T>, +pub struct BufferedUarteRx<'d> { + r: pac::uarte::Uarte, + state: &'static crate::uarte::State, + buffered_state: &'static State, + timer: Timer<'d>, _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 1>, _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 2>, _ppi_group: PpiGroup<'d, AnyGroup>, + _p: PhantomData<&'d ()>, } -impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { +impl<'d> BufferedUarteRx<'d> { /// Create a new BufferedUarte without hardware flow control. /// /// # Panics /// /// Panics if `rx_buffer.len()` is odd. #[allow(clippy::too_many_arguments)] - pub fn new( + pub fn new( uarte: Peri<'d, U>, timer: Peri<'d, T>, ppi_ch1: Peri<'d, impl ConfigurableChannel>, @@ -582,7 +611,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { /// /// Panics if `rx_buffer.len()` is odd. #[allow(clippy::too_many_arguments)] - pub fn new_with_rts( + pub fn new_with_rts( uarte: Peri<'d, U>, timer: Peri<'d, T>, ppi_ch1: Peri<'d, impl ConfigurableChannel>, @@ -608,7 +637,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { } #[allow(clippy::too_many_arguments)] - fn new_inner( + fn new_inner( peri: Peri<'d, U>, timer: Peri<'d, T>, ppi_ch1: Peri<'d, AnyConfigurableChannel>, @@ -619,22 +648,27 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { config: Config, rx_buffer: &'d mut [u8], ) -> Self { - configure(U::regs(), config, rts.is_some()); + let r = U::regs(); + let irq = U::Interrupt::IRQ; + let state = U::state(); + let _buffered_state = U::buffered_state(); + + configure(r, config, rts.is_some()); let this = Self::new_innerer(peri, timer, ppi_ch1, ppi_ch2, ppi_group, rxd, rts, rx_buffer); - U::regs().enable().write(|w| w.set_enable(vals::Enable::ENABLED)); - U::Interrupt::pend(); - unsafe { U::Interrupt::enable() }; + r.enable().write(|w| w.set_enable(vals::Enable::ENABLED)); + irq.pend(); + unsafe { irq.enable() }; - U::state().tx_rx_refcount.store(1, Ordering::Relaxed); + state.tx_rx_refcount.store(1, Ordering::Relaxed); this } #[allow(clippy::too_many_arguments)] - fn new_innerer( - peri: Peri<'d, U>, + fn new_innerer( + _peri: Peri<'d, U>, timer: Peri<'d, T>, ppi_ch1: Peri<'d, AnyConfigurableChannel>, ppi_ch2: Peri<'d, AnyConfigurableChannel>, @@ -646,16 +680,17 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { assert!(rx_buffer.len() % 2 == 0); let r = U::regs(); + let state = U::state(); + let buffered_state = U::buffered_state(); configure_rx_pins(r, rxd, rts); // Initialize state - let s = U::buffered_state(); - s.rx_started_count.store(0, Ordering::Relaxed); - s.rx_ended_count.store(0, Ordering::Relaxed); - s.rx_started.store(false, Ordering::Relaxed); + buffered_state.rx_started_count.store(0, Ordering::Relaxed); + buffered_state.rx_ended_count.store(0, Ordering::Relaxed); + buffered_state.rx_started.store(false, Ordering::Relaxed); let rx_len = rx_buffer.len().min(EASY_DMA_SIZE * 2); - unsafe { s.rx_buf.init(rx_buffer.as_mut_ptr(), rx_len) }; + unsafe { buffered_state.rx_buf.init(rx_buffer.as_mut_ptr(), rx_len) }; // clear errors let errors = r.errorsrc().read(); @@ -683,7 +718,9 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { let mut ppi_ch1 = Ppi::new_one_to_one(ppi_ch1, Event::from_reg(r.events_rxdrdy()), timer.task_count()); ppi_ch1.enable(); - s.rx_ppi_ch.store(ppi_ch2.number() as u8, Ordering::Relaxed); + buffered_state + .rx_ppi_ch + .store(ppi_ch2.number() as u8, Ordering::Relaxed); let mut ppi_group = PpiGroup::new(ppi_group); let mut ppi_ch2 = Ppi::new_one_to_two( ppi_ch2, @@ -695,11 +732,14 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { ppi_group.add_channel(&ppi_ch2); Self { - _peri: peri, + r, + state, + buffered_state, timer, _ppi_ch1: ppi_ch1, _ppi_ch2: ppi_ch2, _ppi_group: ppi_group, + _p: PhantomData, } } @@ -714,17 +754,17 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { /// Return the contents of the internal buffer, filling it with more data from the inner reader if it is empty. pub fn fill_buf(&mut self) -> impl Future> { + let r = self.r; + let s = self.buffered_state; + let ss = self.state; + let timer = &self.timer; poll_fn(move |cx| { compiler_fence(Ordering::SeqCst); //trace!("poll_read"); - let r = U::regs(); - let s = U::buffered_state(); - let ss = U::state(); - // Read the RXDRDY counter. - T::regs().tasks_capture(0).write_value(1); - let mut end = T::regs().cc(0).read() as usize; + timer.cc(0).capture(); + let mut end = timer.cc(0).read() as usize; //trace!(" rxdrdy count = {:?}", end); // We've set a compare channel that resets the counter to 0 when it reaches `len*2`. @@ -771,24 +811,24 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> { return; } - let s = U::buffered_state(); + let s = self.buffered_state; let mut rx = unsafe { s.rx_buf.reader() }; rx.pop_done(amt); - U::regs().intenset().write(|w| w.set_rxstarted(true)); + self.r.intenset().write(|w| w.set_rxstarted(true)); } /// we are ready to read if there is data in the buffer - fn read_ready() -> Result { - let state = U::buffered_state(); + fn read_ready(&self) -> Result { + let state = self.buffered_state; Ok(!state.rx_buf.is_empty()) } } -impl<'a, U: UarteInstance, T: TimerInstance> Drop for BufferedUarteRx<'a, U, T> { +impl<'a> Drop for BufferedUarteRx<'a> { fn drop(&mut self) { self._ppi_group.disable_all(); - let r = U::regs(); + let r = self.r; self.timer.stop(); @@ -801,10 +841,10 @@ impl<'a, U: UarteInstance, T: TimerInstance> Drop for BufferedUarteRx<'a, U, T> r.tasks_stoprx().write_value(1); while r.events_rxto().read() == 0 {} - let s = U::buffered_state(); + let s = self.buffered_state; unsafe { s.rx_buf.deinit() } - let s = U::state(); + let s = self.state; drop_tx_rx(r, s); } } @@ -818,43 +858,44 @@ mod _embedded_io { } } - impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::ErrorType for BufferedUarte<'d, U, T> { + impl<'d> embedded_io_async::ErrorType for BufferedUarte<'d> { type Error = Error; } - impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::ErrorType for BufferedUarteRx<'d, U, T> { + impl<'d> embedded_io_async::ErrorType for BufferedUarteRx<'d> { type Error = Error; } - impl<'d, U: UarteInstance> embedded_io_async::ErrorType for BufferedUarteTx<'d, U> { + impl<'d> embedded_io_async::ErrorType for BufferedUarteTx<'d> { type Error = Error; } - impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::Read for BufferedUarte<'d, U, T> { + impl<'d> embedded_io_async::Read for BufferedUarte<'d> { async fn read(&mut self, buf: &mut [u8]) -> Result { self.read(buf).await } } - impl<'d: 'd, U: UarteInstance, T: TimerInstance> embedded_io_async::Read for BufferedUarteRx<'d, U, T> { + impl<'d> embedded_io_async::Read for BufferedUarteRx<'d> { async fn read(&mut self, buf: &mut [u8]) -> Result { self.read(buf).await } } - impl<'d, U: UarteInstance, T: TimerInstance + 'd> embedded_io_async::ReadReady for BufferedUarte<'d, U, T> { + impl<'d> embedded_io_async::ReadReady for BufferedUarte<'d> { fn read_ready(&mut self) -> Result { - BufferedUarteRx::<'d, U, T>::read_ready() + self.rx.read_ready() } } - impl<'d, U: UarteInstance, T: TimerInstance + 'd> embedded_io_async::ReadReady for BufferedUarteRx<'d, U, T> { + impl<'d> embedded_io_async::ReadReady for BufferedUarteRx<'d> { fn read_ready(&mut self) -> Result { - Self::read_ready() + let state = self.buffered_state; + Ok(!state.rx_buf.is_empty()) } } - impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::BufRead for BufferedUarte<'d, U, T> { + impl<'d> embedded_io_async::BufRead for BufferedUarte<'d> { async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { self.fill_buf().await } @@ -864,7 +905,7 @@ mod _embedded_io { } } - impl<'d: 'd, U: UarteInstance, T: TimerInstance> embedded_io_async::BufRead for BufferedUarteRx<'d, U, T> { + impl<'d> embedded_io_async::BufRead for BufferedUarteRx<'d> { async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> { self.fill_buf().await } @@ -874,7 +915,7 @@ mod _embedded_io { } } - impl<'d, U: UarteInstance, T: TimerInstance> embedded_io_async::Write for BufferedUarte<'d, U, T> { + impl<'d> embedded_io_async::Write for BufferedUarte<'d> { async fn write(&mut self, buf: &[u8]) -> Result { self.write(buf).await } @@ -884,7 +925,7 @@ mod _embedded_io { } } - impl<'d: 'd, U: UarteInstance> embedded_io_async::Write for BufferedUarteTx<'d, U> { + impl<'d> embedded_io_async::Write for BufferedUarteTx<'d> { async fn write(&mut self, buf: &[u8]) -> Result { self.write(buf).await } diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index 1d1f77ea8..0b0bb9780 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -6,6 +6,8 @@ #![macro_use] +use core::marker::PhantomData; + use embassy_hal_internal::{Peri, PeripheralType}; use crate::pac; @@ -81,16 +83,18 @@ pub enum Frequency { /// /// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter /// or trigger an event when the counter reaches a certain value. -pub struct Timer<'d, T: Instance> { - _p: Peri<'d, T>, +pub struct Timer<'d> { + r: pac::timer::Timer, + ccs: usize, + _p: PhantomData<&'d ()>, } -impl<'d, T: Instance> Timer<'d, T> { +impl<'d> Timer<'d> { /// Create a new `Timer` driver. /// /// This can be useful for triggering tasks via PPI. /// `Uarte` uses this internally. - pub fn new(timer: Peri<'d, T>) -> Self { + pub fn new(timer: Peri<'d, T>) -> Self { Self::new_inner(timer, false) } @@ -98,14 +102,18 @@ impl<'d, T: Instance> Timer<'d, T> { /// /// This can be useful for triggering tasks via PPI. /// `Uarte` uses this internally. - pub fn new_counter(timer: Peri<'d, T>) -> Self { + pub fn new_counter(timer: Peri<'d, T>) -> Self { Self::new_inner(timer, true) } - fn new_inner(timer: Peri<'d, T>, is_counter: bool) -> Self { + fn new_inner(_timer: Peri<'d, T>, is_counter: bool) -> Self { let regs = T::regs(); - let this = Self { _p: timer }; + let this = Self { + r: regs, + ccs: T::CCS, + _p: PhantomData, + }; // Stop the timer before doing anything else, // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. @@ -131,7 +139,7 @@ impl<'d, T: Instance> Timer<'d, T> { // Default to the max frequency of the lower power clock this.set_frequency(Frequency::F1MHz); - for n in 0..T::CCS { + for n in 0..this.ccs { let cc = this.cc(n); // Initialize all the shorts as disabled. cc.unshort_compare_clear(); @@ -147,43 +155,43 @@ impl<'d, T: Instance> Timer<'d, T> { #[cfg(feature = "unstable-pac")] #[inline] pub fn regs(&mut self) -> pac::timer::Timer { - T::regs() + self.r } /// Starts the timer. pub fn start(&self) { - T::regs().tasks_start().write_value(1) + self.r.tasks_start().write_value(1) } /// Stops the timer. pub fn stop(&self) { - T::regs().tasks_stop().write_value(1) + self.r.tasks_stop().write_value(1) } /// Reset the timer's counter to 0. pub fn clear(&self) { - T::regs().tasks_clear().write_value(1) + self.r.tasks_clear().write_value(1) } /// Returns the START task, for use with PPI. /// /// When triggered, this task starts the timer. pub fn task_start(&self) -> Task<'d> { - Task::from_reg(T::regs().tasks_start()) + Task::from_reg(self.r.tasks_start()) } /// Returns the STOP task, for use with PPI. /// /// When triggered, this task stops the timer. pub fn task_stop(&self) -> Task<'d> { - Task::from_reg(T::regs().tasks_stop()) + Task::from_reg(self.r.tasks_stop()) } /// Returns the CLEAR task, for use with PPI. /// /// When triggered, this task resets the timer's counter to 0. pub fn task_clear(&self) -> Task<'d> { - Task::from_reg(T::regs().tasks_clear()) + Task::from_reg(self.r.tasks_clear()) } /// Returns the COUNT task, for use with PPI. @@ -191,7 +199,7 @@ impl<'d, T: Instance> Timer<'d, T> { /// When triggered, this task increments the timer's counter by 1. /// Only works in counter mode. pub fn task_count(&self) -> Task<'d> { - Task::from_reg(T::regs().tasks_count()) + Task::from_reg(self.r.tasks_count()) } /// Change the timer's frequency. @@ -201,7 +209,7 @@ impl<'d, T: Instance> Timer<'d, T> { pub fn set_frequency(&self, frequency: Frequency) { self.stop(); - T::regs() + self.r .prescaler() // SAFETY: `frequency` is a variant of `Frequency`, // whose values are all in the range of 0-9 (the valid range of `prescaler`). @@ -212,18 +220,19 @@ impl<'d, T: Instance> Timer<'d, T> { /// /// # Panics /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer). - pub fn cc(&self, n: usize) -> Cc<'d, T> { - if n >= T::CCS { - panic!("Cannot get CC register {} of timer with {} CC registers.", n, T::CCS); + pub fn cc(&self, n: usize) -> Cc<'d> { + if n >= self.ccs { + panic!("Cannot get CC register {} of timer with {} CC registers.", n, self.ccs); } Cc { n, - _p: unsafe { self._p.clone_unchecked() }, + r: self.r, + _p: PhantomData, } } } -impl Timer<'static, T> { +impl Timer<'static> { /// Persist the timer's configuration for the rest of the program's lifetime. This method /// should be preferred over [`core::mem::forget()`] because the `'static` bound prevents /// accidental reuse of the underlying peripheral. @@ -232,7 +241,7 @@ impl Timer<'static, T> { } } -impl<'d, T: Instance> Drop for Timer<'d, T> { +impl<'d> Drop for Timer<'d> { fn drop(&mut self) { self.stop(); } @@ -245,27 +254,28 @@ impl<'d, T: Instance> Drop for Timer<'d, T> { /// /// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register. /// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register -pub struct Cc<'d, T: Instance> { +pub struct Cc<'d> { n: usize, - _p: Peri<'d, T>, + r: pac::timer::Timer, + _p: PhantomData<&'d ()>, } -impl<'d, T: Instance> Cc<'d, T> { +impl<'d> Cc<'d> { /// Get the current value stored in the register. pub fn read(&self) -> u32 { - T::regs().cc(self.n).read() + self.r.cc(self.n).read() } /// Set the value stored in the register. /// /// `event_compare` will fire when the timer's counter reaches this value. pub fn write(&self, value: u32) { - T::regs().cc(self.n).write_value(value); + self.r.cc(self.n).write_value(value); } /// Capture the current value of the timer's counter in this register, and return it. pub fn capture(&self) -> u32 { - T::regs().tasks_capture(self.n).write_value(1); + self.r.tasks_capture(self.n).write_value(1); self.read() } @@ -273,20 +283,20 @@ impl<'d, T: Instance> Cc<'d, T> { /// /// When triggered, this task will capture the current value of the timer's counter in this register. pub fn task_capture(&self) -> Task<'d> { - Task::from_reg(T::regs().tasks_capture(self.n)) + Task::from_reg(self.r.tasks_capture(self.n)) } /// Returns this CC register's COMPARE event, for use with PPI. /// /// This event will fire when the timer's counter reaches the value in this CC register. pub fn event_compare(&self) -> Event<'d> { - Event::from_reg(T::regs().events_compare(self.n)) + Event::from_reg(self.r.events_compare(self.n)) } /// Clear the COMPARE event for this CC register. #[inline] pub fn clear_events(&self) { - T::regs().events_compare(self.n).write_value(0); + self.r.events_compare(self.n).write_value(0); } /// Enable the shortcut between this CC register's COMPARE event and the timer's CLEAR task. @@ -295,12 +305,12 @@ impl<'d, T: Instance> Cc<'d, T> { /// /// So, when the timer's counter reaches the value stored in this register, the timer's counter will be reset to 0. pub fn short_compare_clear(&self) { - T::regs().shorts().modify(|w| w.set_compare_clear(self.n, true)) + self.r.shorts().modify(|w| w.set_compare_clear(self.n, true)) } /// Disable the shortcut between this CC register's COMPARE event and the timer's CLEAR task. pub fn unshort_compare_clear(&self) { - T::regs().shorts().modify(|w| w.set_compare_clear(self.n, false)) + self.r.shorts().modify(|w| w.set_compare_clear(self.n, false)) } /// Enable the shortcut between this CC register's COMPARE event and the timer's STOP task. @@ -309,11 +319,11 @@ impl<'d, T: Instance> Cc<'d, T> { /// /// So, when the timer's counter reaches the value stored in this register, the timer will stop counting up. pub fn short_compare_stop(&self) { - T::regs().shorts().modify(|w| w.set_compare_stop(self.n, true)) + self.r.shorts().modify(|w| w.set_compare_stop(self.n, true)) } /// Disable the shortcut between this CC register's COMPARE event and the timer's STOP task. pub fn unshort_compare_stop(&self) { - T::regs().shorts().modify(|w| w.set_compare_stop(self.n, false)) + self.r.shorts().modify(|w| w.set_compare_stop(self.n, false)) } } diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs index ffc9b39f6..943ea9d31 100644 --- a/embassy-nrf/src/twim.rs +++ b/embassy-nrf/src/twim.rs @@ -114,7 +114,6 @@ impl interrupt::typelevel::Handler for InterruptHandl /// TWI driver. pub struct Twim<'d> { r: pac::twim::Twim, - irq: interrupt::Interrupt, state: &'static State, tx_ram_buffer: &'d mut [u8], _p: PhantomData<&'d ()>, @@ -171,7 +170,6 @@ impl<'d> Twim<'d> { let mut twim = Self { r: T::regs(), - irq: T::Interrupt::IRQ, state: T::state(), tx_ram_buffer, _p: PhantomData {}, diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 927a0ac08..66fb3b3f2 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -132,28 +132,32 @@ impl interrupt::typelevel::Handler for InterruptHandl } /// UARTE driver. -pub struct Uarte<'d, T: Instance> { - tx: UarteTx<'d, T>, - rx: UarteRx<'d, T>, +pub struct Uarte<'d> { + tx: UarteTx<'d>, + rx: UarteRx<'d>, } /// Transmitter part of the UARTE driver. /// /// This can be obtained via [`Uarte::split`], or created directly. -pub struct UarteTx<'d, T: Instance> { - _p: Peri<'d, T>, +pub struct UarteTx<'d> { + r: pac::uarte::Uarte, + state: &'static State, + _p: PhantomData<&'d ()>, } /// Receiver part of the UARTE driver. /// /// This can be obtained via [`Uarte::split`], or created directly. -pub struct UarteRx<'d, T: Instance> { - _p: Peri<'d, T>, +pub struct UarteRx<'d> { + r: pac::uarte::Uarte, + state: &'static State, + _p: PhantomData<&'d ()>, } -impl<'d, T: Instance> Uarte<'d, T> { +impl<'d> Uarte<'d> { /// Create a new UARTE without hardware flow control - pub fn new( + pub fn new( uarte: Peri<'d, T>, rxd: Peri<'d, impl GpioPin>, txd: Peri<'d, impl GpioPin>, @@ -164,7 +168,7 @@ impl<'d, T: Instance> Uarte<'d, T> { } /// Create a new UARTE with hardware flow control (RTS/CTS) - pub fn new_with_rtscts( + pub fn new_with_rtscts( uarte: Peri<'d, T>, rxd: Peri<'d, impl GpioPin>, txd: Peri<'d, impl GpioPin>, @@ -183,8 +187,8 @@ impl<'d, T: Instance> Uarte<'d, T> { ) } - fn new_inner( - uarte: Peri<'d, T>, + fn new_inner( + _uarte: Peri<'d, T>, rxd: Peri<'d, AnyPin>, txd: Peri<'d, AnyPin>, cts: Option>, @@ -211,16 +215,22 @@ impl<'d, T: Instance> Uarte<'d, T> { Self { tx: UarteTx { - _p: unsafe { uarte.clone_unchecked() }, + r: T::regs(), + state: T::state(), + _p: PhantomData {}, + }, + rx: UarteRx { + r: T::regs(), + state: T::state(), + _p: PhantomData {}, }, - rx: UarteRx { _p: uarte }, } } /// Split the Uarte into the transmitter and receiver parts. /// /// This is useful to concurrently transmit and receive from independent tasks. - pub fn split(self) -> (UarteTx<'d, T>, UarteRx<'d, T>) { + pub fn split(self) -> (UarteTx<'d>, UarteRx<'d>) { (self.tx, self.rx) } @@ -228,7 +238,7 @@ impl<'d, T: Instance> Uarte<'d, T> { /// /// The returned halves borrow from `self`, so you can drop them and go back to using /// the "un-split" `self`. This allows temporarily splitting the UART. - pub fn split_by_ref(&mut self) -> (&mut UarteTx<'d, T>, &mut UarteRx<'d, T>) { + pub fn split_by_ref(&mut self) -> (&mut UarteTx<'d>, &mut UarteRx<'d>) { (&mut self.tx, &mut self.rx) } @@ -240,13 +250,13 @@ impl<'d, T: Instance> Uarte<'d, T> { timer: Peri<'d, U>, ppi_ch1: Peri<'d, impl ConfigurableChannel + 'd>, ppi_ch2: Peri<'d, impl ConfigurableChannel + 'd>, - ) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) { + ) -> (UarteTx<'d>, UarteRxWithIdle<'d>) { (self.tx, self.rx.with_idle(timer, ppi_ch1, ppi_ch2)) } /// Return the endtx event for use with PPI pub fn event_endtx(&self) -> Event<'_> { - let r = T::regs(); + let r = self.tx.r; Event::from_reg(r.events_endtx()) } @@ -343,9 +353,9 @@ pub(crate) fn configure(r: pac::uarte::Uarte, config: Config, hardware_flow_cont apply_workaround_for_enable_anomaly(r); } -impl<'d, T: Instance> UarteTx<'d, T> { +impl<'d> UarteTx<'d> { /// Create a new tx-only UARTE without hardware flow control - pub fn new( + pub fn new( uarte: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, txd: Peri<'d, impl GpioPin>, @@ -355,7 +365,7 @@ impl<'d, T: Instance> UarteTx<'d, T> { } /// Create a new tx-only UARTE with hardware flow control (RTS/CTS) - pub fn new_with_rtscts( + pub fn new_with_rtscts( uarte: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, txd: Peri<'d, impl GpioPin>, @@ -365,7 +375,12 @@ impl<'d, T: Instance> UarteTx<'d, T> { Self::new_inner(uarte, txd.into(), Some(cts.into()), config) } - fn new_inner(uarte: Peri<'d, T>, txd: Peri<'d, AnyPin>, cts: Option>, config: Config) -> Self { + fn new_inner( + _uarte: Peri<'d, T>, + txd: Peri<'d, AnyPin>, + cts: Option>, + config: Config, + ) -> Self { let r = T::regs(); configure(r, config, cts.is_some()); @@ -378,7 +393,11 @@ impl<'d, T: Instance> UarteTx<'d, T> { let s = T::state(); s.tx_rx_refcount.store(1, Ordering::Relaxed); - Self { _p: uarte } + Self { + r: T::regs(), + state: T::state(), + _p: PhantomData {}, + } } /// Write all bytes in the buffer. @@ -409,8 +428,8 @@ impl<'d, T: Instance> UarteTx<'d, T> { let ptr = buffer.as_ptr(); let len = buffer.len(); - let r = T::regs(); - let s = T::state(); + let r = self.r; + let s = self.state; let drop = OnDrop::new(move || { trace!("write drop: stopping"); @@ -479,7 +498,7 @@ impl<'d, T: Instance> UarteTx<'d, T> { let ptr = buffer.as_ptr(); let len = buffer.len(); - let r = T::regs(); + let r = self.r; r.txd().ptr().write_value(ptr as u32); r.txd().maxcnt().write(|w| w.set_maxcnt(len as _)); @@ -501,11 +520,11 @@ impl<'d, T: Instance> UarteTx<'d, T> { } } -impl<'a, T: Instance> Drop for UarteTx<'a, T> { +impl<'a> Drop for UarteTx<'a> { fn drop(&mut self) { trace!("uarte tx drop"); - let r = T::regs(); + let r = self.r; let did_stoptx = r.events_txstarted().read() != 0; trace!("did_stoptx {}", did_stoptx); @@ -513,15 +532,15 @@ impl<'a, T: Instance> Drop for UarteTx<'a, T> { // Wait for txstopped, if needed. while did_stoptx && r.events_txstopped().read() == 0 {} - let s = T::state(); + let s = self.state; drop_tx_rx(r, s); } } -impl<'d, T: Instance> UarteRx<'d, T> { +impl<'d> UarteRx<'d> { /// Create a new rx-only UARTE without hardware flow control - pub fn new( + pub fn new( uarte: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, rxd: Peri<'d, impl GpioPin>, @@ -531,7 +550,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { } /// Create a new rx-only UARTE with hardware flow control (RTS/CTS) - pub fn new_with_rtscts( + pub fn new_with_rtscts( uarte: Peri<'d, T>, _irq: impl interrupt::typelevel::Binding> + 'd, rxd: Peri<'d, impl GpioPin>, @@ -543,13 +562,18 @@ impl<'d, T: Instance> UarteRx<'d, T> { /// Check for errors and clear the error register if an error occured. fn check_and_clear_errors(&mut self) -> Result<(), Error> { - let r = T::regs(); + let r = self.r; let err_bits = r.errorsrc().read(); r.errorsrc().write_value(err_bits); ErrorSource::from_bits_truncate(err_bits.0).check() } - fn new_inner(uarte: Peri<'d, T>, rxd: Peri<'d, AnyPin>, rts: Option>, config: Config) -> Self { + fn new_inner( + _uarte: Peri<'d, T>, + rxd: Peri<'d, AnyPin>, + rts: Option>, + config: Config, + ) -> Self { let r = T::regs(); configure(r, config, rts.is_some()); @@ -562,7 +586,11 @@ impl<'d, T: Instance> UarteRx<'d, T> { let s = T::state(); s.tx_rx_refcount.store(1, Ordering::Relaxed); - Self { _p: uarte } + Self { + r: T::regs(), + state: T::state(), + _p: PhantomData {}, + } } /// Upgrade to an instance that supports idle line detection. @@ -571,10 +599,10 @@ impl<'d, T: Instance> UarteRx<'d, T> { timer: Peri<'d, U>, ppi_ch1: Peri<'d, impl ConfigurableChannel + 'd>, ppi_ch2: Peri<'d, impl ConfigurableChannel + 'd>, - ) -> UarteRxWithIdle<'d, T, U> { + ) -> UarteRxWithIdle<'d> { let timer = Timer::new(timer); - let r = T::regs(); + let r = self.r; // BAUDRATE register values are `baudrate * 2^32 / 16000000` // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values @@ -605,11 +633,15 @@ impl<'d, T: Instance> UarteRx<'d, T> { ); ppi_ch2.enable(); + let state = self.state; + UarteRxWithIdle { rx: self, timer, - ppi_ch1, + ppi_ch1: ppi_ch1, _ppi_ch2: ppi_ch2, + r: r, + state: state, } } @@ -625,8 +657,8 @@ impl<'d, T: Instance> UarteRx<'d, T> { let ptr = buffer.as_ptr(); let len = buffer.len(); - let r = T::regs(); - let s = T::state(); + let r = self.r; + let s = self.state; let drop = OnDrop::new(move || { trace!("read drop: stopping"); @@ -692,7 +724,7 @@ impl<'d, T: Instance> UarteRx<'d, T> { let ptr = buffer.as_ptr(); let len = buffer.len(); - let r = T::regs(); + let r = self.r; r.rxd().ptr().write_value(ptr as u32); r.rxd().maxcnt().write(|w| w.set_maxcnt(len as _)); @@ -718,11 +750,11 @@ impl<'d, T: Instance> UarteRx<'d, T> { } } -impl<'a, T: Instance> Drop for UarteRx<'a, T> { +impl<'a> Drop for UarteRx<'a> { fn drop(&mut self) { trace!("uarte rx drop"); - let r = T::regs(); + let r = self.r; let did_stoprx = r.events_rxstarted().read() != 0; trace!("did_stoprx {}", did_stoprx); @@ -730,7 +762,7 @@ impl<'a, T: Instance> Drop for UarteRx<'a, T> { // Wait for rxto, if needed. while did_stoprx && r.events_rxto().read() == 0 {} - let s = T::state(); + let s = self.state; drop_tx_rx(r, s); } @@ -739,14 +771,16 @@ impl<'a, T: Instance> Drop for UarteRx<'a, T> { /// Receiver part of the UARTE driver, with `read_until_idle` support. /// /// This can be obtained via [`Uarte::split_with_idle`]. -pub struct UarteRxWithIdle<'d, T: Instance, U: TimerInstance> { - rx: UarteRx<'d, T>, - timer: Timer<'d, U>, +pub struct UarteRxWithIdle<'d> { + rx: UarteRx<'d>, + timer: Timer<'d>, ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>, _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>, + r: pac::uarte::Uarte, + state: &'static State, } -impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { +impl<'d> UarteRxWithIdle<'d> { /// Read bytes until the buffer is filled. pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { self.ppi_ch1.disable(); @@ -773,8 +807,8 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { let ptr = buffer.as_ptr(); let len = buffer.len(); - let r = T::regs(); - let s = T::state(); + let r = self.r; + let s = self.state; self.ppi_ch1.enable(); @@ -846,7 +880,7 @@ impl<'d, T: Instance, U: TimerInstance> UarteRxWithIdle<'d, T, U> { let ptr = buffer.as_ptr(); let len = buffer.len(); - let r = T::regs(); + let r = self.r; self.ppi_ch1.enable(); @@ -997,7 +1031,7 @@ macro_rules! impl_uarte { mod eh02 { use super::*; - impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write for Uarte<'d, T> { + impl<'d> embedded_hal_02::blocking::serial::Write for Uarte<'d> { type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { @@ -1009,7 +1043,7 @@ mod eh02 { } } - impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write for UarteTx<'d, T> { + impl<'d> embedded_hal_02::blocking::serial::Write for UarteTx<'d> { type Error = Error; fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { @@ -1038,22 +1072,22 @@ mod _embedded_io { } } - impl<'d, U: Instance> embedded_io_async::ErrorType for Uarte<'d, U> { + impl<'d> embedded_io_async::ErrorType for Uarte<'d> { type Error = Error; } - impl<'d, U: Instance> embedded_io_async::ErrorType for UarteTx<'d, U> { + impl<'d> embedded_io_async::ErrorType for UarteTx<'d> { type Error = Error; } - impl<'d, U: Instance> embedded_io_async::Write for Uarte<'d, U> { + impl<'d> embedded_io_async::Write for Uarte<'d> { async fn write(&mut self, buf: &[u8]) -> Result { self.write(buf).await?; Ok(buf.len()) } } - impl<'d: 'd, U: Instance> embedded_io_async::Write for UarteTx<'d, U> { + impl<'d> embedded_io_async::Write for UarteTx<'d> { async fn write(&mut self, buf: &[u8]) -> Result { self.write(buf).await?; Ok(buf.len()) diff --git a/examples/nrf52840/src/bin/uart_split.rs b/examples/nrf52840/src/bin/uart_split.rs index 51af90727..d75143126 100644 --- a/examples/nrf52840/src/bin/uart_split.rs +++ b/examples/nrf52840/src/bin/uart_split.rs @@ -52,7 +52,7 @@ async fn main(spawner: Spawner) { } #[embassy_executor::task] -async fn reader(mut rx: UarteRx<'static, UARTE0>) { +async fn reader(mut rx: UarteRx<'static>) { let mut buf = [0; 8]; loop { info!("reading..."); diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs index 7d4815699..460a4cfae 100644 --- a/examples/nrf9160/src/bin/modem_tcp_client.rs +++ b/examples/nrf9160/src/bin/modem_tcp_client.rs @@ -32,7 +32,7 @@ bind_interrupts!(struct Irqs { }); #[embassy_executor::task] -async fn trace_task(mut uart: BufferedUarteTx<'static, peripherals::SERIAL0>, reader: TraceReader<'static>) -> ! { +async fn trace_task(mut uart: BufferedUarteTx<'static>, reader: TraceReader<'static>) -> ! { let mut rx = [0u8; 1024]; loop { let n = reader.read(&mut rx[..]).await; -- cgit