mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-21 22:32:29 +00:00
Merge pull request #3091 from embassy-rs/nrf-egu-peri
add HAL and example for using nRF EGU peripheral
This commit is contained in:
commit
a0231ed74c
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
103
embassy-nrf/src/egu.rs
Normal file
103
embassy-nrf/src/egu.rs
Normal file
@ -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<P = T> + '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<P = Self> + 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,
|
||||
}
|
@ -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;
|
||||
|
43
examples/nrf52840/src/bin/egu.rs
Normal file
43
examples/nrf52840/src/bin/egu.rs
Normal file
@ -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<PPI_CH0, 1, 1> = Ppi::new_one_to_one(p.PPI_CH0, btn1.event_in(), trigger0.task());
|
||||
ppi1.enable();
|
||||
|
||||
let mut ppi2: Ppi<PPI_CH1, 1, 1> = Ppi::new_one_to_one(p.PPI_CH1, trigger0.event(), trigger1.task());
|
||||
ppi2.enable();
|
||||
|
||||
let mut ppi3: Ppi<PPI_CH2, 1, 1> = Ppi::new_one_to_one(p.PPI_CH2, trigger1.event(), led1.task_out());
|
||||
ppi3.enable();
|
||||
|
||||
defmt::info!("Push the button to toggle the LED");
|
||||
loop {
|
||||
Timer::after(Duration::from_secs(60)).await;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user