stm32f1_hal/
time.rs

1//! Time units
2//!
3//! See [`Hertz`], [`KiloHertz`] and [`MegaHertz`] for creating increasingly higher frequencies.
4//!
5//! The [`fugit::ExtU32`] [`U32Ext`] trait adds various methods like `.Hz()`, `.MHz()`, etc to the `u32` primitive type,
6//! allowing it to be converted into frequencies.
7//!
8//! # Examples
9//!
10//! ## Create a 2 MHz frequency
11//!
12//! This example demonstrates various ways of creating a 2 MHz (2_000_000 Hz) frequency. They are
13//! all equivalent, however the `2.MHz()` variant should be preferred for readability.
14//!
15//! ```rust
16//! use stm32f1xx_hal::{
17//!     time::Hertz,
18//!     // Imports U32Ext trait
19//!     prelude::*,
20//! };
21//!
22//! let freq_hz = 2_000_000.Hz();
23//! let freq_khz = 2_000.kHz();
24//! let freq_mhz = 2.MHz();
25//!
26//! assert_eq!(freq_hz, freq_khz);
27//! assert_eq!(freq_khz, freq_mhz);
28//! ```
29
30#![allow(non_snake_case)]
31
32use core::ops;
33use cortex_m::peripheral::{DCB, DWT};
34
35use crate::rcc::Clocks;
36use waiter_trait::{Interval, TickInstant, TickWaiter};
37
38/// Bits per second
39#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)]
40pub struct Bps(pub u32);
41
42pub use fugit::{
43    Duration, HertzU32 as Hertz, KilohertzU32 as KiloHertz, MegahertzU32 as MegaHertz,
44    MicrosDurationU32 as MicroSeconds, MillisDurationU32 as MilliSeconds, NanosDurationU64,
45};
46
47/// Extension trait that adds convenience methods to the `u32` type
48pub trait U32Ext {
49    /// Wrap in `Bps`
50    fn bps(self) -> Bps;
51}
52
53impl U32Ext for u32 {
54    fn bps(self) -> Bps {
55        Bps(self)
56    }
57}
58
59pub const fn Hz(val: u32) -> Hertz {
60    Hertz::from_raw(val)
61}
62
63pub const fn kHz(val: u32) -> KiloHertz {
64    KiloHertz::from_raw(val)
65}
66
67pub const fn MHz(val: u32) -> MegaHertz {
68    MegaHertz::from_raw(val)
69}
70
71pub const fn ms(val: u32) -> MilliSeconds {
72    MilliSeconds::from_ticks(val)
73}
74
75pub const fn us(val: u32) -> MicroSeconds {
76    MicroSeconds::from_ticks(val)
77}
78
79/// Macro to implement arithmetic operations (e.g. multiplication, division)
80/// for wrapper types.
81macro_rules! impl_arithmetic {
82    ($wrapper:ty, $wrapped:ty) => {
83        impl ops::Mul<$wrapped> for $wrapper {
84            type Output = Self;
85            fn mul(self, rhs: $wrapped) -> Self {
86                Self(self.0 * rhs)
87            }
88        }
89
90        impl ops::MulAssign<$wrapped> for $wrapper {
91            fn mul_assign(&mut self, rhs: $wrapped) {
92                self.0 *= rhs;
93            }
94        }
95
96        impl ops::Div<$wrapped> for $wrapper {
97            type Output = Self;
98            fn div(self, rhs: $wrapped) -> Self {
99                Self(self.0 / rhs)
100            }
101        }
102
103        impl ops::Div<$wrapper> for $wrapper {
104            type Output = $wrapped;
105            fn div(self, rhs: $wrapper) -> $wrapped {
106                self.0 / rhs.0
107            }
108        }
109
110        impl ops::DivAssign<$wrapped> for $wrapper {
111            fn div_assign(&mut self, rhs: $wrapped) {
112                self.0 /= rhs;
113            }
114        }
115    };
116}
117
118impl_arithmetic!(Bps, u32);
119
120/// A monotonic non-decreasing timer
121///
122/// This uses the timer in the debug watch trace peripheral. This means, that if the
123/// core is stopped, the timer does not count up. This may be relevant if you are using
124/// cortex_m_semihosting::hprintln for debugging in which case the timer will be stopped
125/// while printing
126#[derive(Clone, Copy)]
127pub struct MonoTimer {
128    frequency: Hertz,
129}
130
131impl MonoTimer {
132    /// Creates a new `Monotonic` timer
133    pub fn new(mut dwt: DWT, mut dcb: DCB, clocks: &Clocks) -> Self {
134        dcb.enable_trace();
135        dwt.enable_cycle_counter();
136
137        // now the CYCCNT counter can't be stopped or reset
138
139        MonoTimer {
140            frequency: clocks.hclk(),
141        }
142    }
143
144    /// Returns the frequency at which the monotonic timer is operating at
145    pub fn frequency(self) -> Hertz {
146        self.frequency
147    }
148
149    /// Returns an `Instant` corresponding to "now"
150    pub fn now(self) -> Instant {
151        Instant {
152            now: DWT::cycle_count(),
153        }
154    }
155
156    pub fn waiter_us<I: Interval>(
157        &self,
158        timeout: MicroSeconds,
159        interval: I,
160    ) -> TickWaiter<DwtInstant, I, u32> {
161        TickWaiter::us(timeout.ticks(), interval, self.frequency.raw())
162    }
163
164    /// It can wait longer with a nanosecond timeout.
165    pub fn waiter_ns<I: Interval>(
166        &self,
167        timeout: NanosDurationU64,
168        interval: I,
169    ) -> TickWaiter<DwtInstant, I, u64> {
170        TickWaiter::ns(timeout.ticks(), interval, self.frequency.raw())
171    }
172}
173
174/// A measurement of a monotonically non-decreasing clock
175#[derive(Clone, Copy)]
176pub struct Instant {
177    now: u32,
178}
179
180impl Instant {
181    /// Ticks elapsed since the `Instant` was created
182    pub fn elapsed(self) -> u32 {
183        DWT::cycle_count().wrapping_sub(self.now)
184    }
185}
186
187// ----------------------------------------------------------------------------
188
189/// A `TickInstant` implementation
190#[derive(Copy, Clone)]
191pub struct DwtInstant {
192    tick: u32,
193}
194impl TickInstant for DwtInstant {
195    #[inline(always)]
196    fn now() -> Self {
197        Self {
198            tick: DWT::cycle_count(),
199        }
200    }
201
202    #[inline(always)]
203    fn tick_since(self, earlier: Self) -> u32 {
204        if self.tick >= earlier.tick {
205            self.tick - earlier.tick
206        } else {
207            self.tick + (u32::MAX - earlier.tick + 1)
208        }
209    }
210}