aboutsummaryrefslogtreecommitdiff
path: root/src/ostimer.rs
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2025-11-14 17:29:31 +0100
committerJames Munns <[email protected]>2025-11-14 17:29:31 +0100
commite799d6c8956ed3ea5ced65d58c3065a22927ad10 (patch)
tree05db757ce7d739c9f7a92905406bae08e3a281e1 /src/ostimer.rs
parent9b91d886e6a5067d6a553715a053db653af55ca6 (diff)
More work on examples
Diffstat (limited to 'src/ostimer.rs')
-rw-r--r--src/ostimer.rs62
1 files changed, 36 insertions, 26 deletions
diff --git a/src/ostimer.rs b/src/ostimer.rs
index 8bc68389a..efa534194 100644
--- a/src/ostimer.rs
+++ b/src/ostimer.rs
@@ -29,8 +29,13 @@
29 29
30use core::sync::atomic::{AtomicBool, Ordering}; 30use core::sync::atomic::{AtomicBool, Ordering};
31 31
32use embassy_hal_internal::{Peri, PeripheralType};
33
34use crate::clocks::periph_helpers::{OsTimerConfig, OstimerClockSel};
35use crate::clocks::{assert_reset, enable_and_reset, is_reset_released, release_reset, Gate, PoweredClock};
32use crate::interrupt::InterruptExt; 36use crate::interrupt::InterruptExt;
33use crate::pac; 37use crate::pac;
38use crate::peripherals::OSTIMER0;
34 39
35// PAC defines the shared RegisterBlock under `ostimer0`. 40// PAC defines the shared RegisterBlock under `ostimer0`.
36type Regs = pac::ostimer0::RegisterBlock; 41type Regs = pac::ostimer0::RegisterBlock;
@@ -197,16 +202,16 @@ impl<'d> Alarm<'d> {
197pub struct Config { 202pub struct Config {
198 /// Initialize MATCH registers to their max values and mask/clear the interrupt flag. 203 /// Initialize MATCH registers to their max values and mask/clear the interrupt flag.
199 pub init_match_max: bool, 204 pub init_match_max: bool,
200 /// OSTIMER clock frequency in Hz (must match the actual hardware clock) 205 pub power: PoweredClock,
201 pub clock_frequency_hz: u64, 206 pub source: OstimerClockSel,
202} 207}
203 208
204impl Default for Config { 209impl Default for Config {
205 fn default() -> Self { 210 fn default() -> Self {
206 Self { 211 Self {
207 init_match_max: true, 212 init_match_max: true,
208 // Default to 1MHz - user should override this with actual frequency 213 power: PoweredClock::NormalEnabledDeepSleepDisabled,
209 clock_frequency_hz: 1_000_000, 214 source: OstimerClockSel::Clk1M,
210 } 215 }
211 } 216 }
212} 217}
@@ -222,8 +227,16 @@ impl<'d, I: Instance> Ostimer<'d, I> {
222 /// Construct OSTIMER handle. 227 /// Construct OSTIMER handle.
223 /// Requires clocks for the instance to be enabled by the board before calling. 228 /// Requires clocks for the instance to be enabled by the board before calling.
224 /// Does not enable NVIC or INTENA; use time_driver::init() for async operation. 229 /// Does not enable NVIC or INTENA; use time_driver::init() for async operation.
225 pub fn new(_inst: impl Instance, cfg: Config, _p: &'d crate::pac::Peripherals) -> Self { 230 pub fn new(_inst: Peri<'d, I>, cfg: Config) -> Self {
226 assert!(cfg.clock_frequency_hz > 0, "OSTIMER frequency must be greater than 0"); 231 let clock_freq = unsafe {
232 enable_and_reset::<I>(&OsTimerConfig {
233 power: cfg.power,
234 source: cfg.source,
235 })
236 .expect("Enabling OsTimer clock should not fail")
237 };
238
239 assert!(clock_freq > 0, "OSTIMER frequency must be greater than 0");
227 240
228 if cfg.init_match_max { 241 if cfg.init_match_max {
229 let r: &Regs = unsafe { &*I::ptr() }; 242 let r: &Regs = unsafe { &*I::ptr() };
@@ -233,7 +246,7 @@ impl<'d, I: Instance> Ostimer<'d, I> {
233 246
234 Self { 247 Self {
235 _inst: core::marker::PhantomData, 248 _inst: core::marker::PhantomData,
236 clock_frequency_hz: cfg.clock_frequency_hz, 249 clock_frequency_hz: clock_freq as u64,
237 _phantom: core::marker::PhantomData, 250 _phantom: core::marker::PhantomData,
238 } 251 }
239 } 252 }
@@ -260,7 +273,7 @@ impl<'d, I: Instance> Ostimer<'d, I> {
260 /// # Safety 273 /// # Safety
261 /// This operation will reset the entire OSTIMER peripheral. Any active alarms 274 /// This operation will reset the entire OSTIMER peripheral. Any active alarms
262 /// or time_driver operations will be disrupted. Use with caution. 275 /// or time_driver operations will be disrupted. Use with caution.
263 pub fn reset(&self, peripherals: &crate::pac::Peripherals) { 276 pub fn reset(&self, _peripherals: &crate::pac::Peripherals) {
264 critical_section::with(|_| { 277 critical_section::with(|_| {
265 let r: &Regs = unsafe { &*I::ptr() }; 278 let r: &Regs = unsafe { &*I::ptr() };
266 279
@@ -270,19 +283,17 @@ impl<'d, I: Instance> Ostimer<'d, I> {
270 .write(|w| w.ostimer_intrflag().clear_bit_by_one().ostimer_intena().clear_bit()); 283 .write(|w| w.ostimer_intrflag().clear_bit_by_one().ostimer_intena().clear_bit());
271 284
272 unsafe { 285 unsafe {
273 crate::reset::assert::<crate::reset::line::Ostimer0>(peripherals); 286 assert_reset::<OSTIMER0>();
274 }
275 287
276 for _ in 0..RESET_STABILIZE_SPINS { 288 for _ in 0..RESET_STABILIZE_SPINS {
277 cortex_m::asm::nop(); 289 cortex_m::asm::nop();
278 } 290 }
279 291
280 unsafe { 292 release_reset::<OSTIMER0>();
281 crate::reset::release::<crate::reset::line::Ostimer0>(peripherals);
282 }
283 293
284 while !<crate::reset::line::Ostimer0 as crate::reset::ResetLine>::is_released(&peripherals.mrcc0) { 294 while !is_reset_released::<OSTIMER0>() {
285 cortex_m::asm::nop(); 295 cortex_m::asm::nop();
296 }
286 } 297 }
287 298
288 for _ in 0..RESET_STABILIZE_SPINS { 299 for _ in 0..RESET_STABILIZE_SPINS {
@@ -469,14 +480,13 @@ fn now_ticks_read() -> u64 {
469 // Read high then low to minimize incoherent snapshots 480 // Read high then low to minimize incoherent snapshots
470 let hi = (r.evtimerh().read().evtimer_count_value().bits() as u64) & (EVTIMER_HI_MASK as u64); 481 let hi = (r.evtimerh().read().evtimer_count_value().bits() as u64) & (EVTIMER_HI_MASK as u64);
471 let lo = r.evtimerl().read().evtimer_count_value().bits() as u64; 482 let lo = r.evtimerl().read().evtimer_count_value().bits() as u64;
472
473 // Combine and convert from Gray code to binary 483 // Combine and convert from Gray code to binary
474 let gray = lo | (hi << EVTIMER_HI_SHIFT); 484 let gray = lo | (hi << EVTIMER_HI_SHIFT);
475 gray_to_bin(gray) 485 gray_to_bin(gray)
476} 486}
477 487
478// Instance trait like other drivers, providing a PAC pointer for this OSTIMER instance 488// Instance trait like other drivers, providing a PAC pointer for this OSTIMER instance
479pub trait Instance { 489pub trait Instance: Gate<MrccPeriphConfig = OsTimerConfig> + PeripheralType {
480 fn ptr() -> *const Regs; 490 fn ptr() -> *const Regs;
481} 491}
482 492
@@ -491,12 +501,12 @@ impl Instance for crate::peripherals::OSTIMER0 {
491} 501}
492 502
493// Also implement Instance for the Peri wrapper type 503// Also implement Instance for the Peri wrapper type
494impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::OSTIMER0> { 504// impl Instance for embassy_hal_internal::Peri<'_, crate::peripherals::OSTIMER0> {
495 #[inline(always)] 505// #[inline(always)]
496 fn ptr() -> *const Regs { 506// fn ptr() -> *const Regs {
497 pac::Ostimer0::ptr() 507// pac::Ostimer0::ptr()
498 } 508// }
499} 509// }
500 510
501#[inline(always)] 511#[inline(always)]
502fn bin_to_gray(x: u64) -> u64 { 512fn bin_to_gray(x: u64) -> u64 {