stm32f1xx_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;
36
37/// Bits per second
38#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)]
39pub struct Bps(pub u32);
40
41pub use fugit::{
42    HertzU32 as Hertz, KilohertzU32 as KiloHertz, MegahertzU32 as MegaHertz,
43    MicrosDurationU32 as MicroSeconds, MillisDurationU32 as MilliSeconds,
44};
45
46/// Extension trait that adds convenience methods to the `u32` type
47pub trait U32Ext {
48    /// Wrap in `Bps`
49    fn bps(self) -> Bps;
50}
51
52impl U32Ext for u32 {
53    fn bps(self) -> Bps {
54        Bps(self)
55    }
56}
57
58pub const fn Hz(val: u32) -> Hertz {
59    Hertz::from_raw(val)
60}
61
62pub const fn kHz(val: u32) -> KiloHertz {
63    KiloHertz::from_raw(val)
64}
65
66pub const fn MHz(val: u32) -> MegaHertz {
67    MegaHertz::from_raw(val)
68}
69
70pub const fn ms(val: u32) -> MilliSeconds {
71    MilliSeconds::from_ticks(val)
72}
73
74pub const fn us(val: u32) -> MicroSeconds {
75    MicroSeconds::from_ticks(val)
76}
77
78/// Macro to implement arithmetic operations (e.g. multiplication, division)
79/// for wrapper types.
80macro_rules! impl_arithmetic {
81    ($wrapper:ty, $wrapped:ty) => {
82        impl ops::Mul<$wrapped> for $wrapper {
83            type Output = Self;
84            fn mul(self, rhs: $wrapped) -> Self {
85                Self(self.0 * rhs)
86            }
87        }
88
89        impl ops::MulAssign<$wrapped> for $wrapper {
90            fn mul_assign(&mut self, rhs: $wrapped) {
91                self.0 *= rhs;
92            }
93        }
94
95        impl ops::Div<$wrapped> for $wrapper {
96            type Output = Self;
97            fn div(self, rhs: $wrapped) -> Self {
98                Self(self.0 / rhs)
99            }
100        }
101
102        impl ops::Div<$wrapper> for $wrapper {
103            type Output = $wrapped;
104            fn div(self, rhs: $wrapper) -> $wrapped {
105                self.0 / rhs.0
106            }
107        }
108
109        impl ops::DivAssign<$wrapped> for $wrapper {
110            fn div_assign(&mut self, rhs: $wrapped) {
111                self.0 /= rhs;
112            }
113        }
114    };
115}
116
117impl_arithmetic!(Bps, u32);
118
119/// A monotonic non-decreasing timer
120///
121/// This uses the timer in the debug watch trace peripheral. This means, that if the
122/// core is stopped, the timer does not count up. This may be relevant if you are using
123/// cortex_m_semihosting::hprintln for debugging in which case the timer will be stopped
124/// while printing
125#[derive(Clone, Copy)]
126pub struct MonoTimer {
127    frequency: Hertz,
128}
129
130impl MonoTimer {
131    /// Creates a new `Monotonic` timer
132    pub fn new(mut dwt: DWT, mut dcb: DCB, clocks: &Clocks) -> Self {
133        dcb.enable_trace();
134        dwt.enable_cycle_counter();
135
136        // now the CYCCNT counter can't be stopped or reset
137
138        MonoTimer {
139            frequency: clocks.hclk(),
140        }
141    }
142
143    /// Returns the frequency at which the monotonic timer is operating at
144    pub fn frequency(self) -> Hertz {
145        self.frequency
146    }
147
148    /// Returns an `Instant` corresponding to "now"
149    pub fn now(self) -> Instant {
150        Instant {
151            now: DWT::cycle_count(),
152        }
153    }
154}
155
156/// A measurement of a monotonically non-decreasing clock
157#[derive(Clone, Copy)]
158pub struct Instant {
159    now: u32,
160}
161
162impl Instant {
163    /// Ticks elapsed since the `Instant` was created
164    pub fn elapsed(self) -> u32 {
165        DWT::cycle_count().wrapping_sub(self.now)
166    }
167}