groundhog_stm32g031/
lib.rs

1#![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        // pause
32        timer.cr1.modify(|_, w| w.cen().clear_bit());
33        // reset counter
34        timer.cnt.reset();
35
36        // Calculate counter configuration
37
38        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        // TODO: Critical section?
44        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
51// impl Monotonic for GlobalRollingTimer {
52//     type Instant = i32;
53
54//     fn ratio() -> Fraction {
55//         Fraction {
56//             numerator: 64,
57//             denominator: 1,
58//         }
59//     }
60
61//     fn now() -> Self::Instant {
62//         Self::new().get_ticks() as i32
63//     }
64
65//     fn zero() -> Self::Instant {
66//         0
67//     }
68
69//     unsafe fn reset() {
70//         if let Some(t0) = TIMER_PTR.load(Ordering::SeqCst).as_ref() {
71//             t0.tasks_clear.write(|w| w.bits(1));
72//         }
73//     }
74// }
75
76impl 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}