diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 8ec0fb2ce..7c9a2344e 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -14,28 +14,15 @@ use embassy_hal_common::{low_power_wait_until, unborrow}; use crate::gpio::sealed::Pin as _; use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; -use crate::ppi::{AnyChannel, Channel, Event, Ppi, Task}; +use crate::interconnect::{AnyChannel, Event, OneToOneChannel, OneToTwoChannel, Ppi, Task}; +use crate::pac; use crate::timer::Instance as TimerInstance; use crate::timer::{Frequency, Timer}; use crate::uarte::{Config, Instance as UarteInstance}; -use crate::{pac, ppi}; // Re-export SVD variants to allow user to directly set values pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; -#[non_exhaustive] -#[derive(Clone, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum Error { - PpiError(ppi::Error), -} - -impl From for Error { - fn from(e: ppi::Error) -> Self { - Self::PpiError(e) - } -} - #[derive(Copy, Clone, Debug, PartialEq)] enum RxState { Idle, @@ -58,8 +45,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> { struct StateInner<'d, U: UarteInstance, T: TimerInstance> { phantom: PhantomData<&'d mut U>, timer: Timer<'d, T>, - _ppi_ch1: Ppi<'d, AnyChannel>, - _ppi_ch2: Ppi<'d, AnyChannel>, + _ppi_ch1: Ppi<'d, AnyChannel, 1, 2>, + _ppi_ch2: Ppi<'d, AnyChannel, 1, 1>, rx: RingBuffer<'d>, rx_state: RxState, @@ -79,15 +66,12 @@ impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> { impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { /// unsafe: may not leak self or futures - /// - /// - *Note:* ppi_ch1 must have at least 1 free event and 2 free tasks or a PPI error is returned - /// - *Note:* ppi_ch2 must have at least 1 free event and 1 free tasks or a PPI error is returned pub unsafe fn new( state: &'d mut State<'d, U, T>, _uarte: impl Unborrow + 'd, timer: impl Unborrow + 'd, - ppi_ch1: impl Unborrow + 'd, - ppi_ch2: impl Unborrow + 'd, + ppi_ch1: impl Unborrow + 'd, + ppi_ch2: impl Unborrow + 'd, irq: impl Unborrow + 'd, rxd: impl Unborrow + 'd, txd: impl Unborrow + 'd, @@ -96,7 +80,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { config: Config, rx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8], - ) -> Result { + ) -> Self { unborrow!(ppi_ch1, ppi_ch2, irq, rxd, txd, cts, rts); let r = U::regs(); @@ -160,18 +144,24 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { timer.cc(0).short_compare_clear(); timer.cc(0).short_compare_stop(); - let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade()); - ppi_ch1.publish(Event::from_reg(&r.events_rxdrdy))?; - ppi_ch1.subscribe(timer.task_clear())?; - ppi_ch1.subscribe(timer.task_start())?; + let mut ppi_ch1 = Ppi::new_one_to_two( + ppi_ch1, + Event::from_reg(&r.events_rxdrdy), + timer.task_clear(), + timer.task_start(), + ) + .degrade(); ppi_ch1.enable(); - let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade()); - ppi_ch2.publish(timer.cc(0).event_compare())?; - ppi_ch2.subscribe(Task::from_reg(&r.tasks_stoprx))?; + let mut ppi_ch2 = Ppi::new_one_to_one( + ppi_ch2, + timer.cc(0).event_compare(), + Task::from_reg(&r.tasks_stoprx), + ) + .degrade(); ppi_ch2.enable(); - Ok(Self { + Self { inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner { phantom: PhantomData, timer, @@ -186,7 +176,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { tx_state: TxState::Idle, tx_waker: WakerRegistration::new(), }), - }) + } } pub fn set_baudrate(&mut self, baudrate: Baudrate) { diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs index 03fc5f307..326f4a8be 100644 --- a/embassy-nrf/src/chips/nrf52805.rs +++ b/embassy-nrf/src/chips/nrf52805.rs @@ -167,28 +167,28 @@ impl_pin!(P0_29, 0, 29); impl_pin!(P0_30, 0, 30); impl_pin!(P0_31, 0, 31); -impl_ppi_channel!(PPI_CH0, 0, 2, 1); -impl_ppi_channel!(PPI_CH1, 1, 2, 1); -impl_ppi_channel!(PPI_CH2, 2, 2, 1); -impl_ppi_channel!(PPI_CH3, 3, 2, 1); -impl_ppi_channel!(PPI_CH4, 4, 2, 1); -impl_ppi_channel!(PPI_CH5, 5, 2, 1); -impl_ppi_channel!(PPI_CH6, 6, 2, 1); -impl_ppi_channel!(PPI_CH7, 7, 2, 1); -impl_ppi_channel!(PPI_CH8, 8, 2, 1); -impl_ppi_channel!(PPI_CH9, 9, 2, 1); -impl_ppi_channel!(PPI_CH20, 20, 1, 0); -impl_ppi_channel!(PPI_CH21, 21, 1, 0); -impl_ppi_channel!(PPI_CH22, 22, 1, 0); -impl_ppi_channel!(PPI_CH23, 23, 1, 0); -impl_ppi_channel!(PPI_CH24, 24, 1, 0); -impl_ppi_channel!(PPI_CH25, 25, 1, 0); -impl_ppi_channel!(PPI_CH26, 26, 1, 0); -impl_ppi_channel!(PPI_CH27, 27, 1, 0); -impl_ppi_channel!(PPI_CH28, 28, 1, 0); -impl_ppi_channel!(PPI_CH29, 29, 1, 0); -impl_ppi_channel!(PPI_CH30, 30, 1, 0); -impl_ppi_channel!(PPI_CH31, 31, 1, 0); +impl_ppi_channel!(PPI_CH0, 0, true, 1, 2); +impl_ppi_channel!(PPI_CH1, 1, true, 1, 2); +impl_ppi_channel!(PPI_CH2, 2, true, 1, 2); +impl_ppi_channel!(PPI_CH3, 3, true, 1, 2); +impl_ppi_channel!(PPI_CH4, 4, true, 1, 2); +impl_ppi_channel!(PPI_CH5, 5, true, 1, 2); +impl_ppi_channel!(PPI_CH6, 6, true, 1, 2); +impl_ppi_channel!(PPI_CH7, 7, true, 1, 2); +impl_ppi_channel!(PPI_CH8, 8, true, 1, 2); +impl_ppi_channel!(PPI_CH9, 9, true, 1, 2); +impl_ppi_channel!(PPI_CH20, 20, false, 0, 1); +impl_ppi_channel!(PPI_CH21, 21, false, 0, 1); +impl_ppi_channel!(PPI_CH22, 22, false, 0, 1); +impl_ppi_channel!(PPI_CH23, 23, false, 0, 1); +impl_ppi_channel!(PPI_CH24, 24, false, 0, 1); +impl_ppi_channel!(PPI_CH25, 25, false, 0, 1); +impl_ppi_channel!(PPI_CH26, 26, false, 0, 1); +impl_ppi_channel!(PPI_CH27, 27, false, 0, 1); +impl_ppi_channel!(PPI_CH28, 28, false, 0, 1); +impl_ppi_channel!(PPI_CH29, 29, false, 0, 1); +impl_ppi_channel!(PPI_CH30, 30, false, 0, 1); +impl_ppi_channel!(PPI_CH31, 31, false, 0, 1); impl_saadc_input!(P0_04, ANALOGINPUT2); impl_saadc_input!(P0_05, ANALOGINPUT3); diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index e317e4c54..4c16d51a7 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -172,38 +172,38 @@ impl_pin!(P0_29, 0, 29); impl_pin!(P0_30, 0, 30); impl_pin!(P0_31, 0, 31); -impl_ppi_channel!(PPI_CH0, 0, 2, 1); -impl_ppi_channel!(PPI_CH1, 1, 2, 1); -impl_ppi_channel!(PPI_CH2, 2, 2, 1); -impl_ppi_channel!(PPI_CH3, 3, 2, 1); -impl_ppi_channel!(PPI_CH4, 4, 2, 1); -impl_ppi_channel!(PPI_CH5, 5, 2, 1); -impl_ppi_channel!(PPI_CH6, 6, 2, 1); -impl_ppi_channel!(PPI_CH7, 7, 2, 1); -impl_ppi_channel!(PPI_CH8, 8, 2, 1); -impl_ppi_channel!(PPI_CH9, 9, 2, 1); -impl_ppi_channel!(PPI_CH10, 10, 2, 1); -impl_ppi_channel!(PPI_CH11, 11, 2, 1); -impl_ppi_channel!(PPI_CH12, 12, 2, 1); -impl_ppi_channel!(PPI_CH13, 13, 2, 1); -impl_ppi_channel!(PPI_CH14, 14, 2, 1); -impl_ppi_channel!(PPI_CH15, 15, 2, 1); -impl_ppi_channel!(PPI_CH16, 16, 2, 1); -impl_ppi_channel!(PPI_CH17, 17, 2, 1); -impl_ppi_channel!(PPI_CH18, 18, 2, 1); -impl_ppi_channel!(PPI_CH19, 19, 2, 1); -impl_ppi_channel!(PPI_CH20, 20, 1, 0); -impl_ppi_channel!(PPI_CH21, 21, 1, 0); -impl_ppi_channel!(PPI_CH22, 22, 1, 0); -impl_ppi_channel!(PPI_CH23, 23, 1, 0); -impl_ppi_channel!(PPI_CH24, 24, 1, 0); -impl_ppi_channel!(PPI_CH25, 25, 1, 0); -impl_ppi_channel!(PPI_CH26, 26, 1, 0); -impl_ppi_channel!(PPI_CH27, 27, 1, 0); -impl_ppi_channel!(PPI_CH28, 28, 1, 0); -impl_ppi_channel!(PPI_CH29, 29, 1, 0); -impl_ppi_channel!(PPI_CH30, 30, 1, 0); -impl_ppi_channel!(PPI_CH31, 31, 1, 0); +impl_ppi_channel!(PPI_CH0, 0, true, 1, 2); +impl_ppi_channel!(PPI_CH1, 1, true, 1, 2); +impl_ppi_channel!(PPI_CH2, 2, true, 1, 2); +impl_ppi_channel!(PPI_CH3, 3, true, 1, 2); +impl_ppi_channel!(PPI_CH4, 4, true, 1, 2); +impl_ppi_channel!(PPI_CH5, 5, true, 1, 2); +impl_ppi_channel!(PPI_CH6, 6, true, 1, 2); +impl_ppi_channel!(PPI_CH7, 7, true, 1, 2); +impl_ppi_channel!(PPI_CH8, 8, true, 1, 2); +impl_ppi_channel!(PPI_CH9, 9, true, 1, 2); +impl_ppi_channel!(PPI_CH10, 10, true, 1, 2); +impl_ppi_channel!(PPI_CH11, 11, true, 1, 2); +impl_ppi_channel!(PPI_CH12, 12, true, 1, 2); +impl_ppi_channel!(PPI_CH13, 13, true, 1, 2); +impl_ppi_channel!(PPI_CH14, 14, true, 1, 2); +impl_ppi_channel!(PPI_CH15, 15, true, 1, 2); +impl_ppi_channel!(PPI_CH16, 16, true, 1, 2); +impl_ppi_channel!(PPI_CH17, 17, true, 1, 2); +impl_ppi_channel!(PPI_CH18, 18, true, 1, 2); +impl_ppi_channel!(PPI_CH19, 19, true, 1, 2); +impl_ppi_channel!(PPI_CH20, 20, false, 0, 1); +impl_ppi_channel!(PPI_CH21, 21, false, 0, 1); +impl_ppi_channel!(PPI_CH22, 22, false, 0, 1); +impl_ppi_channel!(PPI_CH23, 23, false, 0, 1); +impl_ppi_channel!(PPI_CH24, 24, false, 0, 1); +impl_ppi_channel!(PPI_CH25, 25, false, 0, 1); +impl_ppi_channel!(PPI_CH26, 26, false, 0, 1); +impl_ppi_channel!(PPI_CH27, 27, false, 0, 1); +impl_ppi_channel!(PPI_CH28, 28, false, 0, 1); +impl_ppi_channel!(PPI_CH29, 29, false, 0, 1); +impl_ppi_channel!(PPI_CH30, 30, false, 0, 1); +impl_ppi_channel!(PPI_CH31, 31, false, 0, 1); impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_03, ANALOGINPUT1); diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index 748f5f4ba..0c54d9b9e 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -173,38 +173,38 @@ impl_pin!(P0_29, 0, 29); impl_pin!(P0_30, 0, 30); impl_pin!(P0_31, 0, 31); -impl_ppi_channel!(PPI_CH0, 0, 2, 1); -impl_ppi_channel!(PPI_CH1, 1, 2, 1); -impl_ppi_channel!(PPI_CH2, 2, 2, 1); -impl_ppi_channel!(PPI_CH3, 3, 2, 1); -impl_ppi_channel!(PPI_CH4, 4, 2, 1); -impl_ppi_channel!(PPI_CH5, 5, 2, 1); -impl_ppi_channel!(PPI_CH6, 6, 2, 1); -impl_ppi_channel!(PPI_CH7, 7, 2, 1); -impl_ppi_channel!(PPI_CH8, 8, 2, 1); -impl_ppi_channel!(PPI_CH9, 9, 2, 1); -impl_ppi_channel!(PPI_CH10, 10, 2, 1); -impl_ppi_channel!(PPI_CH11, 11, 2, 1); -impl_ppi_channel!(PPI_CH12, 12, 2, 1); -impl_ppi_channel!(PPI_CH13, 13, 2, 1); -impl_ppi_channel!(PPI_CH14, 14, 2, 1); -impl_ppi_channel!(PPI_CH15, 15, 2, 1); -impl_ppi_channel!(PPI_CH16, 16, 2, 1); -impl_ppi_channel!(PPI_CH17, 17, 2, 1); -impl_ppi_channel!(PPI_CH18, 18, 2, 1); -impl_ppi_channel!(PPI_CH19, 19, 2, 1); -impl_ppi_channel!(PPI_CH20, 20, 1, 0); -impl_ppi_channel!(PPI_CH21, 21, 1, 0); -impl_ppi_channel!(PPI_CH22, 22, 1, 0); -impl_ppi_channel!(PPI_CH23, 23, 1, 0); -impl_ppi_channel!(PPI_CH24, 24, 1, 0); -impl_ppi_channel!(PPI_CH25, 25, 1, 0); -impl_ppi_channel!(PPI_CH26, 26, 1, 0); -impl_ppi_channel!(PPI_CH27, 27, 1, 0); -impl_ppi_channel!(PPI_CH28, 28, 1, 0); -impl_ppi_channel!(PPI_CH29, 29, 1, 0); -impl_ppi_channel!(PPI_CH30, 30, 1, 0); -impl_ppi_channel!(PPI_CH31, 31, 1, 0); +impl_ppi_channel!(PPI_CH0, 0, true, 1, 2); +impl_ppi_channel!(PPI_CH1, 1, true, 1, 2); +impl_ppi_channel!(PPI_CH2, 2, true, 1, 2); +impl_ppi_channel!(PPI_CH3, 3, true, 1, 2); +impl_ppi_channel!(PPI_CH4, 4, true, 1, 2); +impl_ppi_channel!(PPI_CH5, 5, true, 1, 2); +impl_ppi_channel!(PPI_CH6, 6, true, 1, 2); +impl_ppi_channel!(PPI_CH7, 7, true, 1, 2); +impl_ppi_channel!(PPI_CH8, 8, true, 1, 2); +impl_ppi_channel!(PPI_CH9, 9, true, 1, 2); +impl_ppi_channel!(PPI_CH10, 10, true, 1, 2); +impl_ppi_channel!(PPI_CH11, 11, true, 1, 2); +impl_ppi_channel!(PPI_CH12, 12, true, 1, 2); +impl_ppi_channel!(PPI_CH13, 13, true, 1, 2); +impl_ppi_channel!(PPI_CH14, 14, true, 1, 2); +impl_ppi_channel!(PPI_CH15, 15, true, 1, 2); +impl_ppi_channel!(PPI_CH16, 16, true, 1, 2); +impl_ppi_channel!(PPI_CH17, 17, true, 1, 2); +impl_ppi_channel!(PPI_CH18, 18, true, 1, 2); +impl_ppi_channel!(PPI_CH19, 19, true, 1, 2); +impl_ppi_channel!(PPI_CH20, 20, false, 0, 1); +impl_ppi_channel!(PPI_CH21, 21, false, 0, 1); +impl_ppi_channel!(PPI_CH22, 22, false, 0, 1); +impl_ppi_channel!(PPI_CH23, 23, false, 0, 1); +impl_ppi_channel!(PPI_CH24, 24, false, 0, 1); +impl_ppi_channel!(PPI_CH25, 25, false, 0, 1); +impl_ppi_channel!(PPI_CH26, 26, false, 0, 1); +impl_ppi_channel!(PPI_CH27, 27, false, 0, 1); +impl_ppi_channel!(PPI_CH28, 28, false, 0, 1); +impl_ppi_channel!(PPI_CH29, 29, false, 0, 1); +impl_ppi_channel!(PPI_CH30, 30, false, 0, 1); +impl_ppi_channel!(PPI_CH31, 31, false, 0, 1); impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_03, ANALOGINPUT1); diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs index 02d2c6103..d52f2f98a 100644 --- a/embassy-nrf/src/chips/nrf52820.rs +++ b/embassy-nrf/src/chips/nrf52820.rs @@ -168,38 +168,38 @@ impl_pin!(P0_29, 0, 29); impl_pin!(P0_30, 0, 30); impl_pin!(P0_31, 0, 31); -impl_ppi_channel!(PPI_CH0, 0, 2, 1); -impl_ppi_channel!(PPI_CH1, 1, 2, 1); -impl_ppi_channel!(PPI_CH2, 2, 2, 1); -impl_ppi_channel!(PPI_CH3, 3, 2, 1); -impl_ppi_channel!(PPI_CH4, 4, 2, 1); -impl_ppi_channel!(PPI_CH5, 5, 2, 1); -impl_ppi_channel!(PPI_CH6, 6, 2, 1); -impl_ppi_channel!(PPI_CH7, 7, 2, 1); -impl_ppi_channel!(PPI_CH8, 8, 2, 1); -impl_ppi_channel!(PPI_CH9, 9, 2, 1); -impl_ppi_channel!(PPI_CH10, 10, 2, 1); -impl_ppi_channel!(PPI_CH11, 11, 2, 1); -impl_ppi_channel!(PPI_CH12, 12, 2, 1); -impl_ppi_channel!(PPI_CH13, 13, 2, 1); -impl_ppi_channel!(PPI_CH14, 14, 2, 1); -impl_ppi_channel!(PPI_CH15, 15, 2, 1); -impl_ppi_channel!(PPI_CH16, 16, 2, 1); -impl_ppi_channel!(PPI_CH17, 17, 2, 1); -impl_ppi_channel!(PPI_CH18, 18, 2, 1); -impl_ppi_channel!(PPI_CH19, 19, 2, 1); -impl_ppi_channel!(PPI_CH20, 20, 1, 0); -impl_ppi_channel!(PPI_CH21, 21, 1, 0); -impl_ppi_channel!(PPI_CH22, 22, 1, 0); -impl_ppi_channel!(PPI_CH23, 23, 1, 0); -impl_ppi_channel!(PPI_CH24, 24, 1, 0); -impl_ppi_channel!(PPI_CH25, 25, 1, 0); -impl_ppi_channel!(PPI_CH26, 26, 1, 0); -impl_ppi_channel!(PPI_CH27, 27, 1, 0); -impl_ppi_channel!(PPI_CH28, 28, 1, 0); -impl_ppi_channel!(PPI_CH29, 29, 1, 0); -impl_ppi_channel!(PPI_CH30, 30, 1, 0); -impl_ppi_channel!(PPI_CH31, 31, 1, 0); +impl_ppi_channel!(PPI_CH0, 0, true, 1, 2); +impl_ppi_channel!(PPI_CH1, 1, true, 1, 2); +impl_ppi_channel!(PPI_CH2, 2, true, 1, 2); +impl_ppi_channel!(PPI_CH3, 3, true, 1, 2); +impl_ppi_channel!(PPI_CH4, 4, true, 1, 2); +impl_ppi_channel!(PPI_CH5, 5, true, 1, 2); +impl_ppi_channel!(PPI_CH6, 6, true, 1, 2); +impl_ppi_channel!(PPI_CH7, 7, true, 1, 2); +impl_ppi_channel!(PPI_CH8, 8, true, 1, 2); +impl_ppi_channel!(PPI_CH9, 9, true, 1, 2); +impl_ppi_channel!(PPI_CH10, 10, true, 1, 2); +impl_ppi_channel!(PPI_CH11, 11, true, 1, 2); +impl_ppi_channel!(PPI_CH12, 12, true, 1, 2); +impl_ppi_channel!(PPI_CH13, 13, true, 1, 2); +impl_ppi_channel!(PPI_CH14, 14, true, 1, 2); +impl_ppi_channel!(PPI_CH15, 15, true, 1, 2); +impl_ppi_channel!(PPI_CH16, 16, true, 1, 2); +impl_ppi_channel!(PPI_CH17, 17, true, 1, 2); +impl_ppi_channel!(PPI_CH18, 18, true, 1, 2); +impl_ppi_channel!(PPI_CH19, 19, true, 1, 2); +impl_ppi_channel!(PPI_CH20, 20, false, 0, 1); +impl_ppi_channel!(PPI_CH21, 21, false, 0, 1); +impl_ppi_channel!(PPI_CH22, 22, false, 0, 1); +impl_ppi_channel!(PPI_CH23, 23, false, 0, 1); +impl_ppi_channel!(PPI_CH24, 24, false, 0, 1); +impl_ppi_channel!(PPI_CH25, 25, false, 0, 1); +impl_ppi_channel!(PPI_CH26, 26, false, 0, 1); +impl_ppi_channel!(PPI_CH27, 27, false, 0, 1); +impl_ppi_channel!(PPI_CH28, 28, false, 0, 1); +impl_ppi_channel!(PPI_CH29, 29, false, 0, 1); +impl_ppi_channel!(PPI_CH30, 30, false, 0, 1); +impl_ppi_channel!(PPI_CH31, 31, false, 0, 1); pub mod irqs { use crate::pac::Interrupt as InterruptEnum; diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index 611dbbd50..d97a65350 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -190,38 +190,38 @@ impl_pin!(P0_29, 0, 29); impl_pin!(P0_30, 0, 30); impl_pin!(P0_31, 0, 31); -impl_ppi_channel!(PPI_CH0, 0, 2, 1); -impl_ppi_channel!(PPI_CH1, 1, 2, 1); -impl_ppi_channel!(PPI_CH2, 2, 2, 1); -impl_ppi_channel!(PPI_CH3, 3, 2, 1); -impl_ppi_channel!(PPI_CH4, 4, 2, 1); -impl_ppi_channel!(PPI_CH5, 5, 2, 1); -impl_ppi_channel!(PPI_CH6, 6, 2, 1); -impl_ppi_channel!(PPI_CH7, 7, 2, 1); -impl_ppi_channel!(PPI_CH8, 8, 2, 1); -impl_ppi_channel!(PPI_CH9, 9, 2, 1); -impl_ppi_channel!(PPI_CH10, 10, 2, 1); -impl_ppi_channel!(PPI_CH11, 11, 2, 1); -impl_ppi_channel!(PPI_CH12, 12, 2, 1); -impl_ppi_channel!(PPI_CH13, 13, 2, 1); -impl_ppi_channel!(PPI_CH14, 14, 2, 1); -impl_ppi_channel!(PPI_CH15, 15, 2, 1); -impl_ppi_channel!(PPI_CH16, 16, 2, 1); -impl_ppi_channel!(PPI_CH17, 17, 2, 1); -impl_ppi_channel!(PPI_CH18, 18, 2, 1); -impl_ppi_channel!(PPI_CH19, 19, 2, 1); -impl_ppi_channel!(PPI_CH20, 20, 1, 0); -impl_ppi_channel!(PPI_CH21, 21, 1, 0); -impl_ppi_channel!(PPI_CH22, 22, 1, 0); -impl_ppi_channel!(PPI_CH23, 23, 1, 0); -impl_ppi_channel!(PPI_CH24, 24, 1, 0); -impl_ppi_channel!(PPI_CH25, 25, 1, 0); -impl_ppi_channel!(PPI_CH26, 26, 1, 0); -impl_ppi_channel!(PPI_CH27, 27, 1, 0); -impl_ppi_channel!(PPI_CH28, 28, 1, 0); -impl_ppi_channel!(PPI_CH29, 29, 1, 0); -impl_ppi_channel!(PPI_CH30, 30, 1, 0); -impl_ppi_channel!(PPI_CH31, 31, 1, 0); +impl_ppi_channel!(PPI_CH0, 0, true, 1, 2); +impl_ppi_channel!(PPI_CH1, 1, true, 1, 2); +impl_ppi_channel!(PPI_CH2, 2, true, 1, 2); +impl_ppi_channel!(PPI_CH3, 3, true, 1, 2); +impl_ppi_channel!(PPI_CH4, 4, true, 1, 2); +impl_ppi_channel!(PPI_CH5, 5, true, 1, 2); +impl_ppi_channel!(PPI_CH6, 6, true, 1, 2); +impl_ppi_channel!(PPI_CH7, 7, true, 1, 2); +impl_ppi_channel!(PPI_CH8, 8, true, 1, 2); +impl_ppi_channel!(PPI_CH9, 9, true, 1, 2); +impl_ppi_channel!(PPI_CH10, 10, true, 1, 2); +impl_ppi_channel!(PPI_CH11, 11, true, 1, 2); +impl_ppi_channel!(PPI_CH12, 12, true, 1, 2); +impl_ppi_channel!(PPI_CH13, 13, true, 1, 2); +impl_ppi_channel!(PPI_CH14, 14, true, 1, 2); +impl_ppi_channel!(PPI_CH15, 15, true, 1, 2); +impl_ppi_channel!(PPI_CH16, 16, true, 1, 2); +impl_ppi_channel!(PPI_CH17, 17, true, 1, 2); +impl_ppi_channel!(PPI_CH18, 18, true, 1, 2); +impl_ppi_channel!(PPI_CH19, 19, true, 1, 2); +impl_ppi_channel!(PPI_CH20, 20, false, 0, 1); +impl_ppi_channel!(PPI_CH21, 21, false, 0, 1); +impl_ppi_channel!(PPI_CH22, 22, false, 0, 1); +impl_ppi_channel!(PPI_CH23, 23, false, 0, 1); +impl_ppi_channel!(PPI_CH24, 24, false, 0, 1); +impl_ppi_channel!(PPI_CH25, 25, false, 0, 1); +impl_ppi_channel!(PPI_CH26, 26, false, 0, 1); +impl_ppi_channel!(PPI_CH27, 27, false, 0, 1); +impl_ppi_channel!(PPI_CH28, 28, false, 0, 1); +impl_ppi_channel!(PPI_CH29, 29, false, 0, 1); +impl_ppi_channel!(PPI_CH30, 30, false, 0, 1); +impl_ppi_channel!(PPI_CH31, 31, false, 0, 1); impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_03, ANALOGINPUT1); diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index 6f70f2a47..9bf370c4b 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -226,38 +226,38 @@ impl_pin!(P1_13, 1, 13); impl_pin!(P1_14, 1, 14); impl_pin!(P1_15, 1, 15); -impl_ppi_channel!(PPI_CH0, 0, 2, 1); -impl_ppi_channel!(PPI_CH1, 1, 2, 1); -impl_ppi_channel!(PPI_CH2, 2, 2, 1); -impl_ppi_channel!(PPI_CH3, 3, 2, 1); -impl_ppi_channel!(PPI_CH4, 4, 2, 1); -impl_ppi_channel!(PPI_CH5, 5, 2, 1); -impl_ppi_channel!(PPI_CH6, 6, 2, 1); -impl_ppi_channel!(PPI_CH7, 7, 2, 1); -impl_ppi_channel!(PPI_CH8, 8, 2, 1); -impl_ppi_channel!(PPI_CH9, 9, 2, 1); -impl_ppi_channel!(PPI_CH10, 10, 2, 1); -impl_ppi_channel!(PPI_CH11, 11, 2, 1); -impl_ppi_channel!(PPI_CH12, 12, 2, 1); -impl_ppi_channel!(PPI_CH13, 13, 2, 1); -impl_ppi_channel!(PPI_CH14, 14, 2, 1); -impl_ppi_channel!(PPI_CH15, 15, 2, 1); -impl_ppi_channel!(PPI_CH16, 16, 2, 1); -impl_ppi_channel!(PPI_CH17, 17, 2, 1); -impl_ppi_channel!(PPI_CH18, 18, 2, 1); -impl_ppi_channel!(PPI_CH19, 19, 2, 1); -impl_ppi_channel!(PPI_CH20, 20, 1, 0); -impl_ppi_channel!(PPI_CH21, 21, 1, 0); -impl_ppi_channel!(PPI_CH22, 22, 1, 0); -impl_ppi_channel!(PPI_CH23, 23, 1, 0); -impl_ppi_channel!(PPI_CH24, 24, 1, 0); -impl_ppi_channel!(PPI_CH25, 25, 1, 0); -impl_ppi_channel!(PPI_CH26, 26, 1, 0); -impl_ppi_channel!(PPI_CH27, 27, 1, 0); -impl_ppi_channel!(PPI_CH28, 28, 1, 0); -impl_ppi_channel!(PPI_CH29, 29, 1, 0); -impl_ppi_channel!(PPI_CH30, 30, 1, 0); -impl_ppi_channel!(PPI_CH31, 31, 1, 0); +impl_ppi_channel!(PPI_CH0, 0, true, 1, 2); +impl_ppi_channel!(PPI_CH1, 1, true, 1, 2); +impl_ppi_channel!(PPI_CH2, 2, true, 1, 2); +impl_ppi_channel!(PPI_CH3, 3, true, 1, 2); +impl_ppi_channel!(PPI_CH4, 4, true, 1, 2); +impl_ppi_channel!(PPI_CH5, 5, true, 1, 2); +impl_ppi_channel!(PPI_CH6, 6, true, 1, 2); +impl_ppi_channel!(PPI_CH7, 7, true, 1, 2); +impl_ppi_channel!(PPI_CH8, 8, true, 1, 2); +impl_ppi_channel!(PPI_CH9, 9, true, 1, 2); +impl_ppi_channel!(PPI_CH10, 10, true, 1, 2); +impl_ppi_channel!(PPI_CH11, 11, true, 1, 2); +impl_ppi_channel!(PPI_CH12, 12, true, 1, 2); +impl_ppi_channel!(PPI_CH13, 13, true, 1, 2); +impl_ppi_channel!(PPI_CH14, 14, true, 1, 2); +impl_ppi_channel!(PPI_CH15, 15, true, 1, 2); +impl_ppi_channel!(PPI_CH16, 16, true, 1, 2); +impl_ppi_channel!(PPI_CH17, 17, true, 1, 2); +impl_ppi_channel!(PPI_CH18, 18, true, 1, 2); +impl_ppi_channel!(PPI_CH19, 19, true, 1, 2); +impl_ppi_channel!(PPI_CH20, 20, false, 0, 1); +impl_ppi_channel!(PPI_CH21, 21, false, 0, 1); +impl_ppi_channel!(PPI_CH22, 22, false, 0, 1); +impl_ppi_channel!(PPI_CH23, 23, false, 0, 1); +impl_ppi_channel!(PPI_CH24, 24, false, 0, 1); +impl_ppi_channel!(PPI_CH25, 25, false, 0, 1); +impl_ppi_channel!(PPI_CH26, 26, false, 0, 1); +impl_ppi_channel!(PPI_CH27, 27, false, 0, 1); +impl_ppi_channel!(PPI_CH28, 28, false, 0, 1); +impl_ppi_channel!(PPI_CH29, 29, false, 0, 1); +impl_ppi_channel!(PPI_CH30, 30, false, 0, 1); +impl_ppi_channel!(PPI_CH31, 31, false, 0, 1); impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_03, ANALOGINPUT1); diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index 1b9824151..266328d58 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -231,38 +231,38 @@ impl_pin!(P1_13, 1, 13); impl_pin!(P1_14, 1, 14); impl_pin!(P1_15, 1, 15); -impl_ppi_channel!(PPI_CH0, 0, 2, 1); -impl_ppi_channel!(PPI_CH1, 1, 2, 1); -impl_ppi_channel!(PPI_CH2, 2, 2, 1); -impl_ppi_channel!(PPI_CH3, 3, 2, 1); -impl_ppi_channel!(PPI_CH4, 4, 2, 1); -impl_ppi_channel!(PPI_CH5, 5, 2, 1); -impl_ppi_channel!(PPI_CH6, 6, 2, 1); -impl_ppi_channel!(PPI_CH7, 7, 2, 1); -impl_ppi_channel!(PPI_CH8, 8, 2, 1); -impl_ppi_channel!(PPI_CH9, 9, 2, 1); -impl_ppi_channel!(PPI_CH10, 10, 2, 1); -impl_ppi_channel!(PPI_CH11, 11, 2, 1); -impl_ppi_channel!(PPI_CH12, 12, 2, 1); -impl_ppi_channel!(PPI_CH13, 13, 2, 1); -impl_ppi_channel!(PPI_CH14, 14, 2, 1); -impl_ppi_channel!(PPI_CH15, 15, 2, 1); -impl_ppi_channel!(PPI_CH16, 16, 2, 1); -impl_ppi_channel!(PPI_CH17, 17, 2, 1); -impl_ppi_channel!(PPI_CH18, 18, 2, 1); -impl_ppi_channel!(PPI_CH19, 19, 2, 1); -impl_ppi_channel!(PPI_CH20, 20, 1, 0); -impl_ppi_channel!(PPI_CH21, 21, 1, 0); -impl_ppi_channel!(PPI_CH22, 22, 1, 0); -impl_ppi_channel!(PPI_CH23, 23, 1, 0); -impl_ppi_channel!(PPI_CH24, 24, 1, 0); -impl_ppi_channel!(PPI_CH25, 25, 1, 0); -impl_ppi_channel!(PPI_CH26, 26, 1, 0); -impl_ppi_channel!(PPI_CH27, 27, 1, 0); -impl_ppi_channel!(PPI_CH28, 28, 1, 0); -impl_ppi_channel!(PPI_CH29, 29, 1, 0); -impl_ppi_channel!(PPI_CH30, 30, 1, 0); -impl_ppi_channel!(PPI_CH31, 31, 1, 0); +impl_ppi_channel!(PPI_CH0, 0, true, 1, 2); +impl_ppi_channel!(PPI_CH1, 1, true, 1, 2); +impl_ppi_channel!(PPI_CH2, 2, true, 1, 2); +impl_ppi_channel!(PPI_CH3, 3, true, 1, 2); +impl_ppi_channel!(PPI_CH4, 4, true, 1, 2); +impl_ppi_channel!(PPI_CH5, 5, true, 1, 2); +impl_ppi_channel!(PPI_CH6, 6, true, 1, 2); +impl_ppi_channel!(PPI_CH7, 7, true, 1, 2); +impl_ppi_channel!(PPI_CH8, 8, true, 1, 2); +impl_ppi_channel!(PPI_CH9, 9, true, 1, 2); +impl_ppi_channel!(PPI_CH10, 10, true, 1, 2); +impl_ppi_channel!(PPI_CH11, 11, true, 1, 2); +impl_ppi_channel!(PPI_CH12, 12, true, 1, 2); +impl_ppi_channel!(PPI_CH13, 13, true, 1, 2); +impl_ppi_channel!(PPI_CH14, 14, true, 1, 2); +impl_ppi_channel!(PPI_CH15, 15, true, 1, 2); +impl_ppi_channel!(PPI_CH16, 16, true, 1, 2); +impl_ppi_channel!(PPI_CH17, 17, true, 1, 2); +impl_ppi_channel!(PPI_CH18, 18, true, 1, 2); +impl_ppi_channel!(PPI_CH19, 19, true, 1, 2); +impl_ppi_channel!(PPI_CH20, 20, false, 0, 1); +impl_ppi_channel!(PPI_CH21, 21, false, 0, 1); +impl_ppi_channel!(PPI_CH22, 22, false, 0, 1); +impl_ppi_channel!(PPI_CH23, 23, false, 0, 1); +impl_ppi_channel!(PPI_CH24, 24, false, 0, 1); +impl_ppi_channel!(PPI_CH25, 25, false, 0, 1); +impl_ppi_channel!(PPI_CH26, 26, false, 0, 1); +impl_ppi_channel!(PPI_CH27, 27, false, 0, 1); +impl_ppi_channel!(PPI_CH28, 28, false, 0, 1); +impl_ppi_channel!(PPI_CH29, 29, false, 0, 1); +impl_ppi_channel!(PPI_CH30, 30, false, 0, 1); +impl_ppi_channel!(PPI_CH31, 31, false, 0, 1); impl_saadc_input!(P0_02, ANALOGINPUT0); impl_saadc_input!(P0_03, ANALOGINPUT1); diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs index 42053d081..7357e9e22 100644 --- a/embassy-nrf/src/chips/nrf9160.rs +++ b/embassy-nrf/src/chips/nrf9160.rs @@ -184,22 +184,22 @@ impl_pin!(P0_29, 0, 29); impl_pin!(P0_30, 0, 30); impl_pin!(P0_31, 0, 31); -impl_ppi_channel!(PPI_CH0, 0); -impl_ppi_channel!(PPI_CH1, 1); -impl_ppi_channel!(PPI_CH2, 2); -impl_ppi_channel!(PPI_CH3, 3); -impl_ppi_channel!(PPI_CH4, 4); -impl_ppi_channel!(PPI_CH5, 5); -impl_ppi_channel!(PPI_CH6, 6); -impl_ppi_channel!(PPI_CH7, 7); -impl_ppi_channel!(PPI_CH8, 8); -impl_ppi_channel!(PPI_CH9, 9); -impl_ppi_channel!(PPI_CH10, 10); -impl_ppi_channel!(PPI_CH11, 11); -impl_ppi_channel!(PPI_CH12, 12); -impl_ppi_channel!(PPI_CH13, 13); -impl_ppi_channel!(PPI_CH14, 14); -impl_ppi_channel!(PPI_CH15, 15); +impl_ppi_channel!(PPI_CH0, 0, true, many, many); +impl_ppi_channel!(PPI_CH1, 1, true, many, many); +impl_ppi_channel!(PPI_CH2, 2, true, many, many); +impl_ppi_channel!(PPI_CH3, 3, true, many, many); +impl_ppi_channel!(PPI_CH4, 4, true, many, many); +impl_ppi_channel!(PPI_CH5, 5, true, many, many); +impl_ppi_channel!(PPI_CH6, 6, true, many, many); +impl_ppi_channel!(PPI_CH7, 7, true, many, many); +impl_ppi_channel!(PPI_CH8, 8, true, many, many); +impl_ppi_channel!(PPI_CH9, 9, true, many, many); +impl_ppi_channel!(PPI_CH10, 10, true, many, many); +impl_ppi_channel!(PPI_CH11, 11, true, many, many); +impl_ppi_channel!(PPI_CH12, 12, true, many, many); +impl_ppi_channel!(PPI_CH13, 13, true, many, many); +impl_ppi_channel!(PPI_CH14, 14, true, many, many); +impl_ppi_channel!(PPI_CH15, 15, true, many, many); impl_saadc_input!(P0_13, ANALOGINPUT0); impl_saadc_input!(P0_14, ANALOGINPUT1); diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 943ff530b..6703bfc60 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -11,8 +11,8 @@ use futures::future::poll_fn; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Input, Output, Pin as GpioPin}; +use crate::interconnect::{Event, Task}; use crate::pac; -use crate::ppi::{Event, Task}; use crate::{interrupt, peripherals}; pub const CHANNEL_COUNT: usize = 8; @@ -190,13 +190,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { /// Returns the IN event, for use with PPI. pub fn event_in(&self) -> Event { let g = unsafe { &*pac::GPIOTE::ptr() }; - - #[cfg(feature = "_ppi")] - let reg = &g.events_in[self.ch.number()]; - #[cfg(feature = "_dppi")] - let reg = &g.publish_in[self.ch.number()]; - - Event::from_reg(reg) + Event::from_reg(&g.events_in[self.ch.number()]) } } @@ -277,33 +271,21 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> { /// Returns the OUT task, for use with PPI. pub fn task_out(&self) -> Task { let g = unsafe { &*pac::GPIOTE::ptr() }; - #[cfg(feature = "_ppi")] - let reg = &g.tasks_out[self.ch.number()]; - #[cfg(feature = "_dppi")] - let reg = &g.subscribe_out[self.ch.number()]; - Task::from_reg(reg) + Task::from_reg(&g.tasks_out[self.ch.number()]) } /// Returns the CLR task, for use with PPI. #[cfg(not(feature = "nrf51"))] pub fn task_clr(&self) -> Task { let g = unsafe { &*pac::GPIOTE::ptr() }; - #[cfg(feature = "_ppi")] - let reg = &g.tasks_clr[self.ch.number()]; - #[cfg(feature = "_dppi")] - let reg = &g.subscribe_clr[self.ch.number()]; - Task::from_reg(reg) + Task::from_reg(&g.tasks_clr[self.ch.number()]) } /// Returns the SET task, for use with PPI. #[cfg(not(feature = "nrf51"))] pub fn task_set(&self) -> Task { let g = unsafe { &*pac::GPIOTE::ptr() }; - #[cfg(feature = "_ppi")] - let reg = &g.tasks_set[self.ch.number()]; - #[cfg(feature = "_dppi")] - let reg = &g.subscribe_set[self.ch.number()]; - Task::from_reg(reg) + Task::from_reg(&g.tasks_set[self.ch.number()]) } } diff --git a/embassy-nrf/src/interconnect/dppi.rs b/embassy-nrf/src/interconnect/dppi.rs new file mode 100644 index 000000000..60f19fca0 --- /dev/null +++ b/embassy-nrf/src/interconnect/dppi.rs @@ -0,0 +1,47 @@ +use super::{Channel, Event, Ppi, Task}; + +const DPPI_ENABLE_BIT: u32 = 0x8000_0000; +const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF; +const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::(); + +impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> + Ppi<'d, C, EVENT_COUNT, TASK_COUNT> +{ + pub(super) fn enable_task(task: &Task, channel: &C, _index: usize) { + unsafe { + task.0 + .as_ptr() + .add(REGISTER_DPPI_CONFIG_OFFSET) + .write_volatile(DPPI_ENABLE_BIT | (channel.number() as u32 & DPPI_CHANNEL_MASK)); + } + } + + pub(super) fn disable_task(task: &Task, _channel: &C, _index: usize) { + unsafe { + task.0 + .as_ptr() + .add(REGISTER_DPPI_CONFIG_OFFSET) + .write_volatile(0); + } + } + + pub(super) fn enable_event(event: &Event, channel: &C, _index: usize) { + unsafe { + event + .0 + .as_ptr() + .add(REGISTER_DPPI_CONFIG_OFFSET) + .write_volatile(DPPI_ENABLE_BIT | (channel.number() as u32 & DPPI_CHANNEL_MASK)); + } + } + + pub(super) fn disable_event(event: &Event, _channel: &C, _index: usize) { + unsafe { + event + .0 + .as_ptr() + .add(REGISTER_DPPI_CONFIG_OFFSET) + .write_volatile(0); + } + } +} diff --git a/embassy-nrf/src/interconnect/mod.rs b/embassy-nrf/src/interconnect/mod.rs new file mode 100644 index 000000000..23cc45270 --- /dev/null +++ b/embassy-nrf/src/interconnect/mod.rs @@ -0,0 +1,318 @@ +#![macro_use] + +//! HAL interface for the PPI and DPPI peripheral. +//! +//! The (Distributed) Programmable Peripheral Interconnect interface allows for an autonomous interoperability +//! between peripherals through their events and tasks. There are fixed PPI channels and fully +//! configurable ones. Fixed channels can only connect specific events to specific tasks. For fully +//! configurable channels, it is possible to choose, via software, the event and the task that it +//! will triggered by the event. +//! +//! On nRF52 devices, there is also a fork task endpoint, where the user can configure one more task +//! to be triggered by the same event, even fixed PPI channels have a configurable fork task. +//! +//! The DPPI for nRF53 and nRF91 devices works in a different way. Every channel can support infinitely +//! many tasks and events, but any single task or event can only be coupled with one channel. +//! + +use crate::{pac, peripherals}; +use core::marker::PhantomData; +use core::ptr::NonNull; +use embassy::util::Unborrow; +use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; + +#[cfg(feature = "_dppi")] +mod dppi; +#[cfg(feature = "_ppi")] +mod ppi; + +pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> { + ch: C, + events: [Event; EVENT_COUNT], + tasks: [Task; TASK_COUNT], + phantom: PhantomData<&'d mut C>, +} + +impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> + Ppi<'d, C, EVENT_COUNT, TASK_COUNT> +{ + pub fn degrade(self) -> Ppi<'d, AnyChannel, EVENT_COUNT, TASK_COUNT> { + Ppi { + ch: AnyChannel { + number: self.ch.number() as u8, + #[cfg(feature = "_ppi")] + has_configurable_task: self.ch.is_task_configurable(), + }, + events: self.events, + tasks: self.tasks, + phantom: PhantomData, + } + } + + /// Enables the channel. + pub fn enable(&mut self) { + let r = unsafe { &*pac::PPI::ptr() }; + r.chenset + .write(|w| unsafe { w.bits(1 << self.ch.number()) }); + } + + /// Disables the channel. + pub fn disable(&mut self) { + let r = unsafe { &*pac::PPI::ptr() }; + r.chenclr + .write(|w| unsafe { w.bits(1 << self.ch.number()) }); + } + + /// Enables all tasks and events + fn enable_all(&self) { + for (index, task) in self.tasks.iter().enumerate() { + Self::enable_task(task, &self.ch, index); + } + for (index, event) in self.events.iter().enumerate() { + Self::enable_event(event, &self.ch, index); + } + } + + /// Disable all tasks and events + fn disable_all(&self) { + for (index, task) in self.tasks.iter().enumerate() { + Self::disable_task(task, &self.ch, index); + } + for (index, event) in self.events.iter().enumerate() { + Self::disable_event(event, &self.ch, index); + } + } +} + +impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Drop + for Ppi<'d, C, EVENT_COUNT, TASK_COUNT> +{ + fn drop(&mut self) { + self.disable(); + self.disable_all(); + } +} + +impl<'d, C: StaticToOneChannel> Ppi<'d, C, 0, 1> { + pub fn new_static_to_one(ch: impl Unborrow + 'd, task: Task) -> Self { + unborrow!(ch); + + let s = Self { + ch, + events: [], + tasks: [task], + phantom: PhantomData, + }; + + s.enable_all(); + s + } +} + +impl<'d, C: OneToOneChannel> Ppi<'d, C, 1, 1> { + pub fn new_one_to_one(ch: impl Unborrow + 'd, event: Event, task: Task) -> Self { + unborrow!(ch); + + let s = Self { + ch, + events: [event], + tasks: [task], + phantom: PhantomData, + }; + + s.enable_all(); + s + } +} + +impl<'d, C: OneToTwoChannel> Ppi<'d, C, 1, 2> { + pub fn new_one_to_two( + ch: impl Unborrow + 'd, + event: Event, + task1: Task, + task2: Task, + ) -> Self { + unborrow!(ch); + + let s = Self { + ch, + events: [event], + tasks: [task1, task2], + phantom: PhantomData, + }; + + s.enable_all(); + s + } +} + +impl<'d, C: ManyToManyChannel, const EVENT_COUNT: usize, const TASK_COUNT: usize> + Ppi<'d, C, EVENT_COUNT, TASK_COUNT> +{ + pub fn new_many_to_many( + ch: impl Unborrow + 'd, + events: [Event; EVENT_COUNT], + tasks: [Task; TASK_COUNT], + ) -> Self { + unborrow!(ch); + + let s = Self { + ch, + events, + tasks, + phantom: PhantomData, + }; + + s.enable_all(); + s + } +} + +/// Represents a task that a peripheral can do. +/// When a task is subscribed to a PPI channel it will run when the channel is triggered by +/// a published event. +/// +/// The pointer is to a task register +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct Task(pub NonNull); +impl Task { + pub(crate) fn from_reg(reg: &T) -> Self { + Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) + } +} + +/// # Safety +/// +/// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. +unsafe impl Send for Task {} + +/// Represents an event that a peripheral can publish. +/// An event can be set to publish on a PPI channel when the event happens. +/// +/// The pointer is to an event register +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct Event(pub NonNull); +impl Event { + pub(crate) fn from_reg(reg: &T) -> Self { + Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) + } +} + +/// # Safety +/// +/// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. +unsafe impl Send for Event {} + +// ====================== +// traits + +pub(crate) mod sealed { + pub trait Channel {} + pub trait Group {} +} + +pub trait Channel: sealed::Channel + Unborrow + Sized { + /// Returns the number of the channel + fn number(&self) -> usize; + #[cfg(feature = "_ppi")] + fn is_task_configurable(&self) -> bool; +} + +pub trait StaticToOneChannel: Channel {} +pub trait OneToOneChannel: StaticToOneChannel {} +pub trait OneToTwoChannel: OneToOneChannel {} +pub trait ManyToManyChannel: OneToTwoChannel {} + +pub trait Group: sealed::Group + Sized { + fn number(&self) -> usize; +} + +// ====================== +// channels + +pub struct AnyChannel { + number: u8, + #[cfg(feature = "_ppi")] + has_configurable_task: bool, +} +unsafe_impl_unborrow!(AnyChannel); +impl sealed::Channel for AnyChannel {} +impl Channel for AnyChannel { + fn number(&self) -> usize { + self.number as usize + } + + #[cfg(feature = "_ppi")] + fn is_task_configurable(&self) -> bool { + self.has_configurable_task + } +} + +macro_rules! impl_ppi_channel { + ($type:ident, $number:expr, $has_configurable_task:expr) => { + impl crate::interconnect::sealed::Channel for peripherals::$type {} + impl crate::interconnect::Channel for peripherals::$type { + fn number(&self) -> usize { + $number + } + + #[cfg(feature = "_ppi")] + fn is_task_configurable(&self) -> bool { + $has_configurable_task + } + } + }; + ($type:ident, $number:expr, $has_configurable_task:expr, 0, 0) => { + impl_ppi_channel!($type, $number, $has_configurable_task); + }; + ($type:ident, $number:expr, $has_configurable_task:expr, 0, 1) => { + impl_ppi_channel!($type, $number, $has_configurable_task, 0, 0); + impl crate::interconnect::StaticToOneChannel for peripherals::$type {} + }; + ($type:ident, $number:expr, $has_configurable_task:expr, 1, 1) => { + impl_ppi_channel!($type, $number, $has_configurable_task, 0, 1); + impl crate::interconnect::OneToOneChannel for peripherals::$type {} + }; + ($type:ident, $number:expr, $has_configurable_task:expr, 1, 2) => { + impl_ppi_channel!($type, $number, $has_configurable_task, 1, 1); + impl crate::interconnect::OneToTwoChannel for peripherals::$type {} + }; + ($type:ident, $number:expr, $has_configurable_task:expr, many, many) => { + impl_ppi_channel!($type, $number, $has_configurable_task, 1, 2); + impl crate::interconnect::ManyToManyChannel for peripherals::$type {} + }; +} + +// ====================== +// groups + +pub struct AnyGroup { + number: u8, +} +unsafe_impl_unborrow!(AnyGroup); +impl sealed::Group for AnyGroup {} +impl Group for AnyGroup { + fn number(&self) -> usize { + self.number as usize + } +} + +macro_rules! impl_group { + ($type:ident, $number:expr) => { + impl sealed::Group for peripherals::$type {} + impl Group for peripherals::$type { + fn number(&self) -> usize { + $number + } + } + }; +} + +impl_group!(PPI_GROUP0, 0); +impl_group!(PPI_GROUP1, 1); +impl_group!(PPI_GROUP2, 2); +impl_group!(PPI_GROUP3, 3); +#[cfg(not(feature = "nrf51"))] +impl_group!(PPI_GROUP4, 4); +#[cfg(not(feature = "nrf51"))] +impl_group!(PPI_GROUP5, 5); diff --git a/embassy-nrf/src/interconnect/ppi.rs b/embassy-nrf/src/interconnect/ppi.rs new file mode 100644 index 000000000..91ff811fe --- /dev/null +++ b/embassy-nrf/src/interconnect/ppi.rs @@ -0,0 +1,65 @@ +use super::{Channel, Event, Ppi, Task}; +use crate::pac; + +impl<'d, C: Channel + 'd, const EVENT_COUNT: usize, const TASK_COUNT: usize> + Ppi<'d, C, EVENT_COUNT, TASK_COUNT> +{ + pub(super) fn enable_task(task: &Task, channel: &C, index: usize) { + match (index, channel.is_task_configurable()) { + (0, false) => Self::set_fork_task(Some(task), channel.number()), // Static channel with fork + (0, true) => Self::set_main_task(Some(task), channel.number()), // Configurable channel without fork + (1, true) => Self::set_fork_task(Some(task), channel.number()), // Configurable channel with fork + _ => unreachable!("{}, {}", index, channel.is_task_configurable()), // Not available with the PPI, so should not be constructable + } + } + + pub(super) fn disable_task(_task: &Task, channel: &C, index: usize) { + match (index, channel.is_task_configurable()) { + (0, false) => Self::set_fork_task(None, channel.number()), // Static channel with fork + (0, true) => Self::set_main_task(None, channel.number()), // Configurable channel without fork + (1, true) => Self::set_fork_task(None, channel.number()), // Configurable channel with fork + _ => unreachable!(), // Not available with the PPI, so should not be constructable + } + } + + pub(super) fn enable_event(event: &Event, channel: &C, _index: usize) { + Self::set_event(Some(event), channel.number()) + } + + pub(super) fn disable_event(_event: &Event, channel: &C, _index: usize) { + Self::set_event(None, channel.number()) + } + + fn set_main_task(task: Option<&Task>, channel: usize) { + let r = unsafe { &*pac::PPI::ptr() }; + if let Some(task) = task { + r.ch[channel] + .tep + .write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) + } else { + r.ch[channel].tep.write(|w| unsafe { w.bits(0) }) + } + } + + fn set_fork_task(task: Option<&Task>, channel: usize) { + let r = unsafe { &*pac::PPI::ptr() }; + if let Some(task) = task { + r.fork[channel] + .tep + .write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) + } else { + r.fork[channel].tep.write(|w| unsafe { w.bits(0) }) + } + } + + fn set_event(event: Option<&Event>, channel: usize) { + let r = unsafe { &*pac::PPI::ptr() }; + if let Some(event) = event { + r.ch[channel] + .eep + .write(|w| unsafe { w.bits(event.0.as_ptr() as u32) }) + } else { + r.ch[channel].eep.write(|w| unsafe { w.bits(0) }) + } + } +} diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index c21c4d398..39f3e4a4a 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -31,7 +31,7 @@ pub mod gpio; pub mod gpiote; #[cfg(not(feature = "nrf9160"))] pub mod nvmc; -pub mod ppi; +pub mod interconnect; #[cfg(not(any(feature = "nrf52805", feature = "nrf52820")))] pub mod pwm; #[cfg(feature = "nrf52840")] diff --git a/embassy-nrf/src/ppi.rs b/embassy-nrf/src/ppi.rs deleted file mode 100644 index 7aaf17ee5..000000000 --- a/embassy-nrf/src/ppi.rs +++ /dev/null @@ -1,513 +0,0 @@ -#![macro_use] - -//! HAL interface for the PPI peripheral. -//! -//! The Programmable Peripheral Interconnect interface allows for an autonomous interoperability -//! between peripherals through their events and tasks. There are fixed PPI channels and fully -//! configurable ones, fixed channels can only connect specific events to specific tasks. For fully -//! configurable channels, it is possible to choose, via software, the event and the task that it -//! will triggered by the event. -//! -//! On nRF52 devices, there is also a fork task endpoint, where the user can configure one more task -//! to be triggered by the same event, even fixed PPI channels have a configurable fork task. - -use crate::{pac, peripherals}; -use core::marker::PhantomData; -use core::ptr::NonNull; -use embassy::util::Unborrow; -use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; - -// ====================== -// driver - -/// Error type of the PPI driver -#[non_exhaustive] -#[derive(Clone, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum Error { - /// There is no capacity to enable this task or event (nRF51 & nRF52 only) - NoCapacityLeft, - /// This task or event is not in use by the current channel - NotInUseByChannel, - /// This task or event is already enabled on another channel (nRF53 & nRF91 only) - AlreadyInUse, -} - -pub struct Ppi<'d, C: Channel> { - ch: C, - phantom: PhantomData<&'d mut C>, -} - -impl<'d, C: Channel> Ppi<'d, C> { - pub fn new(ch: impl Unborrow + 'd) -> Self { - unborrow!(ch); - - Self { - ch, - phantom: PhantomData, - } - } - - /// Enables the channel. - pub fn enable(&mut self) { - let r = unsafe { &*pac::PPI::ptr() }; - r.chenset - .write(|w| unsafe { w.bits(1 << self.ch.number()) }); - } - - /// Disables the channel. - pub fn disable(&mut self) { - let r = unsafe { &*pac::PPI::ptr() }; - r.chenclr - .write(|w| unsafe { w.bits(1 << self.ch.number()) }); - } -} - -#[cfg(feature = "_ppi")] -impl<'d, C: Channel> Ppi<'d, C> { - /// Makes it so that the given task is subscribed to this channel - pub fn subscribe(&mut self, task: Task) -> Result<(), Error> { - if self.is_main_task_free() { - self.set_main_task(Some(task)); - Ok(()) - } else if self.is_fork_task_free() { - self.set_fork_task(Some(task)); - Ok(()) - } else { - Err(Error::NoCapacityLeft) - } - } - - /// Makes it so that the given task is not subscribed to this channel - pub fn unsubscribe(&mut self, task: Task) -> Result<(), Error> { - if self.get_main_task() == Some(task) { - // If there is a fork task, we move that to the main task for consistency - // If there is no fork task, then the main task is set to 0 - let fork_task = self.get_fork_task(); - self.set_main_task(fork_task); - - if self.has_fork_task() { - // The fork task was copied to the main task, so reset the fork task - self.set_fork_task(None); - } - Ok(()) - } else if self.get_fork_task() == Some(task) { - // Reset the fork task - self.set_fork_task(None); - Ok(()) - } else { - Err(Error::NotInUseByChannel) - } - } - - /// Makes it so that the given event is published on this channel - pub fn publish(&mut self, event: Event) -> Result<(), Error> { - if self.is_event_free() { - self.set_event(Some(event)); - Ok(()) - } else { - Err(Error::NoCapacityLeft) - } - } - - /// Makes it so that the given event is not published on this channel - pub fn unpublish(&mut self, event: Event) -> Result<(), Error> { - if self.get_event() == Some(event) { - self.set_event(None); - Ok(()) - } else { - Err(Error::NotInUseByChannel) - } - } - - fn set_main_task(&mut self, task: Option) { - let r = unsafe { &*pac::PPI::ptr() }; - if let Some(task) = task { - r.ch[self.ch.number()] - .tep - .write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) - } else { - r.ch[self.ch.number()].tep.write(|w| unsafe { w.bits(0) }) - } - } - - fn get_main_task(&mut self) -> Option { - let r = unsafe { &*pac::PPI::ptr() }; - - if !self.has_main_task() { - return None; - } - - let bits = r.ch[self.ch.number()].tep.read().tep().bits(); - - if bits == 0 { - None - } else { - unsafe { Some(Task(NonNull::new_unchecked(bits as *mut _))) } - } - } - - fn set_fork_task(&mut self, task: Option) { - let r = unsafe { &*pac::PPI::ptr() }; - if let Some(task) = task { - r.fork[self.ch.number()] - .tep - .write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) - } else { - r.fork[self.ch.number()].tep.write(|w| unsafe { w.bits(0) }) - } - } - - fn get_fork_task(&mut self) -> Option { - let r = unsafe { &*pac::PPI::ptr() }; - - if !self.has_fork_task() { - return None; - } - - let bits = r.fork[self.ch.number()].tep.read().tep().bits(); - - if bits == 0 { - None - } else { - unsafe { Some(Task(NonNull::new_unchecked(bits as *mut _))) } - } - } - - fn has_main_task(&self) -> bool { - match (self.ch.task_capacity(), self.ch.event_capacity()) { - (0, 0) => false, // Static task - (1, 0) => false, // Static task with fork - (1 | 2, 1) => true, // Configurable task with possibly a fork - _ => unreachable!(), // Every PPI config is covered - } - } - - fn has_fork_task(&self) -> bool { - match (self.ch.task_capacity(), self.ch.event_capacity()) { - (0, 0) => false, // Static task - (1, 0) => true, // Static task with fork - (1, 1) => false, // Configurable task without fork - (2, 1) => true, // Configurable task with fork - _ => unreachable!(), // Every PPI config is covered - } - } - - fn is_main_task_free(&mut self) -> bool { - self.get_main_task().is_none() - } - - fn is_fork_task_free(&mut self) -> bool { - self.get_fork_task().is_none() - } - - fn set_event(&mut self, event: Option) { - let r = unsafe { &*pac::PPI::ptr() }; - if let Some(event) = event { - r.ch[self.ch.number()] - .eep - .write(|w| unsafe { w.bits(event.0.as_ptr() as u32) }) - } else { - r.ch[self.ch.number()].eep.write(|w| unsafe { w.bits(0) }) - } - } - - fn get_event(&mut self) -> Option { - let r = unsafe { &*pac::PPI::ptr() }; - - if !self.has_event() { - return None; - } - - let bits = r.ch[self.ch.number()].eep.read().eep().bits(); - - if bits == 0 { - None - } else { - unsafe { Some(Event(NonNull::new_unchecked(bits as *mut _))) } - } - } - - fn has_event(&self) -> bool { - match (self.ch.task_capacity(), self.ch.event_capacity()) { - (_, 0) => false, // Static event - (_, 1) => true, // Configurable event - _ => unreachable!(), // Every PPI config is covered - } - } - - fn is_event_free(&mut self) -> bool { - self.get_event().is_none() - } -} - -#[cfg(feature = "_dppi")] -const DPPI_ENABLE_BIT: u32 = 0x8000_0000; -#[cfg(feature = "_dppi")] -const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF; - -#[cfg(feature = "_dppi")] -impl<'d, C: Channel> Ppi<'d, C> { - /// Makes it so that the given task is subscribed to this channel - pub fn subscribe(&mut self, task: Task) -> Result<(), Error> { - unsafe { - if Self::is_register_enabled(task.0) { - Err(Error::AlreadyInUse) - } else { - Self::set_register_active(task.0, self.ch.number() as u8); - Ok(()) - } - } - } - - /// Makes it so that the given task is not subscribed to this channel - pub fn unsubscribe(&mut self, task: Task) -> Result<(), Error> { - unsafe { - if Self::get_register_channel(task.0) != self.ch.number() as u8 { - Err(Error::NotInUseByChannel) - } else { - Self::set_register_inactive(task.0); - Ok(()) - } - } - } - - /// Makes it so that the given event is published on this channel - pub fn publish(&mut self, event: Event) -> Result<(), Error> { - unsafe { - if Self::is_register_enabled(event.0) { - Err(Error::AlreadyInUse) - } else { - Self::set_register_active(event.0, self.ch.number() as u8); - Ok(()) - } - } - } - - /// Makes it so that the given event is not published on this channel - pub fn unpublish(&mut self, event: Event) -> Result<(), Error> { - unsafe { - if Self::get_register_channel(event.0) != self.ch.number() as u8 { - Err(Error::NotInUseByChannel) - } else { - Self::set_register_inactive(event.0); - Ok(()) - } - } - } - - /// Checks if the DPPI_ENABLE_BIT is set in the register - /// - /// # Safety - /// - /// The register pointer must point at one of the many SUBSCRIBE_* or PUBLISH_* registers of the peripherals - unsafe fn is_register_enabled(register: NonNull) -> bool { - let bits = register.as_ptr().read_volatile(); - bits & DPPI_ENABLE_BIT > 0 - } - - /// Sets the register to the given channel and enables it - /// - /// # Safety - /// - /// The register pointer must point at one of the many SUBSCRIBE_* or PUBLISH_* registers of the peripherals - unsafe fn set_register_active(register: NonNull, channel: u8) { - register - .as_ptr() - .write_volatile(DPPI_ENABLE_BIT | (channel as u32 & DPPI_CHANNEL_MASK)); - } - - /// Resets the channel number and disables the register - /// - /// # Safety - /// - /// The register pointer must point at one of the many SUBSCRIBE_* or PUBLISH_* registers of the peripherals - unsafe fn set_register_inactive(register: NonNull) { - register.as_ptr().write_volatile(0); - } - - /// Gets the current configured channel number of the register - /// - /// # Safety - /// - /// The register pointer must point at one of the many SUBSCRIBE_* or PUBLISH_* registers of the peripherals - unsafe fn get_register_channel(register: NonNull) -> u8 { - let bits = register.as_ptr().read_volatile(); - (bits & DPPI_CHANNEL_MASK) as u8 - } -} - -impl<'d, C: Channel> Drop for Ppi<'d, C> { - fn drop(&mut self) { - self.disable() - } -} - -/// Represents a task that a peripheral can do. -/// When a task is subscribed to a PPI channel it will run when the channel is triggered by -/// a published event. -/// -/// The pointer in the task can point to two different kinds of register: -/// - PPI *(nRF51 & nRF52)*: A pointer to a task register of the task of the peripheral that has -/// to be registered with the PPI to subscribe to a channel -/// - DPPI *(nRF53 & nRF91)*: A pointer to the subscribe register of the task of the peripheral -/// that has to have the channel number and enable bit written tp it to subscribe to a channel -#[derive(PartialEq, Eq, Clone, Copy)] -pub struct Task(pub NonNull); -impl Task { - pub(crate) fn from_reg(reg: &T) -> Self { - Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) - } -} - -/// Represents an event that a peripheral can publish. -/// An event can be set to publish on a PPI channel when the event happens. -/// -/// The pointer in the event can point to two different kinds of register: -/// - PPI *(nRF51 & nRF52)*: A pointer to an event register of the event of the peripheral that has -/// to be registered with the PPI to publish to a channel -/// - DPPI *(nRF53 & nRF91)*: A pointer to the publish register of the event of the peripheral -/// that has to have the channel number and enable bit written tp it to publish to a channel -#[derive(PartialEq, Eq, Clone, Copy)] -pub struct Event(pub NonNull); -impl Event { - pub(crate) fn from_reg(reg: &T) -> Self { - Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) - } -} - -// ====================== -// traits - -pub(crate) mod sealed { - pub trait Channel {} - pub trait Group {} -} - -pub trait Channel: sealed::Channel + Sized { - /// Returns the number of the channel - fn number(&self) -> usize; - - /// Returns the amount of configurable tasks this channel has. - /// - /// - MAX for DPPI with unlimited capacity (nRF53 & nRF91) - /// - 0 for static channel without fork (nRF51) - /// - 1 for static channel with fork (nRF52) or for configurable channel (nRF51) - /// - 2 for configurable channel with fork (nRF52) - fn task_capacity(&self) -> usize; - - /// Returns the amount of configurable events this channels has - /// - /// - MAX for DPPI with unlimited capacity (nRF53 & nRF91) - /// - 0 for static channel (nRF51 & nRF52) - /// - 1 for configurable channel (nRF51 & nRF52) - fn event_capacity(&self) -> usize; - - fn degrade(self) -> AnyChannel { - pub trait ConfigurableChannel {} - - AnyChannel { - number: self.number() as u8, - task_capacity: self.task_capacity() as _, - event_capacity: self.event_capacity() as _, - } - } -} - -pub trait Group: sealed::Group + Sized { - fn number(&self) -> usize; - fn degrade(self) -> AnyGroup { - AnyGroup { - number: self.number() as u8, - } - } -} - -// ====================== -// channels - -pub struct AnyChannel { - number: u8, - task_capacity: u8, - event_capacity: u8, -} -unsafe_impl_unborrow!(AnyChannel); -impl sealed::Channel for AnyChannel {} -impl Channel for AnyChannel { - fn number(&self) -> usize { - self.number as usize - } - - fn task_capacity(&self) -> usize { - self.task_capacity as _ - } - - fn event_capacity(&self) -> usize { - self.event_capacity as _ - } -} - -macro_rules! impl_ppi_channel { - ($type:ident, $number:expr, $task_capacity:expr, $event_capacity:expr) => { - impl crate::ppi::sealed::Channel for peripherals::$type {} - impl crate::ppi::Channel for peripherals::$type { - fn number(&self) -> usize { - $number - } - fn task_capacity(&self) -> usize { - $task_capacity - } - fn event_capacity(&self) -> usize { - $event_capacity - } - } - }; - ($type:ident, $number:expr) => { - impl crate::ppi::sealed::Channel for peripherals::$type {} - impl crate::ppi::Channel for peripherals::$type { - fn number(&self) -> usize { - $number - } - fn task_capacity(&self) -> usize { - usize::MAX - } - fn event_capacity(&self) -> usize { - usize::MAX - } - } - }; -} - -// ====================== -// groups - -pub struct AnyGroup { - number: u8, -} -unsafe_impl_unborrow!(AnyGroup); -impl sealed::Group for AnyGroup {} -impl Group for AnyGroup { - fn number(&self) -> usize { - self.number as usize - } -} - -macro_rules! impl_group { - ($type:ident, $number:expr) => { - impl sealed::Group for peripherals::$type {} - impl Group for peripherals::$type { - fn number(&self) -> usize { - $number - } - } - }; -} - -impl_group!(PPI_GROUP0, 0); -impl_group!(PPI_GROUP1, 1); -impl_group!(PPI_GROUP2, 2); -impl_group!(PPI_GROUP3, 3); -#[cfg(not(feature = "nrf51"))] -impl_group!(PPI_GROUP4, 4); -#[cfg(not(feature = "nrf51"))] -impl_group!(PPI_GROUP5, 5); diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index e62120aef..27f8e715e 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -11,9 +11,8 @@ use embassy_hal_common::drop::OnDrop; use embassy_hal_common::unborrow; use futures::future::poll_fn; +use crate::interconnect::{Event, Task}; use crate::pac; -use crate::ppi::Event; -use crate::ppi::Task; pub(crate) mod sealed { @@ -184,36 +183,21 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> { /// /// When triggered, this task starts the timer. pub fn task_start(&self) -> Task { - #[cfg(feature = "_ppi")] - let reg = &T::regs().tasks_start; - #[cfg(feature = "_dppi")] - let reg = &T::regs().subscribe_start; - - Task::from_reg(reg) + Task::from_reg(&T::regs().tasks_start) } /// Returns the STOP task, for use with PPI. /// /// When triggered, this task stops the timer. pub fn task_stop(&self) -> Task { - #[cfg(feature = "_ppi")] - let reg = &T::regs().tasks_stop; - #[cfg(feature = "_dppi")] - let reg = &T::regs().subscribe_stop; - - Task::from_reg(reg) + Task::from_reg(&T::regs().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 { - #[cfg(feature = "_ppi")] - let reg = &T::regs().tasks_clear; - #[cfg(feature = "_dppi")] - let reg = &T::regs().subscribe_clear; - - Task::from_reg(reg) + Task::from_reg(&T::regs().tasks_clear) } /// Change the timer's frequency. @@ -334,24 +318,14 @@ impl<'a, T: Instance, I: TimerType> Cc<'a, T, I> { /// /// When triggered, this task will capture the current value of the timer's counter in this register. pub fn task_capture(&self) -> Task { - #[cfg(feature = "_ppi")] - let reg = &T::regs().tasks_capture; - #[cfg(feature = "_dppi")] - let reg = &T::regs().subscribe_capture; - - Task::from_reg(reg) + Task::from_reg(&T::regs().tasks_capture) } /// 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 { - #[cfg(feature = "_ppi")] - let reg = &T::regs().events_compare[self.n]; - #[cfg(feature = "_dppi")] - let reg = &T::regs().publish_compare[self.n]; - - Event::from_reg(reg) + Event::from_reg(&T::regs().events_compare[self.n]) } /// Enable the shortcut between this CC register's COMPARE event and the timer's CLEAR task. diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 71401a561..17e60ce22 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -16,28 +16,15 @@ use futures::future::poll_fn; use crate::chip::EASY_DMA_SIZE; use crate::gpio::sealed::Pin as _; use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin}; +use crate::interconnect::{AnyChannel, Event, OneToOneChannel, OneToTwoChannel, Ppi, Task}; use crate::interrupt::Interrupt; use crate::pac; -use crate::ppi::{AnyChannel, Channel, Event, Ppi, Task}; use crate::timer::Instance as TimerInstance; use crate::timer::{Frequency, Timer}; // Re-export SVD variants to allow user to directly set values. pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; -#[non_exhaustive] -#[derive(Clone, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -pub enum Error { - PpiError(crate::ppi::Error), -} - -impl From for Error { - fn from(e: crate::ppi::Error) -> Self { - Self::PpiError(e) - } -} - #[non_exhaustive] pub struct Config { pub parity: Parity, @@ -344,17 +331,14 @@ impl<'d, T: Instance> Write for Uarte<'d, T> { pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { uarte: Uarte<'d, U>, timer: Timer<'d, T>, - ppi_ch1: Ppi<'d, AnyChannel>, - _ppi_ch2: Ppi<'d, AnyChannel>, + ppi_ch1: Ppi<'d, AnyChannel, 1, 2>, + _ppi_ch2: Ppi<'d, AnyChannel, 1, 1>, } impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { /// Creates the interface to a UARTE instance. /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. /// - /// - *Note:* ppi_ch1 must have at least 1 free event and 2 free tasks or a PPI error is returned - /// - *Note:* ppi_ch2 must have at least 1 free event and 1 free tasks or a PPI error is returned - /// /// # Safety /// /// The returned API is safe unless you use `mem::forget` (or similar safe mechanisms) @@ -364,15 +348,15 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { pub unsafe fn new( uarte: impl Unborrow + 'd, timer: impl Unborrow + 'd, - ppi_ch1: impl Unborrow + 'd, - ppi_ch2: impl Unborrow + 'd, + ppi_ch1: impl Unborrow + 'd, + ppi_ch2: impl Unborrow + 'd, irq: impl Unborrow + 'd, rxd: impl Unborrow + 'd, txd: impl Unborrow + 'd, cts: impl Unborrow + 'd, rts: impl Unborrow + 'd, config: Config, - ) -> Result { + ) -> Self { let baudrate = config.baudrate; let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config); let mut timer = Timer::new(timer); @@ -394,23 +378,29 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { timer.cc(0).short_compare_clear(); timer.cc(0).short_compare_stop(); - let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade()); - ppi_ch1.publish(Event::from_reg(&r.events_rxdrdy))?; - ppi_ch1.subscribe(timer.task_clear())?; - ppi_ch1.subscribe(timer.task_start())?; + let mut ppi_ch1 = Ppi::new_one_to_two( + ppi_ch1, + Event::from_reg(&r.events_rxdrdy), + timer.task_clear(), + timer.task_start(), + ) + .degrade(); ppi_ch1.enable(); - let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade()); - ppi_ch2.publish(timer.cc(0).event_compare())?; - ppi_ch2.subscribe(Task::from_reg(&r.tasks_stoprx))?; + let mut ppi_ch2 = Ppi::new_one_to_one( + ppi_ch2, + timer.cc(0).event_compare(), + Task::from_reg(&r.tasks_stoprx), + ) + .degrade(); ppi_ch2.enable(); - Ok(Self { + Self { uarte, timer, ppi_ch1: ppi_ch1, _ppi_ch2: ppi_ch2, - }) + } } } diff --git a/examples/nrf/src/bin/buffered_uart.rs b/examples/nrf/src/bin/buffered_uart.rs index b01c83ce3..69c7de93b 100644 --- a/examples/nrf/src/bin/buffered_uart.rs +++ b/examples/nrf/src/bin/buffered_uart.rs @@ -26,7 +26,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { let irq = interrupt::take!(UARTE0_UART0); let mut state = State::new(); let u = unsafe { - unwrap!(BufferedUarte::new( + BufferedUarte::new( &mut state, p.UARTE0, p.TIMER0, @@ -40,7 +40,7 @@ async fn main(_spawner: Spawner, p: Peripherals) { config, &mut rx_buffer, &mut tx_buffer, - )) + ) }; pin_mut!(u); diff --git a/examples/nrf/src/bin/ppi.rs b/examples/nrf/src/bin/ppi.rs index 550893968..4edb5d7c0 100644 --- a/examples/nrf/src/bin/ppi.rs +++ b/examples/nrf/src/bin/ppi.rs @@ -10,7 +10,7 @@ use core::future::pending; use embassy::executor::Spawner; use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull}; use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; -use embassy_nrf::ppi::Ppi; +use embassy_nrf::interconnect::Ppi; use embassy_nrf::Peripherals; use gpiote::{OutputChannel, OutputChannelPolarity}; @@ -51,25 +51,21 @@ async fn main(_spawner: Spawner, p: Peripherals) { OutputChannelPolarity::Toggle, ); - let mut ppi = Ppi::new(p.PPI_CH0); - ppi.publish(button1.event_in()).unwrap(); - ppi.subscribe(led1.task_out()).unwrap(); + let mut ppi = Ppi::new_one_to_one(p.PPI_CH0, button1.event_in(), led1.task_out()); ppi.enable(); - let mut ppi = Ppi::new(p.PPI_CH1); - ppi.publish(button2.event_in()).unwrap(); - ppi.subscribe(led1.task_clr()).unwrap(); + let mut ppi = Ppi::new_one_to_one(p.PPI_CH1, button2.event_in(), led1.task_clr()); ppi.enable(); - let mut ppi = Ppi::new(p.PPI_CH2); - ppi.publish(button3.event_in()).unwrap(); - ppi.subscribe(led1.task_set()).unwrap(); + let mut ppi = Ppi::new_one_to_one(p.PPI_CH2, button3.event_in(), led1.task_set()); ppi.enable(); - let mut ppi = Ppi::new(p.PPI_CH3); - ppi.publish(button4.event_in()).unwrap(); - ppi.subscribe(led1.task_out()).unwrap(); - ppi.subscribe(led2.task_out()).unwrap(); + let mut ppi = Ppi::new_one_to_two( + p.PPI_CH3, + button4.event_in(), + led1.task_out(), + led2.task_out(), + ); ppi.enable(); info!("PPI setup!"); diff --git a/examples/nrf/src/bin/uart_idle.rs b/examples/nrf/src/bin/uart_idle.rs index e04e5cf04..e9f4a285a 100644 --- a/examples/nrf/src/bin/uart_idle.rs +++ b/examples/nrf/src/bin/uart_idle.rs @@ -21,9 +21,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { let irq = interrupt::take!(UARTE0_UART0); let mut uart = unsafe { - unwrap!(uarte::UarteWithIdle::new( + uarte::UarteWithIdle::new( p.UARTE0, p.TIMER0, p.PPI_CH0, p.PPI_CH1, irq, p.P0_08, p.P0_06, NoPin, NoPin, config, - )) + ) }; info!("uarte initialized!");