diff options
| author | f_punk <[email protected]> | 2021-09-01 16:16:56 +0200 |
|---|---|---|
| committer | f_punk <[email protected]> | 2021-09-01 16:16:56 +0200 |
| commit | a0c40562eab224d273a972fdcf5029c585974bc7 (patch) | |
| tree | 69d3dc9539d0481252acc1e32d6d850ed638c310 | |
| parent | ea688afe9b32cfdf10e91805d8c1e5668e0e85cd (diff) | |
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
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 7 | ||||
| -rw-r--r-- | embassy-nrf/src/timer.rs | 42 | ||||
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 7 |
3 files changed, 41 insertions, 15 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 048c36d39..5c9f4270b 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -15,9 +15,8 @@ use crate::gpio::sealed::Pin as _; | |||
| 15 | use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; | 15 | use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; |
| 16 | use crate::pac; | 16 | use crate::pac; |
| 17 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 17 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| 18 | use crate::timer::Frequency; | ||
| 19 | use crate::timer::Instance as TimerInstance; | 18 | use crate::timer::Instance as TimerInstance; |
| 20 | use crate::timer::Timer; | 19 | use crate::timer::{Frequency, NotAwaitableTimer}; |
| 21 | use crate::uarte::{Config, Instance as UarteInstance}; | 20 | use crate::uarte::{Config, Instance as UarteInstance}; |
| 22 | 21 | ||
| 23 | // Re-export SVD variants to allow user to directly set values | 22 | // 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> { | |||
| 44 | 43 | ||
| 45 | struct StateInner<'d, U: UarteInstance, T: TimerInstance> { | 44 | struct StateInner<'d, U: UarteInstance, T: TimerInstance> { |
| 46 | phantom: PhantomData<&'d mut U>, | 45 | phantom: PhantomData<&'d mut U>, |
| 47 | timer: Timer<'d, T>, | 46 | timer: NotAwaitableTimer<'d, T>, |
| 48 | _ppi_ch1: Ppi<'d, AnyConfigurableChannel>, | 47 | _ppi_ch1: Ppi<'d, AnyConfigurableChannel>, |
| 49 | _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, | 48 | _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, |
| 50 | 49 | ||
| @@ -85,7 +84,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { | |||
| 85 | 84 | ||
| 86 | let r = U::regs(); | 85 | let r = U::regs(); |
| 87 | 86 | ||
| 88 | let mut timer = Timer::new_irqless(timer); | 87 | let mut timer = NotAwaitableTimer::new(timer); |
| 89 | 88 | ||
| 90 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); | 89 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); |
| 91 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); | 90 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); |
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index eab9a1416..939e99ed5 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs | |||
| @@ -27,6 +27,8 @@ pub(crate) mod sealed { | |||
| 27 | fn waker(n: usize) -> &'static AtomicWaker; | 27 | fn waker(n: usize) -> &'static AtomicWaker; |
| 28 | } | 28 | } |
| 29 | pub trait ExtendedInstance {} | 29 | pub trait ExtendedInstance {} |
| 30 | |||
| 31 | pub trait TimerType {} | ||
| 30 | } | 32 | } |
| 31 | 33 | ||
| 32 | pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static + Send { | 34 | pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static + Send { |
| @@ -84,11 +86,25 @@ pub enum Frequency { | |||
| 84 | /// | 86 | /// |
| 85 | /// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter | 87 | /// It has either 4 or 6 Capture/Compare registers, which can be used to capture the current state of the counter |
| 86 | /// or trigger an event when the counter reaches a certain value. | 88 | /// or trigger an event when the counter reaches a certain value. |
| 87 | pub struct Timer<'d, T: Instance> { | 89 | |
| 88 | phantom: PhantomData<&'d mut T>, | 90 | pub trait TimerType: sealed::TimerType {} |
| 91 | |||
| 92 | pub enum Awaitable {} | ||
| 93 | pub enum NotAwaitable {} | ||
| 94 | |||
| 95 | impl sealed::TimerType for Awaitable {} | ||
| 96 | impl sealed::TimerType for NotAwaitable {} | ||
| 97 | impl TimerType for Awaitable {} | ||
| 98 | impl TimerType for NotAwaitable {} | ||
| 99 | |||
| 100 | pub type AwaitableTimer<'d, T> = Timer<'d, T, Awaitable>; | ||
| 101 | pub type NotAwaitableTimer<'d, T> = Timer<'d, T, NotAwaitable>; | ||
| 102 | |||
| 103 | pub struct Timer<'d, T: Instance, I: TimerType> { | ||
| 104 | phantom: PhantomData<(&'d mut T, I)>, | ||
| 89 | } | 105 | } |
| 90 | 106 | ||
| 91 | impl<'d, T: Instance> Timer<'d, T> { | 107 | impl<'d, T: Instance> Timer<'d, T, Awaitable> { |
| 92 | pub fn new( | 108 | pub fn new( |
| 93 | timer: impl Unborrow<Target = T> + 'd, | 109 | timer: impl Unborrow<Target = T> + 'd, |
| 94 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | 110 | irq: impl Unborrow<Target = T::Interrupt> + 'd, |
| @@ -101,11 +117,18 @@ impl<'d, T: Instance> Timer<'d, T> { | |||
| 101 | 117 | ||
| 102 | Self::new_irqless(timer) | 118 | Self::new_irqless(timer) |
| 103 | } | 119 | } |
| 120 | } | ||
| 121 | impl<'d, T: Instance> Timer<'d, T, NotAwaitable> { | ||
| 122 | pub fn new(timer: impl Unborrow<Target = T> + 'd) -> Self { | ||
| 123 | Self::new_irqless(timer) | ||
| 124 | } | ||
| 125 | } | ||
| 104 | 126 | ||
| 127 | impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> { | ||
| 105 | /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work. | 128 | /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work. |
| 106 | /// | 129 | /// |
| 107 | /// This is used by `Uarte` internally. | 130 | /// This is used by `Uarte` internally. |
| 108 | pub(crate) fn new_irqless(_timer: impl Unborrow<Target = T> + 'd) -> Self { | 131 | fn new_irqless(_timer: impl Unborrow<Target = T> + 'd) -> Self { |
| 109 | let regs = T::regs(); | 132 | let regs = T::regs(); |
| 110 | 133 | ||
| 111 | let mut this = Self { | 134 | let mut this = Self { |
| @@ -208,7 +231,7 @@ impl<'d, T: Instance> Timer<'d, T> { | |||
| 208 | /// | 231 | /// |
| 209 | /// # Panics | 232 | /// # Panics |
| 210 | /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer). | 233 | /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer). |
| 211 | pub fn cc(&mut self, n: usize) -> Cc<T> { | 234 | pub fn cc(&mut self, n: usize) -> Cc<T, I> { |
| 212 | if n >= T::CCS { | 235 | if n >= T::CCS { |
| 213 | panic!( | 236 | panic!( |
| 214 | "Cannot get CC register {} of timer with {} CC registers.", | 237 | "Cannot get CC register {} of timer with {} CC registers.", |
| @@ -219,6 +242,7 @@ impl<'d, T: Instance> Timer<'d, T> { | |||
| 219 | Cc { | 242 | Cc { |
| 220 | n, | 243 | n, |
| 221 | phantom: PhantomData, | 244 | phantom: PhantomData, |
| 245 | phantom2: PhantomData, | ||
| 222 | } | 246 | } |
| 223 | } | 247 | } |
| 224 | } | 248 | } |
| @@ -230,12 +254,16 @@ impl<'d, T: Instance> Timer<'d, T> { | |||
| 230 | /// | 254 | /// |
| 231 | /// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register. | 255 | /// The timer will fire the register's COMPARE event when its counter reaches the value stored in the register. |
| 232 | /// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register | 256 | /// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register |
| 233 | pub struct Cc<'a, T: Instance> { | 257 | pub struct Cc<'a, T: Instance, I: TimerType> { |
| 234 | n: usize, | 258 | n: usize, |
| 235 | phantom: PhantomData<&'a mut T>, | 259 | phantom: PhantomData<&'a mut T>, |
| 260 | phantom2: PhantomData<I>, | ||
| 236 | } | 261 | } |
| 237 | 262 | ||
| 238 | impl<'a, T: Instance> Cc<'a, T> { | 263 | impl<'a, T: Instance> Cc<'a, T, Awaitable> {} |
| 264 | impl<'a, T: Instance> Cc<'a, T, NotAwaitable> {} | ||
| 265 | |||
| 266 | impl<'a, T: Instance, I: TimerType> Cc<'a, T, I> { | ||
| 239 | /// Get the current value stored in the register. | 267 | /// Get the current value stored in the register. |
| 240 | pub fn read(&self) -> u32 { | 268 | pub fn read(&self) -> u32 { |
| 241 | T::regs().cc[self.n].read().cc().bits() | 269 | T::regs().cc[self.n].read().cc().bits() |
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index b2b298661..d164ebcbc 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -18,9 +18,8 @@ use crate::gpio::{self, OptionalPin as GpioOptionalPin, Pin as GpioPin}; | |||
| 18 | use crate::interrupt::Interrupt; | 18 | use crate::interrupt::Interrupt; |
| 19 | use crate::pac; | 19 | use crate::pac; |
| 20 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 20 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| 21 | use crate::timer::Frequency; | ||
| 22 | use crate::timer::Instance as TimerInstance; | 21 | use crate::timer::Instance as TimerInstance; |
| 23 | use crate::timer::Timer; | 22 | use crate::timer::{Frequency, NotAwaitableTimer}; |
| 24 | 23 | ||
| 25 | // Re-export SVD variants to allow user to directly set values. | 24 | // Re-export SVD variants to allow user to directly set values. |
| 26 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 25 | 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> { | |||
| 289 | /// allowing it to implement the ReadUntilIdle trait. | 288 | /// allowing it to implement the ReadUntilIdle trait. |
| 290 | pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { | 289 | pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { |
| 291 | uarte: Uarte<'d, U>, | 290 | uarte: Uarte<'d, U>, |
| 292 | timer: Timer<'d, T>, | 291 | timer: NotAwaitableTimer<'d, T>, |
| 293 | ppi_ch1: Ppi<'d, AnyConfigurableChannel>, | 292 | ppi_ch1: Ppi<'d, AnyConfigurableChannel>, |
| 294 | _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, | 293 | _ppi_ch2: Ppi<'d, AnyConfigurableChannel>, |
| 295 | } | 294 | } |
| @@ -318,7 +317,7 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> { | |||
| 318 | ) -> Self { | 317 | ) -> Self { |
| 319 | let baudrate = config.baudrate; | 318 | let baudrate = config.baudrate; |
| 320 | let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config); | 319 | let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config); |
| 321 | let mut timer = Timer::new_irqless(timer); | 320 | let mut timer = NotAwaitableTimer::new(timer); |
| 322 | 321 | ||
| 323 | unborrow!(ppi_ch1, ppi_ch2); | 322 | unborrow!(ppi_ch1, ppi_ch2); |
| 324 | 323 | ||
