added typestate to nrf-Timer

useful for hooking up the PPI to an Event without needing interrupt
tested with buffered_uart example on nRF52840-DK
This commit is contained in:
f_punk
2021-09-01 16:16:56 +02:00
parent ea688afe9b
commit a0c40562ea
3 changed files with 41 additions and 15 deletions

View File

@ -27,6 +27,8 @@ pub(crate) mod sealed {
fn waker(n: usize) -> &'static AtomicWaker;
}
pub trait ExtendedInstance {}
pub trait TimerType {}
}
pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static + Send {
@ -84,11 +86,25 @@ pub enum Frequency {
///
/// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter
/// or trigger an event when the counter reaches a certain value.
pub struct Timer<'d, T: Instance> {
phantom: PhantomData<&'d mut T>,
pub trait TimerType: sealed::TimerType {}
pub enum Awaitable {}
pub enum NotAwaitable {}
impl sealed::TimerType for Awaitable {}
impl sealed::TimerType for NotAwaitable {}
impl TimerType for Awaitable {}
impl TimerType for NotAwaitable {}
pub type AwaitableTimer<'d, T> = Timer<'d, T, Awaitable>;
pub type NotAwaitableTimer<'d, T> = Timer<'d, T, NotAwaitable>;
pub struct Timer<'d, T: Instance, I: TimerType> {
phantom: PhantomData<(&'d mut T, I)>,
}
impl<'d, T: Instance> Timer<'d, T> {
impl<'d, T: Instance> Timer<'d, T, Awaitable> {
pub fn new(
timer: impl Unborrow<Target = T> + 'd,
irq: impl Unborrow<Target = T::Interrupt> + 'd,
@ -101,11 +117,18 @@ impl<'d, T: Instance> Timer<'d, T> {
Self::new_irqless(timer)
}
}
impl<'d, T: Instance> Timer<'d, T, NotAwaitable> {
pub fn new(timer: impl Unborrow<Target = T> + 'd) -> Self {
Self::new_irqless(timer)
}
}
impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> {
/// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work.
///
/// This is used by `Uarte` internally.
pub(crate) fn new_irqless(_timer: impl Unborrow<Target = T> + 'd) -> Self {
fn new_irqless(_timer: impl Unborrow<Target = T> + 'd) -> Self {
let regs = T::regs();
let mut this = Self {
@ -208,7 +231,7 @@ impl<'d, T: Instance> Timer<'d, T> {
///
/// # Panics
/// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer).
pub fn cc(&mut self, n: usize) -> Cc<T> {
pub fn cc(&mut self, n: usize) -> Cc<T, I> {
if n >= T::CCS {
panic!(
"Cannot get CC register {} of timer with {} CC registers.",
@ -219,6 +242,7 @@ impl<'d, T: Instance> Timer<'d, T> {
Cc {
n,
phantom: PhantomData,
phantom2: PhantomData,
}
}
}
@ -230,12 +254,16 @@ impl<'d, T: Instance> Timer<'d, T> {
///
/// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register.
/// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register
pub struct Cc<'a, T: Instance> {
pub struct Cc<'a, T: Instance, I: TimerType> {
n: usize,
phantom: PhantomData<&'a mut T>,
phantom2: PhantomData<I>,
}
impl<'a, T: Instance> Cc<'a, T> {
impl<'a, T: Instance> Cc<'a, T, Awaitable> {}
impl<'a, T: Instance> Cc<'a, T, NotAwaitable> {}
impl<'a, T: Instance, I: TimerType> Cc<'a, T, I> {
/// Get the current value stored in the register.
pub fn read(&self) -> u32 {
T::regs().cc[self.n].read().cc().bits()