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:
parent
ea688afe9b
commit
a0c40562ea
3 changed files with 41 additions and 15 deletions
|
@ -15,9 +15,8 @@ use crate::gpio::sealed::Pin as _;
|
|||
use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin};
|
||||
use crate::pac;
|
||||
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
|
||||
use crate::timer::Frequency;
|
||||
use crate::timer::Instance as TimerInstance;
|
||||
use crate::timer::Timer;
|
||||
use crate::timer::{Frequency, NotAwaitableTimer};
|
||||
use crate::uarte::{Config, Instance as UarteInstance};
|
||||
|
||||
// Re-export SVD variants to allow user to directly set values
|
||||
|
@ -44,7 +43,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> {
|
|||
|
||||
struct StateInner<'d, U: UarteInstance, T: TimerInstance> {
|
||||
phantom: PhantomData<&'d mut U>,
|
||||
timer: Timer<'d, T>,
|
||||
timer: NotAwaitableTimer<'d, T>,
|
||||
_ppi_ch1: Ppi<'d, AnyConfigurableChannel>,
|
||||
_ppi_ch2: Ppi<'d, AnyConfigurableChannel>,
|
||||
|
||||
|
@ -85,7 +84,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
|
|||
|
||||
let r = U::regs();
|
||||
|
||||
let mut timer = Timer::new_irqless(timer);
|
||||
let mut timer = NotAwaitableTimer::new(timer);
|
||||
|
||||
rxd.conf().write(|w| w.input().connect().drive().h0h1());
|
||||
r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -18,9 +18,8 @@ use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin};
|
|||
use crate::interrupt::Interrupt;
|
||||
use crate::pac;
|
||||
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
|
||||
use crate::timer::Frequency;
|
||||
use crate::timer::Instance as TimerInstance;
|
||||
use crate::timer::Timer;
|
||||
use crate::timer::{Frequency, NotAwaitableTimer};
|
||||
|
||||
// Re-export SVD variants to allow user to directly set values.
|
||||
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
|
||||
|
@ -289,7 +288,7 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
|
|||
/// allowing it to implement the ReadUntilIdle trait.
|
||||
pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
|
||||
uarte: Uarte<'d, U>,
|
||||
timer: Timer<'d, T>,
|
||||
timer: NotAwaitableTimer<'d, T>,
|
||||
ppi_ch1: Ppi<'d, AnyConfigurableChannel>,
|
||||
_ppi_ch2: Ppi<'d, AnyConfigurableChannel>,
|
||||
}
|
||||
|
@ -318,7 +317,7 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
|
|||
) -> Self {
|
||||
let baudrate = config.baudrate;
|
||||
let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config);
|
||||
let mut timer = Timer::new_irqless(timer);
|
||||
let mut timer = NotAwaitableTimer::new(timer);
|
||||
|
||||
unborrow!(ppi_ch1, ppi_ch2);
|
||||
|
||||
|
|
Loading…
Reference in a new issue