- Interconnect is now PPI again
- Scary pointer math is now contained in the tasks and events - ppi now sets the tasks and events immediately and the struct is now zero-sized - StaticToOne is renamed to ZeroToOne - Used DPPI tasks and events now panic when enabled twice
This commit is contained in:
parent
531dfcffb3
commit
a6c84cb915
@ -14,8 +14,8 @@ use embassy_hal_common::{low_power_wait_until, unborrow};
|
|||||||
|
|
||||||
use crate::gpio::sealed::Pin as _;
|
use crate::gpio::sealed::Pin as _;
|
||||||
use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin};
|
use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin};
|
||||||
use crate::interconnect::{AnyChannel, Event, OneToOneChannel, OneToTwoChannel, Ppi, Task};
|
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
|
use crate::ppi::{AnyChannel, Event, OneToOneChannel, OneToTwoChannel, Ppi, Task};
|
||||||
use crate::timer::Instance as TimerInstance;
|
use crate::timer::Instance as TimerInstance;
|
||||||
use crate::timer::{Frequency, Timer};
|
use crate::timer::{Frequency, Timer};
|
||||||
use crate::uarte::{Config, Instance as UarteInstance};
|
use crate::uarte::{Config, Instance as UarteInstance};
|
||||||
|
@ -11,8 +11,8 @@ use futures::future::poll_fn;
|
|||||||
|
|
||||||
use crate::gpio::sealed::Pin as _;
|
use crate::gpio::sealed::Pin as _;
|
||||||
use crate::gpio::{AnyPin, Input, Output, Pin as GpioPin};
|
use crate::gpio::{AnyPin, Input, Output, Pin as GpioPin};
|
||||||
use crate::interconnect::{Event, Task};
|
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
|
use crate::ppi::{Event, Task};
|
||||||
use crate::{interrupt, peripherals};
|
use crate::{interrupt, peripherals};
|
||||||
|
|
||||||
pub const CHANNEL_COUNT: usize = 8;
|
pub const CHANNEL_COUNT: usize = 8;
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
use super::{Channel, Event, Ppi, Task};
|
|
||||||
|
|
||||||
const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
|
|
||||||
const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
|
|
||||||
const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
|
|
||||||
|
|
||||||
impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>
|
|
||||||
Ppi<'d, C, EVENT_COUNT, TASK_COUNT>
|
|
||||||
{
|
|
||||||
pub(super) fn enable_task(task: &Task, channel: &C, _index: usize) {
|
|
||||||
unsafe {
|
|
||||||
task.0
|
|
||||||
.as_ptr()
|
|
||||||
.add(REGISTER_DPPI_CONFIG_OFFSET)
|
|
||||||
.write_volatile(DPPI_ENABLE_BIT | (channel.number() as u32 & DPPI_CHANNEL_MASK));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn disable_task(task: &Task, _channel: &C, _index: usize) {
|
|
||||||
unsafe {
|
|
||||||
task.0
|
|
||||||
.as_ptr()
|
|
||||||
.add(REGISTER_DPPI_CONFIG_OFFSET)
|
|
||||||
.write_volatile(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn enable_event(event: &Event, channel: &C, _index: usize) {
|
|
||||||
unsafe {
|
|
||||||
event
|
|
||||||
.0
|
|
||||||
.as_ptr()
|
|
||||||
.add(REGISTER_DPPI_CONFIG_OFFSET)
|
|
||||||
.write_volatile(DPPI_ENABLE_BIT | (channel.number() as u32 & DPPI_CHANNEL_MASK));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn disable_event(event: &Event, _channel: &C, _index: usize) {
|
|
||||||
unsafe {
|
|
||||||
event
|
|
||||||
.0
|
|
||||||
.as_ptr()
|
|
||||||
.add(REGISTER_DPPI_CONFIG_OFFSET)
|
|
||||||
.write_volatile(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
use super::{Channel, Event, Ppi, Task};
|
|
||||||
use crate::pac;
|
|
||||||
|
|
||||||
impl<'d, C: Channel + 'd, const EVENT_COUNT: usize, const TASK_COUNT: usize>
|
|
||||||
Ppi<'d, C, EVENT_COUNT, TASK_COUNT>
|
|
||||||
{
|
|
||||||
pub(super) fn enable_task(task: &Task, channel: &C, index: usize) {
|
|
||||||
match (index, channel.is_task_configurable()) {
|
|
||||||
(0, false) => Self::set_fork_task(Some(task), channel.number()), // Static channel with fork
|
|
||||||
(0, true) => Self::set_main_task(Some(task), channel.number()), // Configurable channel without fork
|
|
||||||
(1, true) => Self::set_fork_task(Some(task), channel.number()), // Configurable channel with fork
|
|
||||||
_ => unreachable!("{}, {}", index, channel.is_task_configurable()), // Not available with the PPI, so should not be constructable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn disable_task(_task: &Task, channel: &C, index: usize) {
|
|
||||||
match (index, channel.is_task_configurable()) {
|
|
||||||
(0, false) => Self::set_fork_task(None, channel.number()), // Static channel with fork
|
|
||||||
(0, true) => Self::set_main_task(None, channel.number()), // Configurable channel without fork
|
|
||||||
(1, true) => Self::set_fork_task(None, channel.number()), // Configurable channel with fork
|
|
||||||
_ => unreachable!(), // Not available with the PPI, so should not be constructable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn enable_event(event: &Event, channel: &C, _index: usize) {
|
|
||||||
Self::set_event(Some(event), channel.number())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn disable_event(_event: &Event, channel: &C, _index: usize) {
|
|
||||||
Self::set_event(None, channel.number())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_main_task(task: Option<&Task>, channel: usize) {
|
|
||||||
let r = unsafe { &*pac::PPI::ptr() };
|
|
||||||
if let Some(task) = task {
|
|
||||||
r.ch[channel]
|
|
||||||
.tep
|
|
||||||
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
|
|
||||||
} else {
|
|
||||||
r.ch[channel].tep.write(|w| unsafe { w.bits(0) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_fork_task(task: Option<&Task>, channel: usize) {
|
|
||||||
let r = unsafe { &*pac::PPI::ptr() };
|
|
||||||
if let Some(task) = task {
|
|
||||||
r.fork[channel]
|
|
||||||
.tep
|
|
||||||
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
|
|
||||||
} else {
|
|
||||||
r.fork[channel].tep.write(|w| unsafe { w.bits(0) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_event(event: Option<&Event>, channel: usize) {
|
|
||||||
let r = unsafe { &*pac::PPI::ptr() };
|
|
||||||
if let Some(event) = event {
|
|
||||||
r.ch[channel]
|
|
||||||
.eep
|
|
||||||
.write(|w| unsafe { w.bits(event.0.as_ptr() as u32) })
|
|
||||||
} else {
|
|
||||||
r.ch[channel].eep.write(|w| unsafe { w.bits(0) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -31,7 +31,7 @@ pub mod gpio;
|
|||||||
pub mod gpiote;
|
pub mod gpiote;
|
||||||
#[cfg(not(feature = "nrf9160"))]
|
#[cfg(not(feature = "nrf9160"))]
|
||||||
pub mod nvmc;
|
pub mod nvmc;
|
||||||
pub mod interconnect;
|
pub mod ppi;
|
||||||
#[cfg(not(any(feature = "nrf52805", feature = "nrf52820")))]
|
#[cfg(not(any(feature = "nrf52805", feature = "nrf52820")))]
|
||||||
pub mod pwm;
|
pub mod pwm;
|
||||||
#[cfg(feature = "nrf52840")]
|
#[cfg(feature = "nrf52840")]
|
||||||
|
61
embassy-nrf/src/ppi/dppi.rs
Normal file
61
embassy-nrf/src/ppi/dppi.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use super::{Channel, Event, Ppi, Task};
|
||||||
|
|
||||||
|
const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
|
||||||
|
const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
|
||||||
|
|
||||||
|
impl<'d, C: Channel + 'd, const EVENT_COUNT: usize, const TASK_COUNT: usize>
|
||||||
|
Ppi<'d, C, EVENT_COUNT, TASK_COUNT>
|
||||||
|
{
|
||||||
|
pub(super) fn enable_task(task: &Task, channel: &C, _index: usize) {
|
||||||
|
unsafe {
|
||||||
|
if task.subscribe_reg().read_volatile() != 0 {
|
||||||
|
panic!("Task is already in use");
|
||||||
|
}
|
||||||
|
task.subscribe_reg()
|
||||||
|
.write_volatile(DPPI_ENABLE_BIT | (channel.number() as u32 & DPPI_CHANNEL_MASK));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn disable_task(task: &Task, _channel: &C, _index: usize) {
|
||||||
|
unsafe {
|
||||||
|
task.subscribe_reg().write_volatile(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn enable_event(event: &Event, channel: &C, _index: usize) {
|
||||||
|
unsafe {
|
||||||
|
if event.publish_reg().read_volatile() != 0 {
|
||||||
|
panic!("Task is already in use");
|
||||||
|
}
|
||||||
|
event
|
||||||
|
.publish_reg()
|
||||||
|
.write_volatile(DPPI_ENABLE_BIT | (channel.number() as u32 & DPPI_CHANNEL_MASK));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn disable_event(event: &Event, _channel: &C, _index: usize) {
|
||||||
|
unsafe {
|
||||||
|
event.publish_reg().write_volatile(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables all tasks and events
|
||||||
|
pub(super) fn enable_all(tasks: &[Task], events: &[Event], channel: &C) {
|
||||||
|
for (index, task) in tasks.iter().enumerate() {
|
||||||
|
Self::enable_task(task, channel, index);
|
||||||
|
}
|
||||||
|
for (index, event) in events.iter().enumerate() {
|
||||||
|
Self::enable_event(event, channel, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable all tasks and events
|
||||||
|
pub(super) fn disable_all(&self) {
|
||||||
|
for (index, task) in self.tasks.iter().enumerate() {
|
||||||
|
Self::disable_task(task, &self.ch, index);
|
||||||
|
}
|
||||||
|
for (index, event) in self.events.iter().enumerate() {
|
||||||
|
Self::disable_event(event, &self.ch, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,12 +28,14 @@ mod ppi;
|
|||||||
|
|
||||||
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: C,
|
ch: C,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
events: [Event; EVENT_COUNT],
|
events: [Event; EVENT_COUNT],
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
tasks: [Task; TASK_COUNT],
|
tasks: [Task; TASK_COUNT],
|
||||||
phantom: PhantomData<&'d mut C>,
|
phantom: PhantomData<&'d mut C>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>
|
impl<'d, C: Channel + 'd, const EVENT_COUNT: usize, const TASK_COUNT: usize>
|
||||||
Ppi<'d, C, EVENT_COUNT, TASK_COUNT>
|
Ppi<'d, C, EVENT_COUNT, TASK_COUNT>
|
||||||
{
|
{
|
||||||
pub fn degrade(self) -> Ppi<'d, AnyChannel, EVENT_COUNT, TASK_COUNT> {
|
pub fn degrade(self) -> Ppi<'d, AnyChannel, EVENT_COUNT, TASK_COUNT> {
|
||||||
@ -43,7 +45,9 @@ impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>
|
|||||||
#[cfg(feature = "_ppi")]
|
#[cfg(feature = "_ppi")]
|
||||||
has_configurable_task: self.ch.is_task_configurable(),
|
has_configurable_task: self.ch.is_task_configurable(),
|
||||||
},
|
},
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
events: self.events,
|
events: self.events,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
tasks: self.tasks,
|
tasks: self.tasks,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
@ -62,26 +66,6 @@ impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize>
|
|||||||
r.chenclr
|
r.chenclr
|
||||||
.write(|w| unsafe { w.bits(1 << self.ch.number()) });
|
.write(|w| unsafe { w.bits(1 << self.ch.number()) });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables all tasks and events
|
|
||||||
fn enable_all(&self) {
|
|
||||||
for (index, task) in self.tasks.iter().enumerate() {
|
|
||||||
Self::enable_task(task, &self.ch, index);
|
|
||||||
}
|
|
||||||
for (index, event) in self.events.iter().enumerate() {
|
|
||||||
Self::enable_event(event, &self.ch, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Disable all tasks and events
|
|
||||||
fn disable_all(&self) {
|
|
||||||
for (index, task) in self.tasks.iter().enumerate() {
|
|
||||||
Self::disable_task(task, &self.ch, index);
|
|
||||||
}
|
|
||||||
for (index, event) in self.events.iter().enumerate() {
|
|
||||||
Self::disable_event(event, &self.ch, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Drop
|
impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Drop
|
||||||
@ -93,19 +77,23 @@ impl<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> Drop
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, C: StaticToOneChannel> Ppi<'d, C, 0, 1> {
|
impl<'d, C: ZeroToOneChannel> Ppi<'d, C, 0, 1> {
|
||||||
pub fn new_static_to_one(ch: impl Unborrow<Target = C> + 'd, task: Task) -> Self {
|
pub fn new_static_to_one(ch: impl Unborrow<Target = C> + 'd, task: Task) -> Self {
|
||||||
unborrow!(ch);
|
unborrow!(ch);
|
||||||
|
|
||||||
let s = Self {
|
let events = [];
|
||||||
ch,
|
let tasks = [task];
|
||||||
events: [],
|
|
||||||
tasks: [task],
|
|
||||||
phantom: PhantomData,
|
|
||||||
};
|
|
||||||
|
|
||||||
s.enable_all();
|
Self::enable_all(&tasks, &events, &ch);
|
||||||
s
|
|
||||||
|
Self {
|
||||||
|
ch,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
|
events,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
|
tasks,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,15 +101,19 @@ impl<'d, C: OneToOneChannel> Ppi<'d, C, 1, 1> {
|
|||||||
pub fn new_one_to_one(ch: impl Unborrow<Target = C> + 'd, event: Event, task: Task) -> Self {
|
pub fn new_one_to_one(ch: impl Unborrow<Target = C> + 'd, event: Event, task: Task) -> Self {
|
||||||
unborrow!(ch);
|
unborrow!(ch);
|
||||||
|
|
||||||
let s = Self {
|
let events = [event];
|
||||||
ch,
|
let tasks = [task];
|
||||||
events: [event],
|
|
||||||
tasks: [task],
|
|
||||||
phantom: PhantomData,
|
|
||||||
};
|
|
||||||
|
|
||||||
s.enable_all();
|
Self::enable_all(&tasks, &events, &ch);
|
||||||
s
|
|
||||||
|
Self {
|
||||||
|
ch,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
|
events,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
|
tasks,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,15 +126,19 @@ impl<'d, C: OneToTwoChannel> Ppi<'d, C, 1, 2> {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(ch);
|
unborrow!(ch);
|
||||||
|
|
||||||
let s = Self {
|
let events = [event];
|
||||||
ch,
|
let tasks = [task1, task2];
|
||||||
events: [event],
|
|
||||||
tasks: [task1, task2],
|
|
||||||
phantom: PhantomData,
|
|
||||||
};
|
|
||||||
|
|
||||||
s.enable_all();
|
Self::enable_all(&tasks, &events, &ch);
|
||||||
s
|
|
||||||
|
Self {
|
||||||
|
ch,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
|
events,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
|
tasks,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,18 +152,21 @@ impl<'d, C: ManyToManyChannel, const EVENT_COUNT: usize, const TASK_COUNT: usize
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
unborrow!(ch);
|
unborrow!(ch);
|
||||||
|
|
||||||
let s = Self {
|
Self::enable_all(&tasks, &events, &ch);
|
||||||
|
|
||||||
|
Self {
|
||||||
ch,
|
ch,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
events,
|
events,
|
||||||
|
#[cfg(feature = "_dppi")]
|
||||||
tasks,
|
tasks,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
};
|
}
|
||||||
|
|
||||||
s.enable_all();
|
|
||||||
s
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
|
||||||
|
|
||||||
/// Represents a task that a peripheral can do.
|
/// Represents a task that a peripheral can do.
|
||||||
/// When a task is subscribed to a PPI channel it will run when the channel is triggered by
|
/// When a task is subscribed to a PPI channel it will run when the channel is triggered by
|
||||||
/// a published event.
|
/// a published event.
|
||||||
@ -179,6 +178,10 @@ impl Task {
|
|||||||
pub(crate) fn from_reg<T>(reg: &T) -> Self {
|
pub(crate) fn from_reg<T>(reg: &T) -> Self {
|
||||||
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
|
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn subscribe_reg(&self) -> *mut u32 {
|
||||||
|
unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@ -196,6 +199,10 @@ impl Event {
|
|||||||
pub(crate) fn from_reg<T>(reg: &T) -> Self {
|
pub(crate) fn from_reg<T>(reg: &T) -> Self {
|
||||||
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
|
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn publish_reg(&self) -> *mut u32 {
|
||||||
|
unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@ -218,8 +225,8 @@ pub trait Channel: sealed::Channel + Unborrow<Target = Self> + Sized {
|
|||||||
fn is_task_configurable(&self) -> bool;
|
fn is_task_configurable(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait StaticToOneChannel: Channel {}
|
pub trait ZeroToOneChannel: Channel {}
|
||||||
pub trait OneToOneChannel: StaticToOneChannel {}
|
pub trait OneToOneChannel: ZeroToOneChannel {}
|
||||||
pub trait OneToTwoChannel: OneToOneChannel {}
|
pub trait OneToTwoChannel: OneToOneChannel {}
|
||||||
pub trait ManyToManyChannel: OneToTwoChannel {}
|
pub trait ManyToManyChannel: OneToTwoChannel {}
|
||||||
|
|
||||||
@ -250,8 +257,8 @@ impl Channel for AnyChannel {
|
|||||||
|
|
||||||
macro_rules! impl_ppi_channel {
|
macro_rules! impl_ppi_channel {
|
||||||
($type:ident, $number:expr, $has_configurable_task:expr) => {
|
($type:ident, $number:expr, $has_configurable_task:expr) => {
|
||||||
impl crate::interconnect::sealed::Channel for peripherals::$type {}
|
impl crate::ppi::sealed::Channel for peripherals::$type {}
|
||||||
impl crate::interconnect::Channel for peripherals::$type {
|
impl crate::ppi::Channel for peripherals::$type {
|
||||||
fn number(&self) -> usize {
|
fn number(&self) -> usize {
|
||||||
$number
|
$number
|
||||||
}
|
}
|
||||||
@ -267,19 +274,19 @@ macro_rules! impl_ppi_channel {
|
|||||||
};
|
};
|
||||||
($type:ident, $number:expr, $has_configurable_task:expr, 0, 1) => {
|
($type:ident, $number:expr, $has_configurable_task:expr, 0, 1) => {
|
||||||
impl_ppi_channel!($type, $number, $has_configurable_task, 0, 0);
|
impl_ppi_channel!($type, $number, $has_configurable_task, 0, 0);
|
||||||
impl crate::interconnect::StaticToOneChannel for peripherals::$type {}
|
impl crate::ppi::ZeroToOneChannel for peripherals::$type {}
|
||||||
};
|
};
|
||||||
($type:ident, $number:expr, $has_configurable_task:expr, 1, 1) => {
|
($type:ident, $number:expr, $has_configurable_task:expr, 1, 1) => {
|
||||||
impl_ppi_channel!($type, $number, $has_configurable_task, 0, 1);
|
impl_ppi_channel!($type, $number, $has_configurable_task, 0, 1);
|
||||||
impl crate::interconnect::OneToOneChannel for peripherals::$type {}
|
impl crate::ppi::OneToOneChannel for peripherals::$type {}
|
||||||
};
|
};
|
||||||
($type:ident, $number:expr, $has_configurable_task:expr, 1, 2) => {
|
($type:ident, $number:expr, $has_configurable_task:expr, 1, 2) => {
|
||||||
impl_ppi_channel!($type, $number, $has_configurable_task, 1, 1);
|
impl_ppi_channel!($type, $number, $has_configurable_task, 1, 1);
|
||||||
impl crate::interconnect::OneToTwoChannel for peripherals::$type {}
|
impl crate::ppi::OneToTwoChannel for peripherals::$type {}
|
||||||
};
|
};
|
||||||
($type:ident, $number:expr, $has_configurable_task:expr, many, many) => {
|
($type:ident, $number:expr, $has_configurable_task:expr, many, many) => {
|
||||||
impl_ppi_channel!($type, $number, $has_configurable_task, 1, 2);
|
impl_ppi_channel!($type, $number, $has_configurable_task, 1, 2);
|
||||||
impl crate::interconnect::ManyToManyChannel for peripherals::$type {}
|
impl crate::ppi::ManyToManyChannel for peripherals::$type {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
77
embassy-nrf/src/ppi/ppi.rs
Normal file
77
embassy-nrf/src/ppi/ppi.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use super::{Channel, Event, Ppi, Task};
|
||||||
|
use crate::pac;
|
||||||
|
|
||||||
|
impl<'d, C: Channel + 'd, const EVENT_COUNT: usize, const TASK_COUNT: usize>
|
||||||
|
Ppi<'d, C, EVENT_COUNT, TASK_COUNT>
|
||||||
|
{
|
||||||
|
fn set_main_task(task: Option<&Task>, channel: usize) {
|
||||||
|
let r = unsafe { &*pac::PPI::ptr() };
|
||||||
|
if let Some(task) = task {
|
||||||
|
r.ch[channel]
|
||||||
|
.tep
|
||||||
|
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
|
||||||
|
} else {
|
||||||
|
r.ch[channel].tep.write(|w| unsafe { w.bits(0) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_fork_task(task: Option<&Task>, channel: usize) {
|
||||||
|
let r = unsafe { &*pac::PPI::ptr() };
|
||||||
|
if let Some(task) = task {
|
||||||
|
r.fork[channel]
|
||||||
|
.tep
|
||||||
|
.write(|w| unsafe { w.bits(task.0.as_ptr() as u32) })
|
||||||
|
} else {
|
||||||
|
r.fork[channel].tep.write(|w| unsafe { w.bits(0) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_event(event: Option<&Event>, channel: usize) {
|
||||||
|
let r = unsafe { &*pac::PPI::ptr() };
|
||||||
|
if let Some(event) = event {
|
||||||
|
r.ch[channel]
|
||||||
|
.eep
|
||||||
|
.write(|w| unsafe { w.bits(event.0.as_ptr() as u32) })
|
||||||
|
} else {
|
||||||
|
r.ch[channel].eep.write(|w| unsafe { w.bits(0) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables all tasks and events
|
||||||
|
pub(super) fn enable_all(tasks: &[Task], events: &[Event], channel: &C) {
|
||||||
|
// One configurable task, no fork
|
||||||
|
if channel.is_task_configurable() && TASK_COUNT == 1 {
|
||||||
|
Self::set_main_task(Some(&tasks[0]), channel.number());
|
||||||
|
}
|
||||||
|
|
||||||
|
// One configurable task, as fork
|
||||||
|
if !channel.is_task_configurable() && TASK_COUNT == 1 {
|
||||||
|
Self::set_fork_task(Some(&tasks[0]), channel.number());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Two configurable tasks (main + fork)
|
||||||
|
if TASK_COUNT == 2 {
|
||||||
|
Self::set_main_task(Some(&tasks[0]), channel.number());
|
||||||
|
Self::set_fork_task(Some(&tasks[1]), channel.number());
|
||||||
|
}
|
||||||
|
|
||||||
|
if EVENT_COUNT == 1 {
|
||||||
|
Self::set_event(Some(&events[0]), channel.number());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable all tasks and events
|
||||||
|
pub(super) fn disable_all(&self) {
|
||||||
|
if self.ch.is_task_configurable() {
|
||||||
|
Self::set_main_task(None, self.ch.number());
|
||||||
|
}
|
||||||
|
|
||||||
|
if TASK_COUNT == 1 && !self.ch.is_task_configurable() || TASK_COUNT == 2 {
|
||||||
|
Self::set_fork_task(None, self.ch.number());
|
||||||
|
}
|
||||||
|
|
||||||
|
if EVENT_COUNT == 1 {
|
||||||
|
Self::set_event(None, self.ch.number());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,8 +11,8 @@ use embassy_hal_common::drop::OnDrop;
|
|||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
|
|
||||||
use crate::interconnect::{Event, Task};
|
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
|
use crate::ppi::{Event, Task};
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ use futures::future::poll_fn;
|
|||||||
use crate::chip::EASY_DMA_SIZE;
|
use crate::chip::EASY_DMA_SIZE;
|
||||||
use crate::gpio::sealed::Pin as _;
|
use crate::gpio::sealed::Pin as _;
|
||||||
use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin};
|
use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin};
|
||||||
use crate::interconnect::{AnyChannel, Event, OneToOneChannel, OneToTwoChannel, Ppi, Task};
|
|
||||||
use crate::interrupt::Interrupt;
|
use crate::interrupt::Interrupt;
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
|
use crate::ppi::{AnyChannel, Event, OneToOneChannel, OneToTwoChannel, Ppi, Task};
|
||||||
use crate::timer::Instance as TimerInstance;
|
use crate::timer::Instance as TimerInstance;
|
||||||
use crate::timer::{Frequency, Timer};
|
use crate::timer::{Frequency, Timer};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user