nrf: add PPI channel group driver.

This commit is contained in:
Dario Nieuwenhuis 2023-03-04 05:24:38 +01:00
parent 78d733fc73
commit 4314b823aa
3 changed files with 98 additions and 10 deletions

View file

@ -6,7 +6,7 @@ use crate::{pac, Peripheral};
const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
fn regs() -> &'static pac::dppic::RegisterBlock {
pub(crate) fn regs() -> &'static pac::dppic::RegisterBlock {
unsafe { &*pac::DPPIC::ptr() }
}

View file

@ -17,16 +17,16 @@
use core::ptr::NonNull;
use embassy_hal_common::{impl_peripheral, PeripheralRef};
use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
use crate::{peripherals, Peripheral};
#[cfg(feature = "_dppi")]
mod dppi;
#[cfg(feature = "_ppi")]
mod ppi;
#[cfg_attr(feature = "_dppi", path = "dppi.rs")]
#[cfg_attr(feature = "_ppi", path = "ppi.rs")]
mod _version;
pub(crate) use _version::*;
/// An instance of the Programmable peripheral interconnect on nRF devices.
/// PPI channel driver.
pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> {
ch: PeripheralRef<'d, C>,
#[cfg(feature = "_dppi")]
@ -35,6 +35,88 @@ pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize
tasks: [Task; TASK_COUNT],
}
/// PPI channel group driver.
pub struct PpiGroup<'d, G: Group> {
g: PeripheralRef<'d, G>,
}
impl<'d, G: Group> PpiGroup<'d, G> {
/// Create a new PPI group driver.
///
/// The group is initialized as containing no channels.
pub fn new(g: impl Peripheral<P = G> + 'd) -> Self {
into_ref!(g);
let r = regs();
let n = g.number();
r.chg[n].write(|w| unsafe { w.bits(0) });
Self { g }
}
/// Add a PPI channel to this group.
///
/// If the channel is already in the group, this is a no-op.
pub fn add_channel<C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>(
&mut self,
ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
) {
let r = regs();
let ng = self.g.number();
let nc = ch.ch.number();
r.chg[ng].modify(|r, w| unsafe { w.bits(r.bits() | 1 << nc) });
}
/// Remove a PPI channel from this group.
///
/// If the channel is already not in the group, this is a no-op.
pub fn remove_channel<C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>(
&mut self,
ch: &Ppi<'_, C, EVENT_COUNT, TASK_COUNT>,
) {
let r = regs();
let ng = self.g.number();
let nc = ch.ch.number();
r.chg[ng].modify(|r, w| unsafe { w.bits(r.bits() & !(1 << nc)) });
}
/// Enable all the channels in this group.
pub fn enable_all(&mut self) {
let n = self.g.number();
regs().tasks_chg[n].en.write(|w| unsafe { w.bits(1) });
}
/// Disable all the channels in this group.
pub fn disable_all(&mut self) {
let n = self.g.number();
regs().tasks_chg[n].dis.write(|w| unsafe { w.bits(1) });
}
/// Get a reference to the "enable all" task.
///
/// When triggered, it will enable all the channels in this group.
pub fn task_enable_all(&self) -> Task {
let n = self.g.number();
Task::from_reg(&regs().tasks_chg[n].en)
}
/// Get a reference to the "disable all" task.
///
/// When triggered, it will disable all the channels in this group.
pub fn task_disable_all(&self) -> Task {
let n = self.g.number();
Task::from_reg(&regs().tasks_chg[n].dis)
}
}
impl<'d, G: Group> Drop for PpiGroup<'d, G> {
fn drop(&mut self) {
let r = regs();
let n = self.g.number();
r.chg[n].write(|w| unsafe { w.bits(0) });
}
}
#[cfg(feature = "_dppi")]
const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
@ -112,7 +194,7 @@ pub(crate) mod sealed {
}
/// Interface for PPI channels.
pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized {
pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized + 'static {
/// Returns the number of the channel
fn number(&self) -> usize;
}
@ -130,7 +212,7 @@ pub trait StaticChannel: Channel + Into<AnyStaticChannel> {
}
/// Interface for a group of PPI channels.
pub trait Group: sealed::Group + Sized {
pub trait Group: sealed::Group + Peripheral<P = Self> + Into<AnyGroup> + Sized + 'static {
/// Returns the number of the group.
fn number(&self) -> usize;
/// Convert into a type erased group.
@ -248,6 +330,12 @@ macro_rules! impl_group {
$number
}
}
impl From<peripherals::$type> for crate::ppi::AnyGroup {
fn from(val: peripherals::$type) -> Self {
crate::ppi::Group::degrade(val)
}
}
};
}

View file

@ -14,7 +14,7 @@ impl Event {
}
}
fn regs() -> &'static pac::ppi::RegisterBlock {
pub(crate) fn regs() -> &'static pac::ppi::RegisterBlock {
unsafe { &*pac::PPI::ptr() }
}