diff options
author | 2017-12-22 11:20:22 +0100 | |
---|---|---|
committer | 2017-12-23 19:08:04 +0100 | |
commit | 80328e98f361bd7ea07e3376691130790dae71a3 (patch) | |
tree | 24cb226132889f8b535a31d9a3babc766776afa8 /src/peripheral/syst.rs | |
parent | bdc7ca96c5593e410c8f49025d2b0fced7607a4d (diff) | |
download | cortex-m-80328e98f361bd7ea07e3376691130790dae71a3.tar.gz cortex-m-80328e98f361bd7ea07e3376691130790dae71a3.tar.zst cortex-m-80328e98f361bd7ea07e3376691130790dae71a3.zip |
revise peripheral API
closes #67
Diffstat (limited to 'src/peripheral/syst.rs')
-rw-r--r-- | src/peripheral/syst.rs | 135 |
1 files changed, 79 insertions, 56 deletions
diff --git a/src/peripheral/syst.rs b/src/peripheral/syst.rs index 3f96208..e02275d 100644 --- a/src/peripheral/syst.rs +++ b/src/peripheral/syst.rs @@ -2,6 +2,8 @@ use volatile_register::{RO, RW}; +use peripheral::SYST; + /// Register block #[repr(C)] pub struct RegisterBlock { @@ -34,39 +36,41 @@ const SYST_CSR_COUNTFLAG: u32 = 1 << 16; const SYST_CALIB_SKEW: u32 = 1 << 30; const SYST_CALIB_NOREF: u32 = 1 << 31; -impl RegisterBlock { - /// 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) } +impl SYST { + /// Clears current value to 0 + /// + /// After calling `clear_current()`, the next call to `has_wrapped()` + /// will return `false`. + pub fn clear_current(&mut self) { + unsafe { self.cvr.write(0) } } /// Disables counter - pub fn disable_counter(&self) { + pub fn disable_counter(&mut 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 + /// Disables SysTick interrupt + pub fn disable_interrupt(&mut self) { + unsafe { self.csr.modify(|v| v & !SYST_CSR_TICKINT) } } - /// Enables SysTick interrupt - pub fn enable_interrupt(&self) { - unsafe { self.csr.modify(|v| v | SYST_CSR_TICKINT) } + /// Enables counter + pub fn enable_counter(&mut self) { + unsafe { self.csr.modify(|v| v | SYST_CSR_ENABLE) } } - /// Disables SysTick interrupt - pub fn disable_interrupt(&self) { - unsafe { self.csr.modify(|v| v & !SYST_CSR_TICKINT) } + /// Enables SysTick interrupt + pub fn enable_interrupt(&mut self) { + unsafe { self.csr.modify(|v| v | SYST_CSR_TICKINT) } } /// Gets clock source - pub fn get_clock_source(&self) -> SystClkSource { + /// + /// *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`) + pub fn get_clock_source(&mut self) -> SystClkSource { + // NOTE(unsafe) atomic read with no side effects let clk_source_bit = self.csr.read() & SYST_CSR_CLKSOURCE != 0; match clk_source_bit { false => SystClkSource::External, @@ -74,51 +78,56 @@ impl RegisterBlock { } } - /// 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 current value + pub fn get_current() -> u32 { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).cvr.read() } } /// Gets reload value - pub fn get_reload(&self) -> u32 { - self.rvr.read() + pub fn get_reload() -> u32 { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).rvr.read() } } - /// Sets reload value + /// Returns the reload value with which the counter would wrap once per 10 + /// ms /// - /// Valid values are between `1` and `0x00ffffff`. - pub fn set_reload(&self, value: u32) { - unsafe { self.rvr.write(value) } + /// Returns `0` if the value is not known (e.g. because the clock can + /// change dynamically). + pub fn get_ticks_per_10ms() -> u32 { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).calib.read() & SYST_COUNTER_MASK } } - /// Gets current value - pub fn get_current(&self) -> u32 { - self.cvr.read() + /// Checks if an external reference clock is available + pub fn has_reference_clock() -> bool { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).calib.read() & SYST_CALIB_NOREF == 0 } } - /// Clears current value to 0 + /// Checks if the counter wrapped (underflowed) since the last check /// - /// After calling `clear_current()`, the next call to `has_wrapped()` - /// will return `false`. - pub fn clear_current(&self) { - unsafe { self.cvr.write(0) } + /// *NOTE* This takes `&mut self` because the read operation is side effectful and will clear + /// the bit of the read register. + pub fn has_wrapped(&mut self) -> bool { + self.csr.read() & SYST_CSR_COUNTFLAG != 0 } - /// Returns the reload value with which the counter would wrap once per 10 - /// ms + /// Checks if counter is enabled /// - /// 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 + /// *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`) + 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`) + pub fn is_interrupt_enabled(&mut self) -> bool { + self.csr.read() & SYST_CSR_TICKINT != 0 } /// Checks if the calibration value is precise @@ -126,12 +135,26 @@ impl RegisterBlock { /// 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 + pub fn is_precise() -> bool { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).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 + /// Sets clock source + 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`. + pub fn set_reload(&mut self, value: u32) { + unsafe { self.rvr.write(value) } + } + } |