nrf: add PPI channel group driver.
This commit is contained in:
parent
78d733fc73
commit
4314b823aa
@ -6,7 +6,7 @@ use crate::{pac, Peripheral};
|
|||||||
const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
|
const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
|
||||||
const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
|
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() }
|
unsafe { &*pac::DPPIC::ptr() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,16 +17,16 @@
|
|||||||
|
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
|
|
||||||
use embassy_hal_common::{impl_peripheral, PeripheralRef};
|
use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
|
||||||
|
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{peripherals, Peripheral};
|
||||||
|
|
||||||
#[cfg(feature = "_dppi")]
|
#[cfg_attr(feature = "_dppi", path = "dppi.rs")]
|
||||||
mod dppi;
|
#[cfg_attr(feature = "_ppi", path = "ppi.rs")]
|
||||||
#[cfg(feature = "_ppi")]
|
mod _version;
|
||||||
mod ppi;
|
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> {
|
pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> {
|
||||||
ch: PeripheralRef<'d, C>,
|
ch: PeripheralRef<'d, C>,
|
||||||
#[cfg(feature = "_dppi")]
|
#[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],
|
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(®s().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(®s().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")]
|
#[cfg(feature = "_dppi")]
|
||||||
const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
|
const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
|
||||||
|
|
||||||
@ -112,7 +194,7 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Interface for PPI channels.
|
/// 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
|
/// Returns the number of the channel
|
||||||
fn number(&self) -> usize;
|
fn number(&self) -> usize;
|
||||||
}
|
}
|
||||||
@ -130,7 +212,7 @@ pub trait StaticChannel: Channel + Into<AnyStaticChannel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Interface for a group of PPI channels.
|
/// 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.
|
/// Returns the number of the group.
|
||||||
fn number(&self) -> usize;
|
fn number(&self) -> usize;
|
||||||
/// Convert into a type erased group.
|
/// Convert into a type erased group.
|
||||||
@ -248,6 +330,12 @@ macro_rules! impl_group {
|
|||||||
$number
|
$number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<peripherals::$type> for crate::ppi::AnyGroup {
|
||||||
|
fn from(val: peripherals::$type) -> Self {
|
||||||
|
crate::ppi::Group::degrade(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ impl Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regs() -> &'static pac::ppi::RegisterBlock {
|
pub(crate) fn regs() -> &'static pac::ppi::RegisterBlock {
|
||||||
unsafe { &*pac::PPI::ptr() }
|
unsafe { &*pac::PPI::ptr() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user