diff options
author | 2017-04-30 09:49:52 +0000 | |
---|---|---|
committer | 2017-04-30 09:49:59 +0000 | |
commit | a9967c544da4ddc7575135ed522dffd21ec28c19 (patch) | |
tree | ea5e2f7441b78d7b36095b1e41ff51e860a32fac /src | |
parent | 14ec12b8f9ccb9fa26ec0b896941330e985c35e7 (diff) | |
download | cortex-m-a9967c544da4ddc7575135ed522dffd21ec28c19.tar.gz cortex-m-a9967c544da4ddc7575135ed522dffd21ec28c19.tar.zst cortex-m-a9967c544da4ddc7575135ed522dffd21ec28c19.zip |
Implement a complete high-level wrapper for SYST.
Diffstat (limited to 'src')
-rw-r--r-- | src/peripheral/mod.rs | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 78ddfdb..e7d0c18 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -437,6 +437,126 @@ pub struct Syst { pub calib: RO<u32>, } +/// SysTick clock source +pub enum SystClkSource { + /// Core-provided clock + Core, + /// External reference clock + External +} + +const SYST_COUNTER_MASK: u32 = 0x00ffffff; + +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 { + /// Checks if counter is enabled + pub fn is_counter_enabled(&self) -> bool { + self.csr.read() & SYST_CSR_ENABLE != 0 + } + + /// Enables counter + pub fn enable_counter(&self) { + unsafe { self.csr.modify(|v| v | SYST_CSR_ENABLE) } + } + + /// Disables counter + pub fn disable_counter(&self) { + unsafe { self.csr.modify(|v| v & !SYST_CSR_ENABLE) } + } + + /// Checks if SysTick interrupt is enabled + pub fn is_interrupt_enabled(&self) -> bool { + self.csr.read() & SYST_CSR_TICKINT != 0 + } + + /// Enables SysTick interrupt + pub fn enable_interrupt(&self) { + unsafe { self.csr.modify(|v| v | SYST_CSR_TICKINT) } + } + + /// Disables SysTick interrupt + pub fn disable_interrupt(&self) { + unsafe { self.csr.modify(|v| v & !SYST_CSR_TICKINT) } + } + + /// Gets clock source + pub fn get_clock_source(&self) -> SystClkSource { + let clk_source_bit = self.csr.read() & SYST_CSR_CLKSOURCE != 0; + match clk_source_bit { + false => SystClkSource::External, + true => SystClkSource::Core + } + } + + /// Sets clock source + pub fn set_clock_source(&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) } + } + } + + /// Checks if the counter wrapped (underflowed) since the last check + pub fn has_wrapped(&self) -> bool { + self.csr.read() & SYST_CSR_COUNTFLAG != 0 + } + + /// Gets reload value + pub fn get_reload(&self) -> u32 { + self.rvr.read() + } + + /// Sets reload value + /// + /// Valid values are between `1` and `0x00ffffff`. + pub fn set_reload(&self, value: u32) { + unsafe { self.rvr.write(value) } + } + + /// Gets current value + pub fn get_current(&self) -> u32 { + self.cvr.read() + } + + /// Clears current value to 0 + /// + /// After calling `clear_current()`, the next call to `has_wrapped()` + /// will return `false`. + pub fn clear_current(&self) { + unsafe { self.cvr.write(0) } + } + + /// 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). + pub fn get_ticks_per_10ms(&self) -> u32 { + self.calib.read() & SYST_COUNTER_MASK + } + + /// 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. + pub fn is_precise(&self) -> bool { + self.calib.read() & SYST_CALIB_SKEW == 0 + } + + /// Checks if an external reference clock is available + pub fn has_reference_clock(&self) -> bool { + self.calib.read() & SYST_CALIB_NOREF == 0 + } +} + /// TPIU register block #[repr(C)] pub struct Tpiu { |