Skip to content

Commit a64004c

Browse files
committed
systick: System time counter based on Timer(systick)
1 parent 24286fa commit a64004c

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ pub mod signature;
152152
#[cfg(feature = "device-selected")]
153153
pub mod spi;
154154
#[cfg(feature = "device-selected")]
155+
pub mod systick;
156+
#[cfg(feature = "device-selected")]
155157
pub mod time;
156158
#[cfg(feature = "device-selected")]
157159
pub mod timer;

src/systick.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//! SYSTEMTIME based on systick
2+
3+
use cortex_m::peripheral::SYST;
4+
use cortex_m::interrupt::free;
5+
use cortex_m_rt::exception;
6+
7+
use crate::rcc::Clocks;
8+
use crate::time::Hertz;
9+
use crate::timer::{Timer,Event};
10+
11+
use embedded_hal::blocking::delay::{DelayMs,DelayUs};
12+
13+
pub trait SysTickTime {
14+
fn to_systemtime<T>(self, timeout: T, clocks: Clocks) -> SysTime
15+
where
16+
T: Into<Hertz>;
17+
}
18+
impl SysTickTime for SYST {
19+
fn to_systemtime<T>(self, timeout_hz: T, clocks: Clocks) -> SysTime
20+
where
21+
T: Into<Hertz>,
22+
{
23+
let timeout_hz = timeout_hz.into();
24+
25+
let mut systime = SysTickTimeStatic {
26+
countdown: Timer::syst(self,timeout_hz,clocks),
27+
systick: 0,
28+
tick_to_ns: 1_000_000_000 / timeout_hz.0,
29+
};
30+
31+
systime.countdown.listen(Event::TimeOut);
32+
33+
free(|_| unsafe { SYSTIME = Some(systime); });
34+
35+
SysTime {}
36+
}
37+
}
38+
39+
struct SysTickTimeStatic {
40+
countdown: Timer<SYST>,
41+
systick: u64,
42+
tick_to_ns: u32,
43+
}
44+
45+
// there can only be one!
46+
static mut SYSTIME: Option<SysTickTimeStatic> = None;
47+
48+
pub struct SysTime {}
49+
impl SysTime {
50+
/// return time in ns
51+
pub fn ns(&self) -> u64 {
52+
let mut tick_to_ns = 0u32;
53+
free(|_| unsafe {
54+
if let Some(systime) = &SYSTIME {
55+
tick_to_ns = systime.tick_to_ns;
56+
(&systime.systick as *const u64).read_volatile()
57+
} else {
58+
0
59+
}
60+
}) * tick_to_ns as u64
61+
}
62+
/// return time in us
63+
pub fn us(&self) -> u64 {
64+
self.ns() / 1_000_000
65+
}
66+
/// return time in ms
67+
pub fn ms(&self) -> u64 {
68+
self.ns() / 1_000_000
69+
}
70+
/// return time in seconds, as double
71+
pub fn s(&self) -> f64 {
72+
self.ns() as f64 / 1_000_000_000f64
73+
}
74+
75+
/// delay n ns
76+
/// note: this function depends on the systick interrupt,
77+
/// so do not use it from other interrupts (with higher priority).
78+
fn delay_ns_(&self, ns: u64) {
79+
let timeout = self.ns() + ns;
80+
while timeout >= self.ns() {}
81+
}
82+
}
83+
// Implement DelayUs/DelayMs for various integer types
84+
macro_rules! impl_DelayIntT {
85+
(for $($t:ty),+) => {$(
86+
impl DelayMs<$t> for SysTime {
87+
fn delay_ms(&mut self, ms: $t) {
88+
self.delay_ns_(ms as u64 * 1_000_000);
89+
}
90+
}
91+
impl DelayUs<$t> for SysTime {
92+
fn delay_us(&mut self, us: $t) {
93+
self.delay_ns_(us as u64 * 1_000);
94+
}
95+
}
96+
)*}
97+
}
98+
impl_DelayIntT!(for usize,u64,u32,u16,u8,i64,i32,i16,i8);
99+
100+
// there can only be one!
101+
#[exception]
102+
fn SysTick() {
103+
free(|_|unsafe {
104+
if let Some(systime) = &mut SYSTIME {
105+
systime.systick += 1;
106+
}
107+
});
108+
}
109+

0 commit comments

Comments
 (0)