aboutsummaryrefslogtreecommitdiff
path: root/src/peripheral/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/peripheral/mod.rs')
-rw-r--r--src/peripheral/mod.rs83
1 files changed, 78 insertions, 5 deletions
diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs
index dbe3e35..ffbb56c 100644
--- a/src/peripheral/mod.rs
+++ b/src/peripheral/mod.rs
@@ -1,5 +1,66 @@
//! Core peripherals
//!
+//! # API
+//!
+//! To use (most of) the peripheral API first you must get an *instance* of the peripheral. All the
+//! core peripherals are modeled as singletons (there can only ever be, at most, one instance of
+//! them at any given point in time) and the only way to get an instance of them is through the
+//! [`Peripherals::take`](struct.Peripherals.html#method.take) method.
+//!
+//! ``` no_run
+//! extern crate cortex_m;
+//!
+//! use cortex_m::peripheral::Peripherals;
+//!
+//! fn main() {
+//! let mut peripherals = Peripherals::take().unwrap();
+//! peripherals.DWT.enable_cycle_counter();
+//! }
+//! ```
+//!
+//! This method can only be successfully called *once* -- this is why the method returns an
+//! `Option`. Subsequent calls to the method will result in a `None` value being returned.
+//!
+//! A part of the peripheral API doesn't require access to a peripheral instance. This part of the
+//! API is provided as static methods on the peripheral types. One example is the
+//! [`DWT::cyccnt`](struct.DWT.html#method.cyccnt) method.
+//!
+//! ``` no_run
+//! extern crate cortex_m;
+//!
+//! use cortex_m::peripheral::{DWT, Peripherals};
+//!
+//! fn main() {
+//! {
+//! let mut peripherals = Peripherals::take().unwrap();
+//! peripherals.DWT.enable_cycle_counter();
+//! } // all the peripheral singletons are destroyed here
+//!
+//! // but this method can be called without a DWT instance
+//! let cyccnt = DWT::get_cycle_count();
+//! }
+//! ```
+//!
+//! The singleton property can be *unsafely* bypassed using the `ptr` static method which is
+//! available on all the peripheral types. This method is a useful building block for implementing
+//! higher level and safe abstractions.
+//!
+//! ``` no_run
+//! extern crate cortex_m;
+//!
+//! use cortex_m::peripheral::{DWT, Peripherals};
+//!
+//! fn main() {
+//! {
+//! let mut peripherals = Peripherals::take().unwrap();
+//! peripherals.DWT.enable_cycle_counter();
+//! } // all the peripheral singletons are destroyed here
+//!
+//! // actually safe because this is an atomic read with no side effects
+//! let cyccnt = unsafe { (*DWT::ptr()).cyccnt.read() };
+//! }
+//! ```
+//!
//! # References
//!
//! - ARMv7-M Architecture Reference Manual (Issue E.b) - Chapter B3
@@ -9,7 +70,7 @@
#![allow(private_no_mangle_statics)]
use core::marker::PhantomData;
-use core::ops::Deref;
+use core::ops::{Deref, DerefMut};
use interrupt;
@@ -69,7 +130,7 @@ static mut CORE_PERIPHERALS: bool = false;
impl Peripherals {
/// Returns all the core peripherals *once*
- #[inline(always)]
+ #[inline]
pub fn take() -> Option<Self> {
interrupt::free(|_| {
if unsafe { CORE_PERIPHERALS } {
@@ -80,7 +141,7 @@ impl Peripherals {
})
}
- /// Unchecked version of `Peripherals::steal`
+ /// Unchecked version of `Peripherals::take`
pub unsafe fn steal() -> Self {
debug_assert!(!CORE_PERIPHERALS);
@@ -136,6 +197,12 @@ pub struct CBP {
#[cfg(armv7m)]
impl CBP {
+ pub(crate) unsafe fn new() -> Self {
+ CBP {
+ _marker: PhantomData,
+ }
+ }
+
/// Returns a pointer to the register block
pub fn ptr() -> *const self::cbp::RegisterBlock {
0xE000_EF50 as *const _
@@ -262,8 +329,8 @@ pub struct ITM {
impl ITM {
/// Returns a pointer to the register block
- pub fn ptr() -> *const itm::RegisterBlock {
- 0xE000_0000 as *const _
+ pub fn ptr() -> *mut itm::RegisterBlock {
+ 0xE000_0000 as *mut _
}
}
@@ -275,6 +342,12 @@ impl Deref for ITM {
}
}
+impl DerefMut for ITM {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe { &mut *Self::ptr() }
+ }
+}
+
/// Memory Protection Unit
pub struct MPU {
_marker: PhantomData<*const ()>,