diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs index 14c3f9b1a..b51b0c93e 100644 --- a/embassy-nrf/src/chips/nrf52805.rs +++ b/embassy-nrf/src/chips/nrf52805.rs @@ -132,6 +132,10 @@ embassy_hal_internal::peripherals! { // Radio RADIO, + + // EGU + EGU0, + EGU1, } impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); @@ -214,6 +218,9 @@ impl_saadc_input!(P0_05, ANALOG_INPUT3); impl_radio!(RADIO, RADIO, RADIO); +impl_egu!(EGU0, EGU0, SWI0_EGU0); +impl_egu!(EGU1, EGU1, SWI1_EGU1); + embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index c607586db..273098d9b 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -138,6 +138,10 @@ embassy_hal_internal::peripherals! { // Radio RADIO, + + // EGU + EGU0, + EGU1, } impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); @@ -240,6 +244,9 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_radio!(RADIO, RADIO, RADIO); +impl_egu!(EGU0, EGU0, SWI0_EGU0); +impl_egu!(EGU1, EGU1, SWI1_EGU1); + embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index 5f70365b4..9bce38636 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -138,6 +138,10 @@ embassy_hal_internal::peripherals! { // Radio RADIO, + + // EGU + EGU0, + EGU1, } impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); @@ -242,6 +246,9 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_radio!(RADIO, RADIO, RADIO); +impl_egu!(EGU0, EGU0, SWI0_EGU0); +impl_egu!(EGU1, EGU1, SWI1_EGU1); + embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs index 82d097407..2acae2c8f 100644 --- a/embassy-nrf/src/chips/nrf52820.rs +++ b/embassy-nrf/src/chips/nrf52820.rs @@ -133,6 +133,14 @@ embassy_hal_internal::peripherals! { // Radio RADIO, + + // EGU + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, } impl_usb!(USBD, USBD, USBD); @@ -229,6 +237,13 @@ impl_ppi_channel!(PPI_CH31, 31 => static); impl_radio!(RADIO, RADIO, RADIO); +impl_egu!(EGU0, EGU0, SWI0_EGU0); +impl_egu!(EGU1, EGU1, SWI1_EGU1); +impl_egu!(EGU2, EGU2, SWI2_EGU2); +impl_egu!(EGU3, EGU3, SWI3_EGU3); +impl_egu!(EGU4, EGU4, SWI4_EGU4); +impl_egu!(EGU5, EGU5, SWI5_EGU5); + embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index 67b32fe5f..94b373ab3 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -153,6 +153,14 @@ embassy_hal_internal::peripherals! { // Radio RADIO, + + // EGU + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, } impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); @@ -269,6 +277,13 @@ impl_i2s!(I2S, I2S, I2S); impl_radio!(RADIO, RADIO, RADIO); +impl_egu!(EGU0, EGU0, SWI0_EGU0); +impl_egu!(EGU1, EGU1, SWI1_EGU1); +impl_egu!(EGU2, EGU2, SWI2_EGU2); +impl_egu!(EGU3, EGU3, SWI3_EGU3); +impl_egu!(EGU4, EGU4, SWI4_EGU4); +impl_egu!(EGU5, EGU5, SWI5_EGU5); + embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index 20f14e2d6..09cde1ac1 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -173,6 +173,14 @@ embassy_hal_internal::peripherals! { // Radio RADIO, + + // EGU + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, } impl_usb!(USBD, USBD, USBD); @@ -311,6 +319,13 @@ impl_i2s!(I2S, I2S, I2S); impl_radio!(RADIO, RADIO, RADIO); +impl_egu!(EGU0, EGU0, SWI0_EGU0); +impl_egu!(EGU1, EGU1, SWI1_EGU1); +impl_egu!(EGU2, EGU2, SWI2_EGU2); +impl_egu!(EGU3, EGU3, SWI3_EGU3); +impl_egu!(EGU4, EGU4, SWI4_EGU4); +impl_egu!(EGU5, EGU5, SWI5_EGU5); + embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index d3272b2e8..0f3d1b250 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -176,6 +176,14 @@ embassy_hal_internal::peripherals! { // Radio RADIO, + + // EGU + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, } impl_usb!(USBD, USBD, USBD); @@ -316,6 +324,13 @@ impl_i2s!(I2S, I2S, I2S); impl_radio!(RADIO, RADIO, RADIO); +impl_egu!(EGU0, EGU0, SWI0_EGU0); +impl_egu!(EGU1, EGU1, SWI1_EGU1); +impl_egu!(EGU2, EGU2, SWI2_EGU2); +impl_egu!(EGU3, EGU3, SWI3_EGU3); +impl_egu!(EGU4, EGU4, SWI4_EGU4); +impl_egu!(EGU5, EGU5, SWI5_EGU5); + embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs index 62c74bb6f..584f6e43c 100644 --- a/embassy-nrf/src/chips/nrf5340_app.rs +++ b/embassy-nrf/src/chips/nrf5340_app.rs @@ -380,6 +380,14 @@ embassy_hal_internal::peripherals! { P1_13, P1_14, P1_15, + + // EGU + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, } impl_usb!(USBD, USBD, USBD); @@ -519,6 +527,13 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5); impl_saadc_input!(P0_19, ANALOG_INPUT6); impl_saadc_input!(P0_20, ANALOG_INPUT7); +impl_egu!(EGU0, EGU0, EGU0); +impl_egu!(EGU1, EGU1, EGU1); +impl_egu!(EGU2, EGU2, EGU2); +impl_egu!(EGU3, EGU3, EGU3); +impl_egu!(EGU4, EGU4, EGU4); +impl_egu!(EGU5, EGU5, EGU5); + embassy_hal_internal::interrupt_mod!( FPU, CACHE, diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs index 65e8f9653..d772c9a49 100644 --- a/embassy-nrf/src/chips/nrf5340_net.rs +++ b/embassy-nrf/src/chips/nrf5340_net.rs @@ -251,6 +251,9 @@ embassy_hal_internal::peripherals! { // Radio RADIO, + + // EGU + EGU0, } impl_uarte!(SERIAL0, UARTE0, SERIAL0); @@ -350,6 +353,8 @@ impl_ppi_channel!(PPI_CH31, 31 => configurable); impl_radio!(RADIO, RADIO, RADIO); +impl_egu!(EGU0, EGU0, EGU0); + embassy_hal_internal::interrupt_mod!( CLOCK_POWER, RADIO, diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs index 8b1356ef8..8107ca175 100644 --- a/embassy-nrf/src/chips/nrf9160.rs +++ b/embassy-nrf/src/chips/nrf9160.rs @@ -283,6 +283,14 @@ embassy_hal_internal::peripherals! { // PDM PDM, + + // EGU + EGU0, + EGU1, + EGU2, + EGU3, + EGU4, + EGU5, } impl_uarte!(SERIAL0, UARTE0, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0); @@ -380,6 +388,13 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5); impl_saadc_input!(P0_19, ANALOG_INPUT6); impl_saadc_input!(P0_20, ANALOG_INPUT7); +impl_egu!(EGU0, EGU0, EGU0); +impl_egu!(EGU1, EGU1, EGU1); +impl_egu!(EGU2, EGU2, EGU2); +impl_egu!(EGU3, EGU3, EGU3); +impl_egu!(EGU4, EGU4, EGU4); +impl_egu!(EGU5, EGU5, EGU5); + embassy_hal_internal::interrupt_mod!( SPU, CLOCK_POWER, diff --git a/embassy-nrf/src/egu.rs b/embassy-nrf/src/egu.rs new file mode 100644 index 000000000..c0cde8330 --- /dev/null +++ b/embassy-nrf/src/egu.rs @@ -0,0 +1,103 @@ +//! EGU driver. +//! +//! The event generator driver provides a higher level API for task triggering +//! and events to use with PPI. + +#![macro_use] + +use core::marker::PhantomData; + +use embassy_hal_internal::into_ref; + +use crate::ppi::{Event, Task}; +use crate::{interrupt, pac, Peripheral, PeripheralRef}; + +/// An instance of the EGU. +pub struct Egu<'d, T: Instance> { + _p: PeripheralRef<'d, T>, +} + +impl<'d, T: Instance> Egu<'d, T> { + /// Create a new EGU instance. + pub fn new(_p: impl Peripheral
+ 'd) -> Self { + into_ref!(_p); + Self { _p } + } + + /// Get a handle to a trigger for the EGU. + pub fn trigger(&mut self, number: TriggerNumber) -> Trigger<'d, T> { + Trigger { + number, + _p: PhantomData, + } + } +} + +pub(crate) trait SealedInstance { + fn regs() -> &'static pac::egu0::RegisterBlock; +} + +/// Basic Egu instance. +#[allow(private_bounds)] +pub trait Instance: Peripheral
+ SealedInstance + 'static + Send {
+ /// Interrupt for this peripheral.
+ type Interrupt: interrupt::typelevel::Interrupt;
+}
+
+macro_rules! impl_egu {
+ ($type:ident, $pac_type:ident, $irq:ident) => {
+ impl crate::egu::SealedInstance for peripherals::$type {
+ fn regs() -> &'static pac::egu0::RegisterBlock {
+ unsafe { &*pac::$pac_type::ptr() }
+ }
+ }
+ impl crate::egu::Instance for peripherals::$type {
+ type Interrupt = crate::interrupt::typelevel::$irq;
+ }
+ };
+}
+
+/// Represents a trigger within the EGU.
+pub struct Trigger<'d, T: Instance> {
+ number: TriggerNumber,
+ _p: PhantomData<&'d T>,
+}
+
+impl<'d, T: Instance> Trigger<'d, T> {
+ /// Get task for this trigger to use with PPI.
+ pub fn task(&self) -> Task<'d> {
+ let nr = self.number as usize;
+ let regs = T::regs();
+ Task::from_reg(®s.tasks_trigger[nr])
+ }
+
+ /// Get event for this trigger to use with PPI.
+ pub fn event(&self) -> Event<'d> {
+ let nr = self.number as usize;
+ let regs = T::regs();
+ Event::from_reg(®s.events_triggered[nr])
+ }
+}
+
+/// Represents a trigger within an EGU.
+#[allow(missing_docs)]
+#[derive(Clone, Copy, PartialEq)]
+#[repr(u8)]
+pub enum TriggerNumber {
+ Trigger0 = 0,
+ Trigger1 = 1,
+ Trigger2 = 2,
+ Trigger3 = 3,
+ Trigger4 = 4,
+ Trigger5 = 5,
+ Trigger6 = 6,
+ Trigger7 = 7,
+ Trigger8 = 8,
+ Trigger9 = 9,
+ Trigger10 = 10,
+ Trigger11 = 11,
+ Trigger12 = 12,
+ Trigger13 = 13,
+ Trigger14 = 14,
+ Trigger15 = 15,
+}
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 3457dd933..05b52f687 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -50,6 +50,8 @@ pub mod gpiote;
#[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340-app")))]
pub mod radio;
+#[cfg(not(feature = "nrf51"))]
+pub mod egu;
#[cfg(any(feature = "nrf52832", feature = "nrf52833", feature = "nrf52840"))]
pub mod i2s;
pub mod nvmc;
diff --git a/examples/nrf52840/src/bin/egu.rs b/examples/nrf52840/src/bin/egu.rs
new file mode 100644
index 000000000..8bf712697
--- /dev/null
+++ b/examples/nrf52840/src/bin/egu.rs
@@ -0,0 +1,43 @@
+//! This example shows the use of the EGU peripheral combined with PPI.
+//!
+//! It chains events from button -> egu0-trigger0 -> egu0-trigger1 -> led
+#![no_std]
+#![no_main]
+
+use embassy_executor::Spawner;
+use embassy_nrf::egu::{Egu, TriggerNumber};
+use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pull};
+use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity, OutputChannel, OutputChannelPolarity};
+use embassy_nrf::peripherals::{PPI_CH0, PPI_CH1, PPI_CH2};
+use embassy_nrf::ppi::Ppi;
+use embassy_time::{Duration, Timer};
+use {defmt_rtt as _, panic_probe as _};
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+ let p = embassy_nrf::init(Default::default());
+
+ let led1 = Output::new(p.P0_13, Level::High, OutputDrive::Standard);
+ let btn1 = Input::new(p.P0_11, Pull::Up);
+
+ let mut egu1 = Egu::new(p.EGU0);
+ let led1 = OutputChannel::new(p.GPIOTE_CH0, led1, OutputChannelPolarity::Toggle);
+ let btn1 = InputChannel::new(p.GPIOTE_CH1, btn1, InputChannelPolarity::LoToHi);
+
+ let trigger0 = egu1.trigger(TriggerNumber::Trigger0);
+ let trigger1 = egu1.trigger(TriggerNumber::Trigger1);
+
+ let mut ppi1: Ppi