aboutsummaryrefslogtreecommitdiff
path: root/src/peripheral/syst.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/peripheral/syst.rs')
-rw-r--r--src/peripheral/syst.rs135
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) }
+ }
+
}