aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorf_punk <[email protected]>2021-09-01 16:16:56 +0200
committerf_punk <[email protected]>2021-09-01 16:16:56 +0200
commita0c40562eab224d273a972fdcf5029c585974bc7 (patch)
tree69d3dc9539d0481252acc1e32d6d850ed638c310
parentea688afe9b32cfdf10e91805d8c1e5668e0e85cd (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.rs7
-rw-r--r--embassy-nrf/src/timer.rs42
-rw-r--r--embassy-nrf/src/uarte.rs7
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 _;
15use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; 15use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin};
16use crate::pac; 16use crate::pac;
17use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 17use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
18use crate::timer::Frequency;
19use crate::timer::Instance as TimerInstance; 18use crate::timer::Instance as TimerInstance;
20use crate::timer::Timer; 19use crate::timer::{Frequency, NotAwaitableTimer};
21use crate::uarte::{Config, Instance as UarteInstance}; 20use 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
45struct StateInner<'d, U: UarteInstance, T: TimerInstance> { 44struct 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
32pub trait Instance: Unborrow<Target = Self> + sealed::Instance + 'static + Send { 34pub 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.
87pub struct Timer<'d, T: Instance> { 89
88 phantom: PhantomData<&'d mut T>, 90pub trait TimerType: sealed::TimerType {}
91
92pub enum Awaitable {}
93pub enum NotAwaitable {}
94
95impl sealed::TimerType for Awaitable {}
96impl sealed::TimerType for NotAwaitable {}
97impl TimerType for Awaitable {}
98impl TimerType for NotAwaitable {}
99
100pub type AwaitableTimer<'d, T> = Timer<'d, T, Awaitable>;
101pub type NotAwaitableTimer<'d, T> = Timer<'d, T, NotAwaitable>;
102
103pub struct Timer<'d, T: Instance, I: TimerType> {
104 phantom: PhantomData<(&'d mut T, I)>,
89} 105}
90 106
91impl<'d, T: Instance> Timer<'d, T> { 107impl<'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}
121impl<'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
127impl<'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
233pub struct Cc<'a, T: Instance> { 257pub 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
238impl<'a, T: Instance> Cc<'a, T> { 263impl<'a, T: Instance> Cc<'a, T, Awaitable> {}
264impl<'a, T: Instance> Cc<'a, T, NotAwaitable> {}
265
266impl<'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};
18use crate::interrupt::Interrupt; 18use crate::interrupt::Interrupt;
19use crate::pac; 19use crate::pac;
20use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 20use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
21use crate::timer::Frequency;
22use crate::timer::Instance as TimerInstance; 21use crate::timer::Instance as TimerInstance;
23use crate::timer::Timer; 22use 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.
26pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 25pub 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.
290pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { 289pub 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