groundhog_stm32g031/
lib.rs1#![no_std]
2
3pub use groundhog::RollingTimer;
4use embedded_hal::blocking::delay::{DelayUs, DelayMs};
5use core::sync::atomic::{AtomicPtr, Ordering};
6use stm32g0xx_hal::{
7 stm32::{
8 TIM2,
9 RCC,
10 tim2::RegisterBlock as Tim2Rb,
11 },
12};
13
14static TIMER_PTR: AtomicPtr<Tim2Rb> = AtomicPtr::new(core::ptr::null_mut());
15
16pub struct GlobalRollingTimer;
17
18impl GlobalRollingTimer {
19 pub const fn new() -> Self {
20 Self
21 }
22
23 pub fn init(timer: TIM2) {
24 let rcc = unsafe {&*RCC::ptr()};
25
26 rcc.apbenr1.modify(|_, w| w.tim2en().set_bit());
27 rcc.apbrstr1.modify(|_, w| w.tim2rst().set_bit());
28 rcc.apbrstr1.modify(|_, w| w.tim2rst().clear_bit());
29
30
31 timer.cr1.modify(|_, w| w.cen().clear_bit());
33 timer.cnt.reset();
35
36 timer.psc.write(|w| unsafe { w.psc().bits(63) });
39 timer.arr.write(|w| unsafe { w.bits(0xFFFFFFFF) });
40 timer.egr.write(|w| w.ug().set_bit());
41 timer.cr1.modify(|_, w| w.cen().set_bit().urs().set_bit());
42
43 let old_ptr = TIMER_PTR.load(Ordering::SeqCst);
45 TIMER_PTR.store(TIM2::ptr() as *mut _, Ordering::SeqCst);
46
47 debug_assert!(old_ptr == core::ptr::null_mut());
48 }
49}
50
51impl RollingTimer for GlobalRollingTimer {
77 type Tick = u32;
78 const TICKS_PER_SECOND: u32 = 1_000_000;
79
80 fn get_ticks(&self) -> u32 {
81 if let Some(t0) = unsafe { TIMER_PTR.load(Ordering::SeqCst).as_ref() } {
82 t0.cnt.read().bits()
83 } else {
84 0
85 }
86 }
87}
88
89impl DelayUs<u32> for GlobalRollingTimer {
90 fn delay_us(&mut self, us: u32) {
91 let start = self.get_ticks();
92 while self.ticks_since(start) < us { }
93 }
94}
95
96impl DelayMs<u32> for GlobalRollingTimer {
97 fn delay_ms(&mut self, ms: u32) {
98 for _ in 0..ms {
99 self.delay_us(1000)
100 }
101 }
102}