diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-03-04 05:25:57 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-03-04 05:37:33 +0100 |
| commit | 51478caad843e4b0be1d1baf83d1f0e8c0d96a30 (patch) | |
| tree | 8351cd0038efd9dea260d586b41eccdba1f999a6 | |
| parent | 4314b823aaadc54387fbc1379f89300c70007d83 (diff) | |
nrf/timer: add support for counter mode.
| -rw-r--r-- | embassy-nrf/src/timer.rs | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index d1ae57237..3b0d2f1ca 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs | |||
| @@ -132,7 +132,21 @@ impl<'d, T: Instance> Timer<'d, T, Awaitable> { | |||
| 132 | irq.unpend(); | 132 | irq.unpend(); |
| 133 | irq.enable(); | 133 | irq.enable(); |
| 134 | 134 | ||
| 135 | Self::new_inner(timer) | 135 | Self::new_inner(timer, false) |
| 136 | } | ||
| 137 | |||
| 138 | /// Create a new async-capable timer driver in counter mode. | ||
| 139 | pub fn new_awaitable_counter( | ||
| 140 | timer: impl Peripheral<P = T> + 'd, | ||
| 141 | irq: impl Peripheral<P = T::Interrupt> + 'd, | ||
| 142 | ) -> Self { | ||
| 143 | into_ref!(irq); | ||
| 144 | |||
| 145 | irq.set_handler(Self::on_interrupt); | ||
| 146 | irq.unpend(); | ||
| 147 | irq.enable(); | ||
| 148 | |||
| 149 | Self::new_inner(timer, true) | ||
| 136 | } | 150 | } |
| 137 | } | 151 | } |
| 138 | 152 | ||
| @@ -142,7 +156,15 @@ impl<'d, T: Instance> Timer<'d, T, NotAwaitable> { | |||
| 142 | /// This can be useful for triggering tasks via PPI | 156 | /// This can be useful for triggering tasks via PPI |
| 143 | /// `Uarte` uses this internally. | 157 | /// `Uarte` uses this internally. |
| 144 | pub fn new(timer: impl Peripheral<P = T> + 'd) -> Self { | 158 | pub fn new(timer: impl Peripheral<P = T> + 'd) -> Self { |
| 145 | Self::new_inner(timer) | 159 | Self::new_inner(timer, false) |
| 160 | } | ||
| 161 | |||
| 162 | /// Create a `Timer` driver in counter mode without an interrupt, meaning `Cc::wait` won't work. | ||
| 163 | /// | ||
| 164 | /// This can be useful for triggering tasks via PPI | ||
| 165 | /// `Uarte` uses this internally. | ||
| 166 | pub fn new_counter(timer: impl Peripheral<P = T> + 'd) -> Self { | ||
| 167 | Self::new_inner(timer, true) | ||
| 146 | } | 168 | } |
| 147 | } | 169 | } |
| 148 | 170 | ||
| @@ -150,7 +172,7 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> { | |||
| 150 | /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work. | 172 | /// Create a `Timer` without an interrupt, meaning `Cc::wait` won't work. |
| 151 | /// | 173 | /// |
| 152 | /// This is used by the public constructors. | 174 | /// This is used by the public constructors. |
| 153 | fn new_inner(timer: impl Peripheral<P = T> + 'd) -> Self { | 175 | fn new_inner(timer: impl Peripheral<P = T> + 'd, is_counter: bool) -> Self { |
| 154 | into_ref!(timer); | 176 | into_ref!(timer); |
| 155 | 177 | ||
| 156 | let regs = T::regs(); | 178 | let regs = T::regs(); |
| @@ -164,8 +186,11 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> { | |||
| 164 | // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. | 186 | // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. |
| 165 | this.stop(); | 187 | this.stop(); |
| 166 | 188 | ||
| 167 | // Set the instance to timer mode. | 189 | if is_counter { |
| 168 | regs.mode.write(|w| w.mode().timer()); | 190 | regs.mode.write(|w| w.mode().counter()); |
| 191 | } else { | ||
| 192 | regs.mode.write(|w| w.mode().timer()); | ||
| 193 | } | ||
| 169 | 194 | ||
| 170 | // Make the counter's max value as high as possible. | 195 | // Make the counter's max value as high as possible. |
| 171 | // TODO: is there a reason someone would want to set this lower? | 196 | // TODO: is there a reason someone would want to set this lower? |
| @@ -225,6 +250,14 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> { | |||
| 225 | Task::from_reg(&T::regs().tasks_clear) | 250 | Task::from_reg(&T::regs().tasks_clear) |
| 226 | } | 251 | } |
| 227 | 252 | ||
| 253 | /// Returns the COUNT task, for use with PPI. | ||
| 254 | /// | ||
| 255 | /// When triggered, this task increments the timer's counter by 1. | ||
| 256 | /// Only works in counter mode. | ||
| 257 | pub fn task_count(&self) -> Task { | ||
| 258 | Task::from_reg(&T::regs().tasks_count) | ||
| 259 | } | ||
| 260 | |||
| 228 | /// Change the timer's frequency. | 261 | /// Change the timer's frequency. |
| 229 | /// | 262 | /// |
| 230 | /// This will stop the timer if it isn't already stopped, | 263 | /// This will stop the timer if it isn't already stopped, |
