diff options
Diffstat (limited to 'src/peripheral/syst.rs')
-rw-r--r-- | src/peripheral/syst.rs | 185 |
1 files changed, 0 insertions, 185 deletions
diff --git a/src/peripheral/syst.rs b/src/peripheral/syst.rs deleted file mode 100644 index 345acc2..0000000 --- a/src/peripheral/syst.rs +++ /dev/null @@ -1,185 +0,0 @@ -//! SysTick: System Timer - -use volatile_register::{RO, RW}; - -use crate::peripheral::SYST; - -/// Register block -#[repr(C)] -pub struct RegisterBlock { - /// Control and Status - pub csr: RW<u32>, - /// Reload Value - pub rvr: RW<u32>, - /// Current Value - pub cvr: RW<u32>, - /// Calibration Value - pub calib: RO<u32>, -} - -/// SysTick clock source -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum SystClkSource { - /// Core-provided clock - Core, - /// External reference clock - External, -} - -const SYST_COUNTER_MASK: u32 = 0x00ff_ffff; - -const SYST_CSR_ENABLE: u32 = 1 << 0; -const SYST_CSR_TICKINT: u32 = 1 << 1; -const SYST_CSR_CLKSOURCE: u32 = 1 << 2; -const SYST_CSR_COUNTFLAG: u32 = 1 << 16; - -const SYST_CALIB_SKEW: u32 = 1 << 30; -const SYST_CALIB_NOREF: u32 = 1 << 31; - -impl SYST { - /// Clears current value to 0 - /// - /// After calling `clear_current()`, the next call to `has_wrapped()` will return `false`. - #[inline] - pub fn clear_current(&mut self) { - unsafe { self.cvr.write(0) } - } - - /// Disables counter - #[inline] - pub fn disable_counter(&mut self) { - unsafe { self.csr.modify(|v| v & !SYST_CSR_ENABLE) } - } - - /// Disables SysTick interrupt - #[inline] - pub fn disable_interrupt(&mut self) { - unsafe { self.csr.modify(|v| v & !SYST_CSR_TICKINT) } - } - - /// Enables counter - /// - /// *NOTE* The reference manual indicates that: - /// - /// "The SysTick counter reload and current value are undefined at reset, the correct - /// initialization sequence for the SysTick counter is: - /// - /// - Program reload value - /// - Clear current value - /// - Program Control and Status register" - /// - /// The sequence translates to `self.set_reload(x); self.clear_current(); self.enable_counter()` - #[inline] - pub fn enable_counter(&mut self) { - unsafe { self.csr.modify(|v| v | SYST_CSR_ENABLE) } - } - - /// Enables SysTick interrupt - #[inline] - pub fn enable_interrupt(&mut self) { - unsafe { self.csr.modify(|v| v | SYST_CSR_TICKINT) } - } - - /// Gets clock source - /// - /// *NOTE* This takes `&mut self` because the read operation is side effectful and can clear the - /// bit that indicates that the timer has wrapped (cf. `SYST.has_wrapped`) - #[inline] - pub fn get_clock_source(&mut self) -> SystClkSource { - // NOTE(unsafe) atomic read with no side effects - if self.csr.read() & SYST_CSR_CLKSOURCE != 0 { - SystClkSource::Core - } else { - SystClkSource::External - } - } - - /// Gets current value - #[inline] - pub fn get_current() -> u32 { - // NOTE(unsafe) atomic read with no side effects - unsafe { (*Self::PTR).cvr.read() } - } - - /// Gets reload value - #[inline] - pub fn get_reload() -> u32 { - // NOTE(unsafe) atomic read with no side effects - unsafe { (*Self::PTR).rvr.read() } - } - - /// Returns the reload value with which the counter would wrap once per 10 - /// ms - /// - /// Returns `0` if the value is not known (e.g. because the clock can - /// change dynamically). - #[inline] - pub fn get_ticks_per_10ms() -> u32 { - // NOTE(unsafe) atomic read with no side effects - unsafe { (*Self::PTR).calib.read() & SYST_COUNTER_MASK } - } - - /// Checks if an external reference clock is available - #[inline] - pub fn has_reference_clock() -> bool { - // NOTE(unsafe) atomic read with no side effects - unsafe { (*Self::PTR).calib.read() & SYST_CALIB_NOREF == 0 } - } - - /// Checks if the counter wrapped (underflowed) since the last check - /// - /// *NOTE* This takes `&mut self` because the read operation is side effectful and will clear - /// the bit of the read register. - #[inline] - pub fn has_wrapped(&mut self) -> bool { - self.csr.read() & SYST_CSR_COUNTFLAG != 0 - } - - /// Checks if counter is enabled - /// - /// *NOTE* This takes `&mut self` because the read operation is side effectful and can clear the - /// bit that indicates that the timer has wrapped (cf. `SYST.has_wrapped`) - #[inline] - pub fn is_counter_enabled(&mut self) -> bool { - self.csr.read() & SYST_CSR_ENABLE != 0 - } - - /// Checks if SysTick interrupt is enabled - /// - /// *NOTE* This takes `&mut self` because the read operation is side effectful and can clear the - /// bit that indicates that the timer has wrapped (cf. `SYST.has_wrapped`) - #[inline] - pub fn is_interrupt_enabled(&mut self) -> bool { - self.csr.read() & SYST_CSR_TICKINT != 0 - } - - /// Checks if the calibration value is precise - /// - /// Returns `false` if using the reload value returned by - /// `get_ticks_per_10ms()` may result in a period significantly deviating - /// from 10 ms. - #[inline] - pub fn is_precise() -> bool { - // NOTE(unsafe) atomic read with no side effects - unsafe { (*Self::PTR).calib.read() & SYST_CALIB_SKEW == 0 } - } - - /// Sets clock source - #[inline] - pub fn set_clock_source(&mut self, clk_source: SystClkSource) { - match clk_source { - SystClkSource::External => unsafe { self.csr.modify(|v| v & !SYST_CSR_CLKSOURCE) }, - SystClkSource::Core => unsafe { self.csr.modify(|v| v | SYST_CSR_CLKSOURCE) }, - } - } - - /// Sets reload value - /// - /// Valid values are between `1` and `0x00ffffff`. - /// - /// *NOTE* To make the timer wrap every `N` ticks set the reload value to `N - 1` - #[inline] - pub fn set_reload(&mut self, value: u32) { - unsafe { self.rvr.write(value) } - } -} |