From 26705ec32862a00e79cf334019aa3fbd4596bf17 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 27 Mar 2021 04:40:05 +0100 Subject: [PATCH] nrf/ppi: add peris and traits --- embassy-nrf/src/lib.rs | 48 ++++++++++++++ embassy-nrf/src/ppi.rs | 143 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 embassy-nrf/src/ppi.rs diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 9e5132c5..1bcaf548 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -97,6 +97,7 @@ pub mod buffered_uarte; pub mod gpio; pub mod gpiote; pub mod interrupt; +pub mod ppi; #[cfg(feature = "52840")] pub mod qspi; pub mod rtc; @@ -145,6 +146,53 @@ embassy_extras::peripherals! { GPIOTE_CH6, GPIOTE_CH7, + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + #[cfg(not(feature = "51"))] + PPI_CH16, + #[cfg(not(feature = "51"))] + PPI_CH17, + #[cfg(not(feature = "51"))] + PPI_CH18, + #[cfg(not(feature = "51"))] + PPI_CH19, + PPI_CH20, + PPI_CH21, + PPI_CH22, + PPI_CH23, + PPI_CH24, + PPI_CH25, + PPI_CH26, + PPI_CH27, + PPI_CH28, + PPI_CH29, + PPI_CH30, + PPI_CH31, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + #[cfg(not(feature = "51"))] + PPI_GROUP4, + #[cfg(not(feature = "51"))] + PPI_GROUP5, + // GPIO port 0 P0_00, P0_01, diff --git a/embassy-nrf/src/ppi.rs b/embassy-nrf/src/ppi.rs new file mode 100644 index 00000000..c06b212c --- /dev/null +++ b/embassy-nrf/src/ppi.rs @@ -0,0 +1,143 @@ +//! 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 embassy_extras::impl_unborrow; + +use crate::peripherals; + +// ====================== +// traits + +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 {} + +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, +} +impl_unborrow!(AnyChannel); +impl sealed::Channel for AnyChannel {} +impl Channel for AnyChannel { + fn number(&self) -> usize { + self.number as usize + } +} + +macro_rules! impl_channel { + ($type:ident, $number:expr, configurable) => { + impl_channel!($type, $number); + impl sealed::ConfigurableChannel for peripherals::$type {} + impl ConfigurableChannel for peripherals::$type {} + }; + ($type:ident, $number:expr) => { + impl sealed::Channel for peripherals::$type {} + impl Channel for peripherals::$type { + fn number(&self) -> usize { + $number + } + } + }; +} + +impl_channel!(PPI_CH0, 0, configurable); +impl_channel!(PPI_CH1, 1, configurable); +impl_channel!(PPI_CH2, 2, configurable); +impl_channel!(PPI_CH3, 3, configurable); +impl_channel!(PPI_CH4, 4, configurable); +impl_channel!(PPI_CH5, 5, configurable); +impl_channel!(PPI_CH6, 6, configurable); +impl_channel!(PPI_CH7, 7, configurable); +impl_channel!(PPI_CH8, 8, configurable); +impl_channel!(PPI_CH9, 9, configurable); +impl_channel!(PPI_CH10, 10, configurable); +impl_channel!(PPI_CH11, 11, configurable); +impl_channel!(PPI_CH12, 12, configurable); +impl_channel!(PPI_CH13, 13, configurable); +impl_channel!(PPI_CH14, 14, configurable); +impl_channel!(PPI_CH15, 15, configurable); +#[cfg(not(feature = "51"))] +impl_channel!(PPI_CH16, 16, configurable); +#[cfg(not(feature = "51"))] +impl_channel!(PPI_CH17, 17, configurable); +#[cfg(not(feature = "51"))] +impl_channel!(PPI_CH18, 18, configurable); +#[cfg(not(feature = "51"))] +impl_channel!(PPI_CH19, 19, configurable); +impl_channel!(PPI_CH20, 20); +impl_channel!(PPI_CH21, 21); +impl_channel!(PPI_CH22, 22); +impl_channel!(PPI_CH23, 23); +impl_channel!(PPI_CH24, 24); +impl_channel!(PPI_CH25, 25); +impl_channel!(PPI_CH26, 26); +impl_channel!(PPI_CH27, 27); +impl_channel!(PPI_CH28, 28); +impl_channel!(PPI_CH29, 29); +impl_channel!(PPI_CH30, 30); +impl_channel!(PPI_CH31, 31); + +// ====================== +// groups + +pub struct AnyGroup { + number: u8, +} +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 = "51"))] +impl_group!(PPI_GROUP4, 4); +#[cfg(not(feature = "51"))] +impl_group!(PPI_GROUP5, 5);