embedded_async_timer/impls/
stm32f103_rtc.rs1use bare_metal::CriticalSection;
4use core::sync::atomic::{self, Ordering};
5use stm32f1xx_hal::{
6 pac,
7 prelude::*,
8 rtc::Rtc,
9 stm32::{Interrupt, NVIC},
10};
11
12use crate::{AsyncTimer, Timer};
13
14const TICKS_PER_SECOND: u64 = 1000;
15
16#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Copy, Debug)]
18pub struct InstantU32(u32);
19
20#[derive(Clone)]
22pub struct DurationU32(u32);
23
24impl core::convert::From<core::time::Duration> for DurationU32 {
25 fn from(duration: core::time::Duration) -> Self {
26 Self(
27 ((duration.as_secs() as u64) * TICKS_PER_SECOND
28 + (duration.subsec_nanos() as u64) * TICKS_PER_SECOND / 1_000_000_000)
29 as u32,
30 )
31 }
32}
33
34impl core::ops::AddAssign<DurationU32> for InstantU32 {
35 fn add_assign(&mut self, duration: DurationU32) {
36 self.0 += duration.0;
37 }
38}
39
40impl core::ops::Add<DurationU32> for InstantU32 {
41 type Output = Self;
42
43 fn add(mut self, rhs: DurationU32) -> Self::Output {
44 self += rhs;
45 self
46 }
47}
48
49impl Timer for Rtc {
50 type Instant = InstantU32;
51 type Duration = DurationU32;
52
53 const DELTA: DurationU32 = DurationU32(2);
54
55 fn reset(&mut self) {
56 unsafe { NVIC::unmask(Interrupt::RTC) }
57 self.select_frequency((TICKS_PER_SECOND as u32).hz());
58 self.set_time(0);
59 }
60
61 #[inline(always)]
62 fn interrupt_free<F: FnOnce(&CriticalSection) -> R, R>(f: F) -> R {
63 cortex_m::interrupt::free(f)
64 }
65
66 #[inline(always)]
67 fn now(&self) -> Self::Instant {
68 InstantU32(self.current_time())
69 }
70
71 #[inline(always)]
72 fn disarm(&mut self) {
73 self.unlisten_alarm();
74 self.clear_alarm_flag();
75 }
76
77 #[inline(always)]
78 fn arm(&mut self, deadline: &Self::Instant) {
79 self.set_alarm(deadline.0);
81 self.clear_alarm_flag();
82 self.listen_alarm();
83 }
84}
85
86#[inline(always)]
102pub fn handle_interrupt<'a>(get_timer: impl FnOnce() -> &'a AsyncTimer<Rtc>) {
103 if swap_check() {
104 get_timer().awaken();
105 }
106}
107
108#[inline(always)]
109fn swap_check() -> bool {
110 stm32f1xx_hal::pac::RTC::borrow_unchecked(|rtc| {
111 if rtc.crl.read().alrf().bit() {
112 rtc.crl.modify(|_, w| w.alrf().clear_bit());
113 true
114 } else {
115 false
116 }
117 })
118}
119
120macro_rules! borrow_unchecked {
121 ($($peripheral:ident),*) => {
122 $(
123 unsafe impl BorrowUnchecked for pac::$peripheral {
124 #[inline(always)]
125 fn borrow_unchecked<T>(f: impl FnOnce(&Self) -> T) -> T {
126 let p = unsafe { core::mem::transmute(()) };
127 f(&p)
128 }
129 }
130 )*
131 }
132}
133
134unsafe trait BorrowUnchecked {
136 fn borrow_unchecked<T>(f: impl FnOnce(&Self) -> T) -> T;
137}
138
139borrow_unchecked!(RTC);