From 51478caad843e4b0be1d1baf83d1f0e8c0d96a30 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 4 Mar 2023 05:25:57 +0100 Subject: [PATCH] nrf/timer: add support for counter mode. --- embassy-nrf/src/timer.rs | 43 +++++++++++++++++++++++++++++++++++----- 1 file 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> { irq.unpend(); irq.enable(); - Self::new_inner(timer) + Self::new_inner(timer, false) + } + + /// Create a new async-capable timer driver in counter mode. + pub fn new_awaitable_counter( + timer: impl Peripheral

+ 'd, + irq: impl Peripheral

+ 'd, + ) -> Self { + into_ref!(irq); + + irq.set_handler(Self::on_interrupt); + irq.unpend(); + irq.enable(); + + Self::new_inner(timer, true) } } @@ -142,7 +156,15 @@ impl<'d, T: Instance> Timer<'d, T, NotAwaitable> { /// This can be useful for triggering tasks via PPI /// `Uarte` uses this internally. pub fn new(timer: impl Peripheral

+ 'd) -> Self { - Self::new_inner(timer) + Self::new_inner(timer, false) + } + + /// Create a `Timer` driver in counter mode without an interrupt, meaning `Cc::wait` won't work. + /// + /// This can be useful for triggering tasks via PPI + /// `Uarte` uses this internally. + pub fn new_counter(timer: impl Peripheral

+ 'd) -> Self { + Self::new_inner(timer, true) } } @@ -150,7 +172,7 @@ 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 the public constructors. - fn new_inner(timer: impl Peripheral

+ 'd) -> Self { + fn new_inner(timer: impl Peripheral

+ 'd, is_counter: bool) -> Self { into_ref!(timer); let regs = T::regs(); @@ -164,8 +186,11 @@ impl<'d, T: Instance, I: TimerType> Timer<'d, T, I> { // since changing BITMODE while running can cause 'unpredictable behaviour' according to the specification. this.stop(); - // Set the instance to timer mode. - regs.mode.write(|w| w.mode().timer()); + if is_counter { + regs.mode.write(|w| w.mode().counter()); + } else { + regs.mode.write(|w| w.mode().timer()); + } // Make the counter's max value as high as possible. // 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> { Task::from_reg(&T::regs().tasks_clear) } + /// Returns the COUNT task, for use with PPI. + /// + /// When triggered, this task increments the timer's counter by 1. + /// Only works in counter mode. + pub fn task_count(&self) -> Task { + Task::from_reg(&T::regs().tasks_count) + } + /// Change the timer's frequency. /// /// This will stop the timer if it isn't already stopped,