Merge pull request #1600 from ilikepi63/main

feature(1354): Added lifetimes to Event + Tasks
This commit is contained in:
Dario Nieuwenhuis 2023-07-05 17:13:26 +00:00 committed by GitHub
commit 8313b7315a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 54 additions and 45 deletions

View File

@ -221,7 +221,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> {
} }
/// Returns the IN event, for use with PPI. /// Returns the IN event, for use with PPI.
pub fn event_in(&self) -> Event { pub fn event_in(&self) -> Event<'d> {
let g = regs(); let g = regs();
Event::from_reg(&g.events_in[self.ch.number()]) Event::from_reg(&g.events_in[self.ch.number()])
} }
@ -292,21 +292,21 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> {
} }
/// Returns the OUT task, for use with PPI. /// Returns the OUT task, for use with PPI.
pub fn task_out(&self) -> Task { pub fn task_out(&self) -> Task<'d> {
let g = regs(); let g = regs();
Task::from_reg(&g.tasks_out[self.ch.number()]) Task::from_reg(&g.tasks_out[self.ch.number()])
} }
/// Returns the CLR task, for use with PPI. /// Returns the CLR task, for use with PPI.
#[cfg(not(feature = "nrf51"))] #[cfg(not(feature = "nrf51"))]
pub fn task_clr(&self) -> Task { pub fn task_clr(&self) -> Task<'d> {
let g = regs(); let g = regs();
Task::from_reg(&g.tasks_clr[self.ch.number()]) Task::from_reg(&g.tasks_clr[self.ch.number()])
} }
/// Returns the SET task, for use with PPI. /// Returns the SET task, for use with PPI.
#[cfg(not(feature = "nrf51"))] #[cfg(not(feature = "nrf51"))]
pub fn task_set(&self) -> Task { pub fn task_set(&self) -> Task<'d> {
let g = regs(); let g = regs();
Task::from_reg(&g.tasks_set[self.ch.number()]) Task::from_reg(&g.tasks_set[self.ch.number()])
} }

View File

