1#![no_std]
9
10use cortex_m::peripheral::{syst::SystClkSource, SYST};
11pub use fugit::{self, ExtU64};
12use rtic_monotonic::Monotonic;
13
14pub struct Systick<const TIMER_HZ: u32> {
17 systick: SYST,
18 cnt: u64,
19}
20
21impl<const TIMER_HZ: u32> Systick<TIMER_HZ> {
22 pub fn new(mut systick: SYST, sysclk: u32) -> Self {
30 let reload = (sysclk + TIMER_HZ / 2) / TIMER_HZ - 1;
33
34 assert!(reload <= 0x00ff_ffff);
35 assert!(reload > 0);
36
37 systick.disable_counter();
38 systick.set_clock_source(SystClkSource::Core);
39 systick.set_reload(reload);
40
41 Systick { systick, cnt: 0 }
42 }
43}
44
45impl<const TIMER_HZ: u32> Monotonic for Systick<TIMER_HZ> {
46 const DISABLE_INTERRUPT_ON_EMPTY_QUEUE: bool = false;
47
48 type Instant = fugit::TimerInstantU64<TIMER_HZ>;
49 type Duration = fugit::TimerDurationU64<TIMER_HZ>;
50
51 fn now(&mut self) -> Self::Instant {
52 if self.systick.has_wrapped() {
53 self.cnt = self.cnt.wrapping_add(1);
54 }
55
56 Self::Instant::from_ticks(self.cnt)
57 }
58
59 unsafe fn reset(&mut self) {
60 self.systick.clear_current();
61 self.systick.enable_counter();
62 }
63
64 #[inline(always)]
65 fn set_compare(&mut self, _val: Self::Instant) {
66 }
68
69 #[inline(always)]
70 fn clear_compare_flag(&mut self) {
71 }
73
74 #[inline(always)]
75 fn zero() -> Self::Instant {
76 Self::Instant::from_ticks(0)
77 }
78
79 #[inline(always)]
80 fn on_interrupt(&mut self) {
81 if self.systick.has_wrapped() {
82 self.cnt = self.cnt.wrapping_add(1);
83 }
84 }
85}