bl702_hal/
delay.rs

1//! Delays
2
3use core::convert::Infallible;
4use embedded_hal::delay::blocking::{DelayMs, DelayUs};
5
6/// Use RISCV machine-mode cycle counter (`mcycle`) as a delay provider.
7///
8/// This can be used for high resolution delays for device initialization,
9/// bit-banging protocols, etc
10#[derive(Copy, Clone)]
11pub struct McycleDelay {
12    core_frequency: u32,
13}
14
15impl McycleDelay {
16    /// Constructs the delay provider based on core clock frequency `freq`
17    pub fn new(freq: u32) -> Self {
18        Self {
19            /// System clock frequency, used to convert clock cycles
20            /// into real-world time values
21            core_frequency: freq,
22        }
23    }
24
25    /// Retrieves the cycle count for the current HART
26    #[inline]
27    pub fn get_cycle_count() -> u64 {
28        riscv::register::mcycle::read64()
29    }
30
31    /// Returns the number of elapsed cycles since `previous_cycle_count`
32    #[inline]
33    pub fn cycles_since(previous_cycle_count: u64) -> u64 {
34        riscv::register::mcycle::read64().wrapping_sub(previous_cycle_count)
35    }
36
37    /// Performs a busy-wait loop until the number of cycles `cycle_count` has elapsed
38    #[inline]
39    pub fn delay_cycles(cycle_count: u64) {
40        let start_cycle_count = McycleDelay::get_cycle_count();
41
42        while McycleDelay::cycles_since(start_cycle_count) <= cycle_count {}
43    }
44}
45
46impl DelayUs<u64> for McycleDelay {
47    type Error = Infallible;
48
49    /// Performs a busy-wait loop until the number of microseconds `us` has elapsed
50    #[inline]
51    fn delay_us(&mut self, us: u64) -> Result<(), Infallible> {
52        McycleDelay::delay_cycles((us * (self.core_frequency as u64)) / 1_000_000);
53
54        Ok(())
55    }
56}
57
58impl DelayMs<u64> for McycleDelay {
59    type Error = Infallible;
60
61    /// Performs a busy-wait loop until the number of milliseconds `ms` has elapsed
62    #[inline]
63    fn delay_ms(&mut self, ms: u64) -> Result<(), Infallible> {
64        McycleDelay::delay_cycles((ms * (self.core_frequency as u64)) / 1000);
65
66        Ok(())
67    }
68}