@ -12,14 +12,14 @@ pub(crate) fn regs() -> &'static pac::dppic::RegisterBlock {
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
/// Configure PPI channel to trigger `task` on `event`. /// Configure PPI channel to trigger `task` on `event`.
pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self { pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task: Task<'d>) -> Self {
Ppi::new_many_to_many(ch, [event], [task]) Ppi::new_many_to_many(ch, [event], [task])
} }
} }
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
/// Configure PPI channel to trigger both `task1` and `task2` on `event`. /// Configure PPI channel to trigger both `task1` and `task2` on `event`.
pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self { pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self {
Ppi::new_many_to_many(ch, [event], [task1, task2]) Ppi::new_many_to_many(ch, [event], [task1, task2])
} }
} }
@ -30,8 +30,8 @@ impl<'d, C: ConfigurableChannel, const EVENT_COUNT: usize, const TASK_COUNT: usi
/// Configure a DPPI channel to trigger all `tasks` when any of the `events` fires. /// Configure a DPPI channel to trigger all `tasks` when any of the `events` fires.
pub fn new_many_to_many( pub fn new_many_to_many(
ch: impl Peripheral<P = C> + 'd, ch: impl Peripheral<P = C> + 'd,
events: [Event; EVENT_COUNT], events: [Event<'d>; EVENT_COUNT],
tasks: [Task; TASK_COUNT], tasks: [Task<'d>; TASK_COUNT],
) -> Self { ) -> Self {
into_ref!(ch); into_ref!(ch);

View File

@ -15,6 +15,7 @@
//! many tasks and events, but any single task or event can only be coupled with one channel. //! many tasks and events, but any single task or event can only be coupled with one channel.
//! //!
use core::marker::PhantomData;
use core::ptr::NonNull; use core::ptr::NonNull;
use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
@ -30,9 +31,9 @@ pub(crate) use _version::*;
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")]
events: [Event; EVENT_COUNT], events: [Event<'d>; EVENT_COUNT],
#[cfg(feature = "_dppi")] #[cfg(feature = "_dppi")]
tasks: [Task; TASK_COUNT], tasks: [Task<'d>; TASK_COUNT],
} }
/// PPI channel group driver. /// PPI channel group driver.
@ -95,7 +96,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
/// Get a reference to the "enable all" task. /// Get a reference to the "enable all" task.
/// ///
/// When triggered, it will enable all the channels in this group. /// When triggered, it will enable all the channels in this group.
pub fn task_enable_all(&self) -> Task { pub fn task_enable_all(&self) -> Task<'d> {
let n = self.g.number(); let n = self.g.number();
Task::from_reg(&regs().tasks_chg[n].en) Task::from_reg(&regs().tasks_chg[n].en)
} }
@ -103,7 +104,7 @@ impl<'d, G: Group> PpiGroup<'d, G> {
/// Get a reference to the "disable all" task. /// Get a reference to the "disable all" task.
/// ///
/// When triggered, it will disable all the channels in this group. /// When triggered, it will disable all the channels in this group.
pub fn task_disable_all(&self) -> Task { pub fn task_disable_all(&self) -> Task<'d> {
let n = self.g.number(); let n = self.g.number();
Task::from_reg(&regs().tasks_chg[n].dis) Task::from_reg(&regs().tasks_chg[n].dis)
} }
@ -125,16 +126,16 @@ const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
/// 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.
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
pub struct Task(NonNull<u32>); pub struct Task<'d>(NonNull<u32>, PhantomData<&'d ()>);
impl Task { impl<'d> Task<'d> {
/// Create a new `Task` from a task register pointer /// Create a new `Task` from a task register pointer
/// ///
/// # Safety /// # Safety
/// ///
/// `ptr` must be a pointer to a valid `TASKS_*` register from an nRF peripheral. /// `ptr` must be a pointer to a valid `TASKS_*` register from an nRF peripheral.
pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self { pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self {
Self(ptr) Self(ptr, PhantomData)
} }
/// Triggers this task. /// Triggers this task.
@ -143,7 +144,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 _) },
PhantomData,
)
} }
/// Address of subscription register for this task. /// Address of subscription register for this task.
@ -156,26 +160,29 @@ impl Task {
/// # Safety /// # Safety
/// ///
/// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. /// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core.
unsafe impl Send for Task {} unsafe impl Send for Task<'_> {}
/// Represents an event that a peripheral can publish. /// Represents an event that a peripheral can publish.
/// ///
/// An event can be set to publish on a PPI channel when the event happens. /// An event can be set to publish on a PPI channel when the event happens.
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
pub struct Event(NonNull<u32>); pub struct Event<'d>(NonNull<u32>, PhantomData<&'d ()>);
impl Event { impl<'d> Event<'d> {
/// Create a new `Event` from an event register pointer /// Create a new `Event` from an event register pointer
/// ///
/// # Safety /// # Safety
/// ///
/// `ptr` must be a pointer to a valid `EVENTS_*` register from an nRF peripheral. /// `ptr` must be a pointer to a valid `EVENTS_*` register from an nRF peripheral.
pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self { pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self {
Self(ptr) Self(ptr, PhantomData)
} }
pub(crate) fn from_reg<T>(reg: &T) -> Self { pub(crate) fn from_reg<T>(reg: &'d T) -> Self {
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) Self(
unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) },
PhantomData,
)
} }
/// Describes whether this Event is currently in a triggered state. /// Describes whether this Event is currently in a triggered state.
@ -198,7 +205,7 @@ impl Event {
/// # Safety /// # Safety
/// ///
/// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core. /// NonNull is not send, but this event is only allowed to point at registers and those exist in any context on the same core.
unsafe impl Send for Event {} unsafe impl Send for Event<'_> {}
// ====================== // ======================
// traits // traits

View File

@ -3,12 +3,12 @@ use embassy_hal_common::into_ref;
use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task};
use crate::{pac, Peripheral}; use crate::{pac, Peripheral};
impl Task { impl<'d> Task<'d> {
fn reg_val(&self) -> u32 { fn reg_val(&self) -> u32 {
self.0.as_ptr() as _ self.0.as_ptr() as _
} }
} }
impl Event { impl<'d> Event<'d> {
fn reg_val(&self) -> u32 { fn reg_val(&self) -> u32 {
self.0.as_ptr() as _ self.0.as_ptr() as _
} }
@ -34,7 +34,7 @@ impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> {
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
/// Configure PPI channel to trigger `task` on `event`. /// Configure PPI channel to trigger `task` on `event`.
pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self { pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task: Task<'d>) -> Self {
into_ref!(ch); into_ref!(ch);
let r = regs(); let r = regs();
@ -49,7 +49,7 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task #[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
/// Configure PPI channel to trigger both `task1` and `task2` on `event`. /// Configure PPI channel to trigger both `task1` and `task2` on `event`.
pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self { pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self {
into_ref!(ch); into_ref!(ch);
let r = regs(); let r = regs();

View File

@ -181,7 +181,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// Returns reference to `Stopped` event endpoint for PPI. /// Returns reference to `Stopped` event endpoint for PPI.
#[inline(always)] #[inline(always)]
pub fn event_stopped(&self) -> Event { pub fn event_stopped(&self) -> Event<'d> {
let r = T::regs(); let r = T::regs();
Event::from_reg(&r.events_stopped) Event::from_reg(&r.events_stopped)
@ -189,7 +189,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// Returns reference to `LoopsDone` event endpoint for PPI. /// Returns reference to `LoopsDone` event endpoint for PPI.
#[inline(always)] #[inline(always)]
pub fn event_loops_done(&self) -> Event { pub fn event_loops_done(&self) -> Event<'d> {
let r = T::regs(); let r = T::regs();
Event::from_reg(&r.events_loopsdone) Event::from_reg(&r.events_loopsdone)
@ -197,7 +197,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// Returns reference to `PwmPeriodEnd` event endpoint for PPI. /// Returns reference to `PwmPeriodEnd` event endpoint for PPI.
#[inline(always)] #[inline(always)]
pub fn event_pwm_period_end(&self) -> Event { pub fn event_pwm_period_end(&self) -> Event<'d> {
let r = T::regs(); let r = T::regs();
Event::from_reg(&r.events_pwmperiodend) Event::from_reg(&r.events_pwmperiodend)
@ -205,7 +205,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// Returns reference to `Seq0 End` event endpoint for PPI. /// Returns reference to `Seq0 End` event endpoint for PPI.
#[inline(always)] #[inline(always)]
pub fn event_seq_end(&self) -> Event { pub fn event_seq_end(&self) -> Event<'d> {
let r = T::regs(); let r = T::regs();
Event::from_reg(&r.events_seqend[0]) Event::from_reg(&r.events_seqend[0])
@ -213,7 +213,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// Returns reference to `Seq1 End` event endpoint for PPI. /// Returns reference to `Seq1 End` event endpoint for PPI.
#[inline(always)] #[inline(always)]
pub fn event_seq1_end(&self) -> Event { pub fn event_seq1_end(&self) -> Event<'d> {
let r = T::regs(); let r = T::regs();
Event::from_reg(&r.events_seqend[1]) Event::from_reg(&r.events_seqend[1])
@ -221,7 +221,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// Returns reference to `Seq0 Started` event endpoint for PPI. /// Returns reference to `Seq0 Started` event endpoint for PPI.
#[inline(always)] #[inline(always)]
pub fn event_seq0_started(&self) -> Event { pub fn event_seq0_started(&self) -> Event<'d> {
let r = T::regs(); let r = T::regs();
Event::from_reg(&r.events_seqstarted[0]) Event::from_reg(&r.events_seqstarted[0])
@ -229,7 +229,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// Returns reference to `Seq1 Started` event endpoint for PPI. /// Returns reference to `Seq1 Started` event endpoint for PPI.
#[inline(always)] #[inline(always)]
pub fn event_seq1_started(&self) -> Event { pub fn event_seq1_started(&self) -> Event<'d> {
let r = T::regs(); let r = T::regs();
Event::from_reg(&r.events_seqstarted[1]) Event::from_reg(&r.events_seqstarted[1])
@ -240,7 +240,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// ///
/// Interacting with the sequence while it runs puts it in an unknown state /// Interacting with the sequence while it runs puts it in an unknown state
#[inline(always)] #[inline(always)]
pub unsafe fn task_start_seq0(&self) -> Task { pub unsafe fn task_start_seq0(&self) -> Task<'d> {
let r = T::regs(); let r = T::regs();
Task::from_reg(&r.tasks_seqstart[0]) Task::from_reg(&r.tasks_seqstart[0])
@ -251,7 +251,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// ///
/// Interacting with the sequence while it runs puts it in an unknown state /// Interacting with the sequence while it runs puts it in an unknown state
#[inline(always)] #[inline(always)]
pub unsafe fn task_start_seq1(&self) -> Task { pub unsafe fn task_start_seq1(&self) -> Task<'d> {
let r = T::regs(); let r = T::regs();
Task::from_reg(&r.tasks_seqstart[1]) Task::from_reg(&r.tasks_seqstart[1])
@ -262,7 +262,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// ///
/// Interacting with the sequence while it runs puts it in an unknown state /// Interacting with the sequence while it runs puts it in an unknown state
#[inline(always)] #[inline(always)]
pub unsafe fn task_next_step(&self) -> Task { pub unsafe fn task_next_step(&self) -> Task<'d> {
let r = T::regs(); let r = T::regs();
Task::from_reg(&r.tasks_nextstep) Task::from_reg(&r.tasks_nextstep)
@ -273,7 +273,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
/// ///
/// Interacting with the sequence while it runs puts it in an unknown state /// Interacting with the sequence while it runs puts it in an unknown state
#[inline(always)] #[inline(always)]
pub unsafe fn task_stop(&self) -> Task { pub unsafe fn task_stop(&self) -> Task<'d> {
let r = T::regs(); let r = T::regs();
Task::from_reg(&r.tasks_stop) Task::from_reg(&r.tasks_stop)

View File

@ -320,7 +320,9 @@ impl<'d, const N: usize> Saadc<'d, N> {
timer.cc(0).write(sample_counter); timer.cc(0).write(sample_counter);
timer.cc(0).short_compare_clear(); timer.cc(0).short_compare_clear();
let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer.cc(0).event_compare(), Task::from_reg(&r.tasks_sample)); let timer_cc = timer.cc(0);
let mut sample_ppi = Ppi::new_one_to_one(ppi_ch2, timer_cc.event_compare(), Task::from_reg(&r.tasks_sample));
timer.start(); timer.start();

View File

@ -168,21 +168,21 @@ impl<'d, T: Instance> Timer<'d, T> {
/// Returns the START task, for use with PPI. /// Returns the START task, for use with PPI.
/// ///
/// When triggered, this task starts the timer. /// When triggered, this task starts the timer.
pub fn task_start(&self) -> Task { pub fn task_start(&self) -> Task<'d> {
Task::from_reg(&T::regs().tasks_start) Task::from_reg(&T::regs().tasks_start)
} }
/// Returns the STOP task, for use with PPI. /// Returns the STOP task, for use with PPI.
/// ///
/// When triggered, this task stops the timer. /// When triggered, this task stops the timer.
pub fn task_stop(&self) -> Task { pub fn task_stop(&self) -> Task<'d> {
Task::from_reg(&T::regs().tasks_stop) Task::from_reg(&T::regs().tasks_stop)
} }
/// Returns the CLEAR task, for use with PPI. /// Returns the CLEAR task, for use with PPI.
/// ///
/// When triggered, this task resets the timer's counter to 0. /// When triggered, this task resets the timer's counter to 0.
pub fn task_clear(&self) -> Task { pub fn task_clear(&self) -> Task<'d> {
Task::from_reg(&T::regs().tasks_clear) Task::from_reg(&T::regs().tasks_clear)
} }
@ -190,7 +190,7 @@ impl<'d, T: Instance> Timer<'d, T> {
/// ///
/// When triggered, this task increments the timer's counter by 1. /// When triggered, this task increments the timer's counter by 1.
/// Only works in counter mode. /// Only works in counter mode.
pub fn task_count(&self) -> Task { pub fn task_count(&self) -> Task<'d> {
Task::from_reg(&T::regs().tasks_count) Task::from_reg(&T::regs().tasks_count)
} }
@ -258,14 +258,14 @@ impl<'d, T: Instance> Cc<'d, T> {
/// Returns this CC register's CAPTURE task, for use with PPI. /// Returns this CC register's CAPTURE task, for use with PPI.
/// ///
/// When triggered, this task will capture the current value of the timer's counter in this register. /// When triggered, this task will capture the current value of the timer's counter in this register.
pub fn task_capture(&self) -> Task { pub fn task_capture(&self) -> Task<'d> {
Task::from_reg(&T::regs().tasks_capture) Task::from_reg(&T::regs().tasks_capture)
} }
/// Returns this CC register's COMPARE event, for use with PPI. /// Returns this CC register's COMPARE event, for use with PPI.
/// ///
/// This event will fire when the timer's counter reaches the value in this CC register. /// This event will fire when the timer's counter reaches the value in this CC register.
pub fn event_compare(&self) -> Event { pub fn event_compare(&self) -> Event<'d> {
Event::from_reg(&T::regs().events_compare[self.n]) Event::from_reg(&T::regs().events_compare[self.n])
} }