diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index fc1ec6b01..c083978c3 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -18,18 +18,20 @@ defmt-info = [ ] defmt-warn = [ ] defmt-error = [ ] -nrf52805 = ["nrf52805-pac"] -nrf52810 = ["nrf52810-pac"] -nrf52811 = ["nrf52811-pac"] -nrf52820 = ["nrf52820-pac"] -nrf52832 = ["nrf52832-pac"] -nrf52833 = ["nrf52833-pac"] -nrf52840 = ["nrf52840-pac"] -nrf9160 = ["nrf9160-pac"] +nrf52805 = ["nrf52805-pac", "_ppi"] +nrf52810 = ["nrf52810-pac", "_ppi"] +nrf52811 = ["nrf52811-pac", "_ppi"] +nrf52820 = ["nrf52820-pac", "_ppi"] +nrf52832 = ["nrf52832-pac", "_ppi"] +nrf52833 = ["nrf52833-pac", "_ppi"] +nrf52840 = ["nrf52840-pac", "_ppi"] +nrf9160 = ["nrf9160-pac", "_dppi"] # Features starting with `_` are for internal use only. They're not intended # to be enabled by other crates, and are not covered by semver guarantees. _time-driver = ["embassy/time-tick-32768hz"] +_ppi = [] +_dppi = [] gpiote = [] time-driver-rtc1 = ["_time-driver"] diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index cd08875cd..717ada78d 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -5,7 +5,7 @@ use core::pin::Pin; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; use embassy::interrupt::InterruptExt; -use embassy::io::{AsyncBufRead, AsyncWrite, Result}; +use embassy::io::{AsyncBufRead, AsyncWrite}; use embassy::util::Unborrow; use embassy::waitqueue::WakerRegistration; use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; @@ -45,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, AnyConfigurableChannel>, - _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, + _ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>, + _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>, rx: RingBuffer<'d>, rx_state: RxState, @@ -70,8 +70,8 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { 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, @@ -144,15 +144,19 @@ 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_configurable()); - ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); - ppi_ch1.set_task(timer.task_clear()); - ppi_ch1.set_fork_task(timer.task_start()); + let mut ppi_ch1 = Ppi::new_one_to_two( + ppi_ch1.degrade(), + Event::from_reg(&r.events_rxdrdy), + timer.task_clear(), + timer.task_start(), + ); ppi_ch1.enable(); - let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); - ppi_ch2.set_event(timer.cc(0).event_compare()); - ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); + let mut ppi_ch2 = Ppi::new_one_to_one( + ppi_ch2.degrade(), + timer.cc(0).event_compare(), + Task::from_reg(&r.tasks_stoprx), + ); ppi_ch2.enable(); Self { @@ -187,7 +191,10 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { } impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d, U, T> { - fn poll_fill_buf(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_fill_buf( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { self.inner.with(|state| { // Conservative compiler fence to prevent optimizations that do not // take in to account actions by DMA. The fence has been placed here, @@ -206,7 +213,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncBufRead for BufferedUarte<'d, trace!(" empty"); state.rx_waker.register(cx.waker()); - Poll::>::Pending + Poll::>::Pending }) } @@ -224,7 +231,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> AsyncWrite for BufferedUarte<'d, U, mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], - ) -> Poll> { + ) -> Poll> { let poll = self.inner.with(|state| { trace!("poll_write: {:?}", buf.len()); diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs index d68697936..689896485 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, configurable); -impl_ppi_channel!(PPI_CH1, 1, configurable); -impl_ppi_channel!(PPI_CH2, 2, configurable); -impl_ppi_channel!(PPI_CH3, 3, configurable); -impl_ppi_channel!(PPI_CH4, 4, configurable); -impl_ppi_channel!(PPI_CH5, 5, configurable); -impl_ppi_channel!(PPI_CH6, 6, configurable); -impl_ppi_channel!(PPI_CH7, 7, configurable); -impl_ppi_channel!(PPI_CH8, 8, configurable); -impl_ppi_channel!(PPI_CH9, 9, configurable); -impl_ppi_channel!(PPI_CH20, 20); -impl_ppi_channel!(PPI_CH21, 21); -impl_ppi_channel!(PPI_CH22, 22); -impl_ppi_channel!(PPI_CH23, 23); -impl_ppi_channel!(PPI_CH24, 24); -impl_ppi_channel!(PPI_CH25, 25); -impl_ppi_channel!(PPI_CH26, 26); -impl_ppi_channel!(PPI_CH27, 27); -impl_ppi_channel!(PPI_CH28, 28); -impl_ppi_channel!(PPI_CH29, 29); -impl_ppi_channel!(PPI_CH30, 30); -impl_ppi_channel!(PPI_CH31, 31); +impl_ppi_channel!(PPI_CH0, 0 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH20, 20 => static); +impl_ppi_channel!(PPI_CH21, 21 => static); +impl_ppi_channel!(PPI_CH22, 22 => static); +impl_ppi_channel!(PPI_CH23, 23 => static); +impl_ppi_channel!(PPI_CH24, 24 => static); +impl_ppi_channel!(PPI_CH25, 25 => static); +impl_ppi_channel!(PPI_CH26, 26 => static); +impl_ppi_channel!(PPI_CH27, 27 => static); +impl_ppi_channel!(PPI_CH28, 28 => static); +impl_ppi_channel!(PPI_CH29, 29 => static); +impl_ppi_channel!(PPI_CH30, 30 => static); +impl_ppi_channel!(PPI_CH31, 31 => static); 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 c119e7cdb..b3b3593bb 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, configurable); -impl_ppi_channel!(PPI_CH1, 1, configurable); -impl_ppi_channel!(PPI_CH2, 2, configurable); -impl_ppi_channel!(PPI_CH3, 3, configurable); -impl_ppi_channel!(PPI_CH4, 4, configurable); -impl_ppi_channel!(PPI_CH5, 5, configurable); -impl_ppi_channel!(PPI_CH6, 6, configurable); -impl_ppi_channel!(PPI_CH7, 7, configurable); -impl_ppi_channel!(PPI_CH8, 8, configurable); -impl_ppi_channel!(PPI_CH9, 9, configurable); -impl_ppi_channel!(PPI_CH10, 10, configurable); -impl_ppi_channel!(PPI_CH11, 11, configurable); -impl_ppi_channel!(PPI_CH12, 12, configurable); -impl_ppi_channel!(PPI_CH13, 13, configurable); -impl_ppi_channel!(PPI_CH14, 14, configurable); -impl_ppi_channel!(PPI_CH15, 15, configurable); -impl_ppi_channel!(PPI_CH16, 16, configurable); -impl_ppi_channel!(PPI_CH17, 17, configurable); -impl_ppi_channel!(PPI_CH18, 18, configurable); -impl_ppi_channel!(PPI_CH19, 19, configurable); -impl_ppi_channel!(PPI_CH20, 20); -impl_ppi_channel!(PPI_CH21, 21); -impl_ppi_channel!(PPI_CH22, 22); -impl_ppi_channel!(PPI_CH23, 23); -impl_ppi_channel!(PPI_CH24, 24); -impl_ppi_channel!(PPI_CH25, 25); -impl_ppi_channel!(PPI_CH26, 26); -impl_ppi_channel!(PPI_CH27, 27); -impl_ppi_channel!(PPI_CH28, 28); -impl_ppi_channel!(PPI_CH29, 29); -impl_ppi_channel!(PPI_CH30, 30); -impl_ppi_channel!(PPI_CH31, 31); +impl_ppi_channel!(PPI_CH0, 0 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH10, 10 => configurable); +impl_ppi_channel!(PPI_CH11, 11 => configurable); +impl_ppi_channel!(PPI_CH12, 12 => configurable); +impl_ppi_channel!(PPI_CH13, 13 => configurable); +impl_ppi_channel!(PPI_CH14, 14 => configurable); +impl_ppi_channel!(PPI_CH15, 15 => configurable); +impl_ppi_channel!(PPI_CH16, 16 => configurable); +impl_ppi_channel!(PPI_CH17, 17 => configurable); +impl_ppi_channel!(PPI_CH18, 18 => configurable); +impl_ppi_channel!(PPI_CH19, 19 => configurable); +impl_ppi_channel!(PPI_CH20, 20 => static); +impl_ppi_channel!(PPI_CH21, 21 => static); +impl_ppi_channel!(PPI_CH22, 22 => static); +impl_ppi_channel!(PPI_CH23, 23 => static); +impl_ppi_channel!(PPI_CH24, 24 => static); +impl_ppi_channel!(PPI_CH25, 25 => static); +impl_ppi_channel!(PPI_CH26, 26 => static); +impl_ppi_channel!(PPI_CH27, 27 => static); +impl_ppi_channel!(PPI_CH28, 28 => static); +impl_ppi_channel!(PPI_CH29, 29 => static); +impl_ppi_channel!(PPI_CH30, 30 => static); +impl_ppi_channel!(PPI_CH31, 31 => static); 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 3c9df40fe..7551492c3 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, configurable); -impl_ppi_channel!(PPI_CH1, 1, configurable); -impl_ppi_channel!(PPI_CH2, 2, configurable); -impl_ppi_channel!(PPI_CH3, 3, configurable); -impl_ppi_channel!(PPI_CH4, 4, configurable); -impl_ppi_channel!(PPI_CH5, 5, configurable); -impl_ppi_channel!(PPI_CH6, 6, configurable); -impl_ppi_channel!(PPI_CH7, 7, configurable); -impl_ppi_channel!(PPI_CH8, 8, configurable); -impl_ppi_channel!(PPI_CH9, 9, configurable); -impl_ppi_channel!(PPI_CH10, 10, configurable); -impl_ppi_channel!(PPI_CH11, 11, configurable); -impl_ppi_channel!(PPI_CH12, 12, configurable); -impl_ppi_channel!(PPI_CH13, 13, configurable); -impl_ppi_channel!(PPI_CH14, 14, configurable); -impl_ppi_channel!(PPI_CH15, 15, configurable); -impl_ppi_channel!(PPI_CH16, 16, configurable); -impl_ppi_channel!(PPI_CH17, 17, configurable); -impl_ppi_channel!(PPI_CH18, 18, configurable); -impl_ppi_channel!(PPI_CH19, 19, configurable); -impl_ppi_channel!(PPI_CH20, 20); -impl_ppi_channel!(PPI_CH21, 21); -impl_ppi_channel!(PPI_CH22, 22); -impl_ppi_channel!(PPI_CH23, 23); -impl_ppi_channel!(PPI_CH24, 24); -impl_ppi_channel!(PPI_CH25, 25); -impl_ppi_channel!(PPI_CH26, 26); -impl_ppi_channel!(PPI_CH27, 27); -impl_ppi_channel!(PPI_CH28, 28); -impl_ppi_channel!(PPI_CH29, 29); -impl_ppi_channel!(PPI_CH30, 30); -impl_ppi_channel!(PPI_CH31, 31); +impl_ppi_channel!(PPI_CH0, 0 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH10, 10 => configurable); +impl_ppi_channel!(PPI_CH11, 11 => configurable); +impl_ppi_channel!(PPI_CH12, 12 => configurable); +impl_ppi_channel!(PPI_CH13, 13 => configurable); +impl_ppi_channel!(PPI_CH14, 14 => configurable); +impl_ppi_channel!(PPI_CH15, 15 => configurable); +impl_ppi_channel!(PPI_CH16, 16 => configurable); +impl_ppi_channel!(PPI_CH17, 17 => configurable); +impl_ppi_channel!(PPI_CH18, 18 => configurable); +impl_ppi_channel!(PPI_CH19, 19 => configurable); +impl_ppi_channel!(PPI_CH20, 20 => static); +impl_ppi_channel!(PPI_CH21, 21 => static); +impl_ppi_channel!(PPI_CH22, 22 => static); +impl_ppi_channel!(PPI_CH23, 23 => static); +impl_ppi_channel!(PPI_CH24, 24 => static); +impl_ppi_channel!(PPI_CH25, 25 => static); +impl_ppi_channel!(PPI_CH26, 26 => static); +impl_ppi_channel!(PPI_CH27, 27 => static); +impl_ppi_channel!(PPI_CH28, 28 => static); +impl_ppi_channel!(PPI_CH29, 29 => static); +impl_ppi_channel!(PPI_CH30, 30 => static); +impl_ppi_channel!(PPI_CH31, 31 => static); 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 8a8e23a9e..128e1503f 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, configurable); -impl_ppi_channel!(PPI_CH1, 1, configurable); -impl_ppi_channel!(PPI_CH2, 2, configurable); -impl_ppi_channel!(PPI_CH3, 3, configurable); -impl_ppi_channel!(PPI_CH4, 4, configurable); -impl_ppi_channel!(PPI_CH5, 5, configurable); -impl_ppi_channel!(PPI_CH6, 6, configurable); -impl_ppi_channel!(PPI_CH7, 7, configurable); -impl_ppi_channel!(PPI_CH8, 8, configurable); -impl_ppi_channel!(PPI_CH9, 9, configurable); -impl_ppi_channel!(PPI_CH10, 10, configurable); -impl_ppi_channel!(PPI_CH11, 11, configurable); -impl_ppi_channel!(PPI_CH12, 12, configurable); -impl_ppi_channel!(PPI_CH13, 13, configurable); -impl_ppi_channel!(PPI_CH14, 14, configurable); -impl_ppi_channel!(PPI_CH15, 15, configurable); -impl_ppi_channel!(PPI_CH16, 16, configurable); -impl_ppi_channel!(PPI_CH17, 17, configurable); -impl_ppi_channel!(PPI_CH18, 18, configurable); -impl_ppi_channel!(PPI_CH19, 19, configurable); -impl_ppi_channel!(PPI_CH20, 20); -impl_ppi_channel!(PPI_CH21, 21); -impl_ppi_channel!(PPI_CH22, 22); -impl_ppi_channel!(PPI_CH23, 23); -impl_ppi_channel!(PPI_CH24, 24); -impl_ppi_channel!(PPI_CH25, 25); -impl_ppi_channel!(PPI_CH26, 26); -impl_ppi_channel!(PPI_CH27, 27); -impl_ppi_channel!(PPI_CH28, 28); -impl_ppi_channel!(PPI_CH29, 29); -impl_ppi_channel!(PPI_CH30, 30); -impl_ppi_channel!(PPI_CH31, 31); +impl_ppi_channel!(PPI_CH0, 0 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH10, 10 => configurable); +impl_ppi_channel!(PPI_CH11, 11 => configurable); +impl_ppi_channel!(PPI_CH12, 12 => configurable); +impl_ppi_channel!(PPI_CH13, 13 => configurable); +impl_ppi_channel!(PPI_CH14, 14 => configurable); +impl_ppi_channel!(PPI_CH15, 15 => configurable); +impl_ppi_channel!(PPI_CH16, 16 => configurable); +impl_ppi_channel!(PPI_CH17, 17 => configurable); +impl_ppi_channel!(PPI_CH18, 18 => configurable); +impl_ppi_channel!(PPI_CH19, 19 => configurable); +impl_ppi_channel!(PPI_CH20, 20 => static); +impl_ppi_channel!(PPI_CH21, 21 => static); +impl_ppi_channel!(PPI_CH22, 22 => static); +impl_ppi_channel!(PPI_CH23, 23 => static); +impl_ppi_channel!(PPI_CH24, 24 => static); +impl_ppi_channel!(PPI_CH25, 25 => static); +impl_ppi_channel!(PPI_CH26, 26 => static); +impl_ppi_channel!(PPI_CH27, 27 => static); +impl_ppi_channel!(PPI_CH28, 28 => static); +impl_ppi_channel!(PPI_CH29, 29 => static); +impl_ppi_channel!(PPI_CH30, 30 => static); +impl_ppi_channel!(PPI_CH31, 31 => static); 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 c1b02a0bf..432af143c 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, configurable); -impl_ppi_channel!(PPI_CH1, 1, configurable); -impl_ppi_channel!(PPI_CH2, 2, configurable); -impl_ppi_channel!(PPI_CH3, 3, configurable); -impl_ppi_channel!(PPI_CH4, 4, configurable); -impl_ppi_channel!(PPI_CH5, 5, configurable); -impl_ppi_channel!(PPI_CH6, 6, configurable); -impl_ppi_channel!(PPI_CH7, 7, configurable); -impl_ppi_channel!(PPI_CH8, 8, configurable); -impl_ppi_channel!(PPI_CH9, 9, configurable); -impl_ppi_channel!(PPI_CH10, 10, configurable); -impl_ppi_channel!(PPI_CH11, 11, configurable); -impl_ppi_channel!(PPI_CH12, 12, configurable); -impl_ppi_channel!(PPI_CH13, 13, configurable); -impl_ppi_channel!(PPI_CH14, 14, configurable); -impl_ppi_channel!(PPI_CH15, 15, configurable); -impl_ppi_channel!(PPI_CH16, 16, configurable); -impl_ppi_channel!(PPI_CH17, 17, configurable); -impl_ppi_channel!(PPI_CH18, 18, configurable); -impl_ppi_channel!(PPI_CH19, 19, configurable); -impl_ppi_channel!(PPI_CH20, 20); -impl_ppi_channel!(PPI_CH21, 21); -impl_ppi_channel!(PPI_CH22, 22); -impl_ppi_channel!(PPI_CH23, 23); -impl_ppi_channel!(PPI_CH24, 24); -impl_ppi_channel!(PPI_CH25, 25); -impl_ppi_channel!(PPI_CH26, 26); -impl_ppi_channel!(PPI_CH27, 27); -impl_ppi_channel!(PPI_CH28, 28); -impl_ppi_channel!(PPI_CH29, 29); -impl_ppi_channel!(PPI_CH30, 30); -impl_ppi_channel!(PPI_CH31, 31); +impl_ppi_channel!(PPI_CH0, 0 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH10, 10 => configurable); +impl_ppi_channel!(PPI_CH11, 11 => configurable); +impl_ppi_channel!(PPI_CH12, 12 => configurable); +impl_ppi_channel!(PPI_CH13, 13 => configurable); +impl_ppi_channel!(PPI_CH14, 14 => configurable); +impl_ppi_channel!(PPI_CH15, 15 => configurable); +impl_ppi_channel!(PPI_CH16, 16 => configurable); +impl_ppi_channel!(PPI_CH17, 17 => configurable); +impl_ppi_channel!(PPI_CH18, 18 => configurable); +impl_ppi_channel!(PPI_CH19, 19 => configurable); +impl_ppi_channel!(PPI_CH20, 20 => static); +impl_ppi_channel!(PPI_CH21, 21 => static); +impl_ppi_channel!(PPI_CH22, 22 => static); +impl_ppi_channel!(PPI_CH23, 23 => static); +impl_ppi_channel!(PPI_CH24, 24 => static); +impl_ppi_channel!(PPI_CH25, 25 => static); +impl_ppi_channel!(PPI_CH26, 26 => static); +impl_ppi_channel!(PPI_CH27, 27 => static); +impl_ppi_channel!(PPI_CH28, 28 => static); +impl_ppi_channel!(PPI_CH29, 29 => static); +impl_ppi_channel!(PPI_CH30, 30 => static); +impl_ppi_channel!(PPI_CH31, 31 => static); 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 4f5c26002..7c7198dfd 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, configurable); -impl_ppi_channel!(PPI_CH1, 1, configurable); -impl_ppi_channel!(PPI_CH2, 2, configurable); -impl_ppi_channel!(PPI_CH3, 3, configurable); -impl_ppi_channel!(PPI_CH4, 4, configurable); -impl_ppi_channel!(PPI_CH5, 5, configurable); -impl_ppi_channel!(PPI_CH6, 6, configurable); -impl_ppi_channel!(PPI_CH7, 7, configurable); -impl_ppi_channel!(PPI_CH8, 8, configurable); -impl_ppi_channel!(PPI_CH9, 9, configurable); -impl_ppi_channel!(PPI_CH10, 10, configurable); -impl_ppi_channel!(PPI_CH11, 11, configurable); -impl_ppi_channel!(PPI_CH12, 12, configurable); -impl_ppi_channel!(PPI_CH13, 13, configurable); -impl_ppi_channel!(PPI_CH14, 14, configurable); -impl_ppi_channel!(PPI_CH15, 15, configurable); -impl_ppi_channel!(PPI_CH16, 16, configurable); -impl_ppi_channel!(PPI_CH17, 17, configurable); -impl_ppi_channel!(PPI_CH18, 18, configurable); -impl_ppi_channel!(PPI_CH19, 19, configurable); -impl_ppi_channel!(PPI_CH20, 20); -impl_ppi_channel!(PPI_CH21, 21); -impl_ppi_channel!(PPI_CH22, 22); -impl_ppi_channel!(PPI_CH23, 23); -impl_ppi_channel!(PPI_CH24, 24); -impl_ppi_channel!(PPI_CH25, 25); -impl_ppi_channel!(PPI_CH26, 26); -impl_ppi_channel!(PPI_CH27, 27); -impl_ppi_channel!(PPI_CH28, 28); -impl_ppi_channel!(PPI_CH29, 29); -impl_ppi_channel!(PPI_CH30, 30); -impl_ppi_channel!(PPI_CH31, 31); +impl_ppi_channel!(PPI_CH0, 0 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH10, 10 => configurable); +impl_ppi_channel!(PPI_CH11, 11 => configurable); +impl_ppi_channel!(PPI_CH12, 12 => configurable); +impl_ppi_channel!(PPI_CH13, 13 => configurable); +impl_ppi_channel!(PPI_CH14, 14 => configurable); +impl_ppi_channel!(PPI_CH15, 15 => configurable); +impl_ppi_channel!(PPI_CH16, 16 => configurable); +impl_ppi_channel!(PPI_CH17, 17 => configurable); +impl_ppi_channel!(PPI_CH18, 18 => configurable); +impl_ppi_channel!(PPI_CH19, 19 => configurable); +impl_ppi_channel!(PPI_CH20, 20 => static); +impl_ppi_channel!(PPI_CH21, 21 => static); +impl_ppi_channel!(PPI_CH22, 22 => static); +impl_ppi_channel!(PPI_CH23, 23 => static); +impl_ppi_channel!(PPI_CH24, 24 => static); +impl_ppi_channel!(PPI_CH25, 25 => static); +impl_ppi_channel!(PPI_CH26, 26 => static); +impl_ppi_channel!(PPI_CH27, 27 => static); +impl_ppi_channel!(PPI_CH28, 28 => static); +impl_ppi_channel!(PPI_CH29, 29 => static); +impl_ppi_channel!(PPI_CH30, 30 => static); +impl_ppi_channel!(PPI_CH31, 31 => static); 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 1006acd95..f5b90cd5a 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, configurable); -impl_ppi_channel!(PPI_CH1, 1, configurable); -impl_ppi_channel!(PPI_CH2, 2, configurable); -impl_ppi_channel!(PPI_CH3, 3, configurable); -impl_ppi_channel!(PPI_CH4, 4, configurable); -impl_ppi_channel!(PPI_CH5, 5, configurable); -impl_ppi_channel!(PPI_CH6, 6, configurable); -impl_ppi_channel!(PPI_CH7, 7, configurable); -impl_ppi_channel!(PPI_CH8, 8, configurable); -impl_ppi_channel!(PPI_CH9, 9, configurable); -impl_ppi_channel!(PPI_CH10, 10, configurable); -impl_ppi_channel!(PPI_CH11, 11, configurable); -impl_ppi_channel!(PPI_CH12, 12, configurable); -impl_ppi_channel!(PPI_CH13, 13, configurable); -impl_ppi_channel!(PPI_CH14, 14, configurable); -impl_ppi_channel!(PPI_CH15, 15, configurable); -impl_ppi_channel!(PPI_CH16, 16, configurable); -impl_ppi_channel!(PPI_CH17, 17, configurable); -impl_ppi_channel!(PPI_CH18, 18, configurable); -impl_ppi_channel!(PPI_CH19, 19, configurable); -impl_ppi_channel!(PPI_CH20, 20); -impl_ppi_channel!(PPI_CH21, 21); -impl_ppi_channel!(PPI_CH22, 22); -impl_ppi_channel!(PPI_CH23, 23); -impl_ppi_channel!(PPI_CH24, 24); -impl_ppi_channel!(PPI_CH25, 25); -impl_ppi_channel!(PPI_CH26, 26); -impl_ppi_channel!(PPI_CH27, 27); -impl_ppi_channel!(PPI_CH28, 28); -impl_ppi_channel!(PPI_CH29, 29); -impl_ppi_channel!(PPI_CH30, 30); -impl_ppi_channel!(PPI_CH31, 31); +impl_ppi_channel!(PPI_CH0, 0 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH10, 10 => configurable); +impl_ppi_channel!(PPI_CH11, 11 => configurable); +impl_ppi_channel!(PPI_CH12, 12 => configurable); +impl_ppi_channel!(PPI_CH13, 13 => configurable); +impl_ppi_channel!(PPI_CH14, 14 => configurable); +impl_ppi_channel!(PPI_CH15, 15 => configurable); +impl_ppi_channel!(PPI_CH16, 16 => configurable); +impl_ppi_channel!(PPI_CH17, 17 => configurable); +impl_ppi_channel!(PPI_CH18, 18 => configurable); +impl_ppi_channel!(PPI_CH19, 19 => configurable); +impl_ppi_channel!(PPI_CH20, 20 => static); +impl_ppi_channel!(PPI_CH21, 21 => static); +impl_ppi_channel!(PPI_CH22, 22 => static); +impl_ppi_channel!(PPI_CH23, 23 => static); +impl_ppi_channel!(PPI_CH24, 24 => static); +impl_ppi_channel!(PPI_CH25, 25 => static); +impl_ppi_channel!(PPI_CH26, 26 => static); +impl_ppi_channel!(PPI_CH27, 27 => static); +impl_ppi_channel!(PPI_CH28, 28 => static); +impl_ppi_channel!(PPI_CH29, 29 => static); +impl_ppi_channel!(PPI_CH30, 30 => static); +impl_ppi_channel!(PPI_CH31, 31 => static); 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..6ca918104 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 => configurable); +impl_ppi_channel!(PPI_CH1, 1 => configurable); +impl_ppi_channel!(PPI_CH2, 2 => configurable); +impl_ppi_channel!(PPI_CH3, 3 => configurable); +impl_ppi_channel!(PPI_CH4, 4 => configurable); +impl_ppi_channel!(PPI_CH5, 5 => configurable); +impl_ppi_channel!(PPI_CH6, 6 => configurable); +impl_ppi_channel!(PPI_CH7, 7 => configurable); +impl_ppi_channel!(PPI_CH8, 8 => configurable); +impl_ppi_channel!(PPI_CH9, 9 => configurable); +impl_ppi_channel!(PPI_CH10, 10 => configurable); +impl_ppi_channel!(PPI_CH11, 11 => configurable); +impl_ppi_channel!(PPI_CH12, 12 => configurable); +impl_ppi_channel!(PPI_CH13, 13 => configurable); +impl_ppi_channel!(PPI_CH14, 14 => configurable); +impl_ppi_channel!(PPI_CH15, 15 => configurable); impl_saadc_input!(P0_13, ANALOGINPUT0); impl_saadc_input!(P0_14, ANALOGINPUT1); diff --git a/embassy-nrf/src/ppi.rs b/embassy-nrf/src/ppi.rs deleted file mode 100644 index f5e06c69f..000000000 --- a/embassy-nrf/src/ppi.rs +++ /dev/null @@ -1,248 +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 - -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); - - #[allow(unused_mut)] - let mut this = Self { - ch, - phantom: PhantomData, - }; - #[cfg(not(any(feature = "nrf51", feature = "nrf9160")))] - this.clear_fork_task(); - this - } - - /// 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(not(any(feature = "nrf51", feature = "nrf9160")))] - /// Sets the fork task that must be triggered when the configured event occurs. The user must - /// provide a reference to the task. - pub fn set_fork_task(&mut self, task: Task) { - let r = unsafe { &*pac::PPI::ptr() }; - r.fork[self.ch.number()] - .tep - .write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) - } - - #[cfg(not(any(feature = "nrf51", feature = "nrf9160")))] - /// Clear the fork task endpoint. Previously set task will no longer be triggered. - pub fn clear_fork_task(&mut self) { - let r = unsafe { &*pac::PPI::ptr() }; - r.fork[self.ch.number()].tep.write(|w| unsafe { w.bits(0) }) - } - - #[cfg(feature = "nrf9160")] - /// Sets the fork task that must be triggered when the configured event occurs. The user must - /// provide a reference to the task. - pub fn set_fork_task(&mut self, _task: Task) { - todo!("Tasks not yet implemented for nrf9160"); - } - - #[cfg(feature = "nrf9160")] - /// Clear the fork task endpoint. Previously set task will no longer be triggered. - pub fn clear_fork_task(&mut self) { - todo!("Tasks not yet implemented for nrf9160"); - } -} - -impl<'d, C: Channel> Drop for Ppi<'d, C> { - fn drop(&mut self) { - self.disable() - } -} - -#[cfg(not(feature = "nrf9160"))] -impl<'d, C: ConfigurableChannel> Ppi<'d, C> { - /// Sets the task to be triggered when the configured event occurs. - pub fn set_task(&mut self, task: Task) { - let r = unsafe { &*pac::PPI::ptr() }; - r.ch[self.ch.number()] - .tep - .write(|w| unsafe { w.bits(task.0.as_ptr() as u32) }) - } - - /// Sets the event that will trigger the chosen task(s). - pub fn set_event(&mut self, event: Event) { - let r = unsafe { &*pac::PPI::ptr() }; - r.ch[self.ch.number()] - .eep - .write(|w| unsafe { w.bits(event.0.as_ptr() as u32) }) - } -} - -#[cfg(feature = "nrf9160")] -impl<'d, C: ConfigurableChannel> Ppi<'d, C> { - /// Sets the task to be triggered when the configured event occurs. - pub fn set_task(&mut self, _task: Task) { - todo!("Tasks not yet implemented for nrf9160") - } - - /// Sets the event that will trigger the chosen task(s). - pub fn set_event(&mut self, _event: Event) { - todo!("Events not yet implemented for nrf9160") - } -} - -// ====================== -// traits - -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 ()) }) - } -} - -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 ()) }) - } -} - -pub(crate) mod sealed { - pub trait ConfigurableChannel {} - pub trait Channel {} - pub trait Group {} -} - -pub trait Channel: sealed::Channel + Sized { - fn number(&self) -> usize; - fn degrade(self) -> AnyChannel { - AnyChannel { - number: self.number() as u8, - } - } -} -pub trait ConfigurableChannel: Channel + sealed::ConfigurableChannel { - fn degrade_configurable(self) -> AnyConfigurableChannel { - AnyConfigurableChannel { - number: self.number() as u8, - } - } -} - -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, -} -unsafe_impl_unborrow!(AnyChannel); -impl sealed::Channel for AnyChannel {} -impl Channel for AnyChannel { - fn number(&self) -> usize { - self.number as usize - } -} - -pub struct AnyConfigurableChannel { - number: u8, -} -unsafe_impl_unborrow!(AnyConfigurableChannel); -impl sealed::Channel for AnyConfigurableChannel {} -impl sealed::ConfigurableChannel for AnyConfigurableChannel {} -impl ConfigurableChannel for AnyConfigurableChannel {} -impl Channel for AnyConfigurableChannel { - fn number(&self) -> usize { - self.number as usize - } -} - -macro_rules! impl_ppi_channel { - ($type:ident, $number:expr, configurable) => { - impl_ppi_channel!($type, $number); - impl crate::ppi::sealed::ConfigurableChannel for peripherals::$type {} - impl crate::ppi::ConfigurableChannel for peripherals::$type {} - }; - ($type:ident, $number:expr) => { - impl crate::ppi::sealed::Channel for peripherals::$type {} - impl crate::ppi::Channel for peripherals::$type { - fn number(&self) -> usize { - $number - } - } - }; -} - -// ====================== -// 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/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs new file mode 100644 index 000000000..b3676fca4 --- /dev/null +++ b/embassy-nrf/src/ppi/dppi.rs @@ -0,0 +1,74 @@ +use core::marker::PhantomData; + +use embassy::util::Unborrow; +use embassy_hal_common::unborrow; + +use super::{Channel, ConfigurableChannel, Event, Ppi, Task}; + +const DPPI_ENABLE_BIT: u32 = 0x8000_0000; +const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF; + +impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { + pub fn new_one_to_one(ch: impl Unborrow + 'd, event: Event, task: Task) -> Self { + Ppi::new_many_to_many(ch, [event], [task]) + } +} + +impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { + pub fn new_one_to_two( + ch: impl Unborrow + 'd, + event: Event, + task1: Task, + task2: Task, + ) -> Self { + Ppi::new_many_to_many(ch, [event], [task1, task2]) + } +} + +impl<'d, C: ConfigurableChannel, 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 val = DPPI_ENABLE_BIT | (ch.number() as u32 & DPPI_CHANNEL_MASK); + for task in tasks { + if unsafe { task.subscribe_reg().read_volatile() } != 0 { + panic!("Task is already in use"); + } + unsafe { task.subscribe_reg().write_volatile(val) } + } + for event in events { + if unsafe { event.publish_reg().read_volatile() } != 0 { + panic!("Event is already in use"); + } + unsafe { event.publish_reg().write_volatile(val) } + } + + Self { + ch, + events, + tasks, + phantom: PhantomData, + } + } +} + +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(); + + for task in self.tasks { + unsafe { task.subscribe_reg().write_volatile(0) } + } + for event in self.events { + unsafe { event.publish_reg().write_volatile(0) } + } + } +} diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs new file mode 100644 index 000000000..96f867d18 --- /dev/null +++ b/embassy-nrf/src/ppi/mod.rs @@ -0,0 +1,235 @@ +#![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::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, + #[cfg(feature = "_dppi")] + events: [Event; EVENT_COUNT], + #[cfg(feature = "_dppi")] + tasks: [Task; TASK_COUNT], + phantom: PhantomData<&'d mut C>, +} + +impl<'d, C: Channel + 'd, const EVENT_COUNT: usize, const TASK_COUNT: usize> + Ppi<'d, C, EVENT_COUNT, TASK_COUNT> +{ + /// 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()) }); + } +} + +const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::(); + +/// 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 _) }) + } + + pub fn subscribe_reg(&self) -> *mut u32 { + unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) } + } +} + +/// # 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 _) }) + } + + pub fn publish_reg(&self) -> *mut u32 { + unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) } + } +} + +/// # 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; +} + +pub trait ConfigurableChannel: Channel { + fn degrade(self) -> AnyConfigurableChannel; +} + +pub trait StaticChannel: Channel { + fn degrade(self) -> AnyStaticChannel; +} + +pub trait Group: sealed::Group + Sized { + fn number(&self) -> usize; + fn degrade(self) -> AnyGroup { + AnyGroup { + number: self.number() as u8, + } + } +} + +// ====================== +// channels + +/// The any channel can represent any static channel at runtime. +/// This can be used to have fewer generic parameters in some places. +pub struct AnyStaticChannel { + pub(crate) number: u8, +} +unsafe_impl_unborrow!(AnyStaticChannel); +impl sealed::Channel for AnyStaticChannel {} +impl Channel for AnyStaticChannel { + fn number(&self) -> usize { + self.number as usize + } +} +impl StaticChannel for AnyStaticChannel { + fn degrade(self) -> AnyStaticChannel { + self + } +} + +/// The any configurable channel can represent any configurable channel at runtime. +/// This can be used to have fewer generic parameters in some places. +pub struct AnyConfigurableChannel { + pub(crate) number: u8, +} +unsafe_impl_unborrow!(AnyConfigurableChannel); +impl sealed::Channel for AnyConfigurableChannel {} +impl Channel for AnyConfigurableChannel { + fn number(&self) -> usize { + self.number as usize + } +} +impl ConfigurableChannel for AnyConfigurableChannel { + fn degrade(self) -> AnyConfigurableChannel { + self + } +} + +macro_rules! impl_ppi_channel { + ($type:ident, $number:expr) => { + impl crate::ppi::sealed::Channel for peripherals::$type {} + impl crate::ppi::Channel for peripherals::$type { + fn number(&self) -> usize { + $number + } + } + }; + ($type:ident, $number:expr => static) => { + impl_ppi_channel!($type, $number); + impl crate::ppi::StaticChannel for peripherals::$type { + fn degrade(self) -> crate::ppi::AnyStaticChannel { + use crate::ppi::Channel; + crate::ppi::AnyStaticChannel { + number: self.number() as u8, + } + } + } + }; + ($type:ident, $number:expr => configurable) => { + impl_ppi_channel!($type, $number); + impl crate::ppi::ConfigurableChannel for peripherals::$type { + fn degrade(self) -> crate::ppi::AnyConfigurableChannel { + use crate::ppi::Channel; + crate::ppi::AnyConfigurableChannel { + number: self.number() as u8, + } + } + } + }; +} + +// ====================== +// 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/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs new file mode 100644 index 000000000..c1d9794c9 --- /dev/null +++ b/embassy-nrf/src/ppi/ppi.rs @@ -0,0 +1,87 @@ +use core::marker::PhantomData; + +use embassy::util::Unborrow; +use embassy_hal_common::unborrow; + +use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; +use crate::pac; + +impl Task { + fn reg_val(&self) -> u32 { + self.0.as_ptr() as _ + } +} +impl Event { + fn reg_val(&self) -> u32 { + self.0.as_ptr() as _ + } +} + +#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task +impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> { + pub fn new_zero_to_one(ch: impl Unborrow + 'd, task: Task) -> Self { + unborrow!(ch); + + let r = unsafe { &*pac::PPI::ptr() }; + let n = ch.number(); + r.fork[n].tep.write(|w| unsafe { w.bits(task.reg_val()) }); + + Self { + ch, + phantom: PhantomData, + } + } +} + +impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { + pub fn new_one_to_one(ch: impl Unborrow + 'd, event: Event, task: Task) -> Self { + unborrow!(ch); + + let r = unsafe { &*pac::PPI::ptr() }; + let n = ch.number(); + r.ch[n].eep.write(|w| unsafe { w.bits(event.reg_val()) }); + r.ch[n].tep.write(|w| unsafe { w.bits(task.reg_val()) }); + + Self { + ch, + phantom: PhantomData, + } + } +} + +#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task +impl<'d, C: ConfigurableChannel> 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 r = unsafe { &*pac::PPI::ptr() }; + let n = ch.number(); + r.ch[n].eep.write(|w| unsafe { w.bits(event.reg_val()) }); + r.ch[n].tep.write(|w| unsafe { w.bits(task1.reg_val()) }); + r.fork[n].tep.write(|w| unsafe { w.bits(task2.reg_val()) }); + + Self { + ch, + phantom: PhantomData, + } + } +} + +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(); + + let r = unsafe { &*pac::PPI::ptr() }; + let n = self.ch.number(); + r.ch[n].eep.write(|w| unsafe { w.bits(0) }); + r.ch[n].tep.write(|w| unsafe { w.bits(0) }); + r.fork[n].tep.write(|w| unsafe { w.bits(0) }); + } +} diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index 5690ff0d8..9173338b6 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -12,8 +12,7 @@ use embassy_hal_common::unborrow; use futures::future::poll_fn; use crate::pac; -use crate::ppi::Event; -use crate::ppi::Task; +use crate::ppi::{Event, Task}; pub(crate) mod sealed { @@ -319,7 +318,7 @@ 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 { - Task::from_reg(&T::regs().tasks_capture[self.n]) + Task::from_reg(&T::regs().tasks_capture) } /// Returns this CC register's COMPARE event, for use with PPI. diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 63bbe5a77..4bbdec63f 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -7,7 +7,7 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; use embassy::interrupt::InterruptExt; -use embassy::traits::uart::{Error, Read, ReadUntilIdle, Write}; +use embassy::traits::uart::{Error as TraitError, Read, ReadUntilIdle, Write}; use embassy::util::Unborrow; use embassy_hal_common::drop::OnDrop; use embassy_hal_common::unborrow; @@ -219,7 +219,7 @@ impl<'a, T: Instance> Drop for Uarte<'a, T> { impl<'d, T: Instance> Read for Uarte<'d, T> { #[rustfmt::skip] - type ReadFuture<'a> where Self: 'a = impl Future> + 'a; + type ReadFuture<'a> where Self: 'a = impl Future> + 'a; fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { async move { @@ -273,7 +273,7 @@ impl<'d, T: Instance> Read for Uarte<'d, T> { impl<'d, T: Instance> Write for Uarte<'d, T> { #[rustfmt::skip] - type WriteFuture<'a> where Self: 'a = impl Future> + 'a; + type WriteFuture<'a> where Self: 'a = impl Future> + 'a; fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { async move { @@ -331,8 +331,8 @@ 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, AnyConfigurableChannel>, - _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, + ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 2>, + _ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 1>, } impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { @@ -348,8 +348,8 @@ 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, @@ -378,15 +378,19 @@ 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_configurable()); - ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); - ppi_ch1.set_task(timer.task_clear()); - ppi_ch1.set_fork_task(timer.task_start()); + let mut ppi_ch1 = Ppi::new_one_to_two( + ppi_ch1.degrade(), + Event::from_reg(&r.events_rxdrdy), + timer.task_clear(), + timer.task_start(), + ); ppi_ch1.enable(); - let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); - ppi_ch2.set_event(timer.cc(0).event_compare()); - ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); + let mut ppi_ch2 = Ppi::new_one_to_one( + ppi_ch2.degrade(), + timer.cc(0).event_compare(), + Task::from_reg(&r.tasks_stoprx), + ); ppi_ch2.enable(); Self { @@ -400,7 +404,7 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T> { #[rustfmt::skip] - type ReadUntilIdleFuture<'a> where Self: 'a = impl Future> + 'a; + type ReadUntilIdleFuture<'a> where Self: 'a = impl Future> + 'a; fn read_until_idle<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a> { async move { let ptr = rx_buffer.as_ptr(); @@ -460,7 +464,7 @@ impl<'d, U: Instance, T: TimerInstance> ReadUntilIdle for UarteWithIdle<'d, U, T impl<'d, U: Instance, T: TimerInstance> Read for UarteWithIdle<'d, U, T> { #[rustfmt::skip] - type ReadFuture<'a> where Self: 'a = impl Future> + 'a; + type ReadFuture<'a> where Self: 'a = impl Future> + 'a; fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { async move { self.ppi_ch1.disable(); @@ -473,7 +477,7 @@ impl<'d, U: Instance, T: TimerInstance> Read for UarteWithIdle<'d, U, T> { impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> { #[rustfmt::skip] - type WriteFuture<'a> where Self: 'a = impl Future> + 'a; + type WriteFuture<'a> where Self: 'a = impl Future> + 'a; fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { self.uarte.write(tx_buffer) diff --git a/examples/nrf/src/bin/ppi.rs b/examples/nrf/src/bin/ppi.rs index 6ea03ebd0..99246eeda 100644 --- a/examples/nrf/src/bin/ppi.rs +++ b/examples/nrf/src/bin/ppi.rs @@ -51,25 +51,21 @@ async fn main(_spawner: Spawner, p: Peripherals) { OutputChannelPolarity::Toggle, ); - let mut ppi = Ppi::new(p.PPI_CH0); - ppi.set_event(button1.event_in()); - ppi.set_task(led1.task_out()); + 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.set_event(button2.event_in()); - ppi.set_task(led1.task_clr()); + 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.set_event(button3.event_in()); - ppi.set_task(led1.task_set()); + 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.set_event(button4.event_in()); - ppi.set_task(led1.task_out()); - ppi.set_fork_task(led2.task_out()); + 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/saadc_continuous.rs b/examples/nrf/src/bin/saadc_continuous.rs index 149b9c60c..a06a01e91 100644 --- a/examples/nrf/src/bin/saadc_continuous.rs +++ b/examples/nrf/src/bin/saadc_continuous.rs @@ -32,9 +32,7 @@ async fn main(_spawner: Spawner, mut p: Peripherals) { timer.cc(0).write(100); // We want to sample at 10KHz timer.cc(0).short_compare_clear(); - let mut ppi = Ppi::new(p.PPI_CH0); - ppi.set_event(timer.cc(0).event_compare()); - ppi.set_task(saadc.task_sample()); + let mut ppi = Ppi::new_one_to_one(p.PPI_CH0, timer.cc(0).event_compare(), saadc.task_sample()); ppi.enable(); timer.start();