cortex-m 0.1.8

Low level access to Cortex-M processors
Documentation
//! Processor core registers
//!
//! The following registers can only be accessed in PRIVILEGED mode:
//!
//! - MSP
//! - IPSR
//! - EPSR
//! - PRIMASK
//! - FAULTMASK
//! - BASEPRI
//! - CONTROL
//!
//! The rest of registers (see list below) can be accessed in either, PRIVILEGED or UNPRIVILEGED,
//! mode.
//!
//! - PSP
//! - LR
//! - PC
//! - APSR
//!
//! # Caveats
//!
//! - The API doesn't check if the value passed to `write` is valid (e.g. reserved bits are not
//!   modified) or not. It's up to the user to verify that.
//!
//! # References
//!
//! - Cortex-M* Devices Generic User Guide - Section 2.1.3 Core registers

// NOTE all the functions here are `always(inline)` to prevent a function call which may change the
// contents of the core registers.

macro_rules! sr {
    ($name:ident) => {
        /// Reads the special register
        #[inline(always)]
        pub unsafe fn read() -> u32 {
            let r: u32;
            match () {
                #[cfg(target_arch = "arm")]
                () => asm!(concat!("mrs ", "$0,", stringify!($name)) : "=r"(r) ::: "volatile"),

                #[cfg(not(target_arch = "arm"))]
                () => r = 0,
            }
            r
        }
    };
}

macro_rules! srw {
    (#[$attr:meta] $name:ident) => {
        #[$attr]
        pub mod $name {
            sr!($name);

            /// Writes to the special register
            #[inline(always)]
            pub unsafe fn write(r: u32) {
                match r {
                    #[cfg(target_arch = "arm")]
                    _ => asm!(concat!("msr ", stringify!($name), ",$0") :: "r"(r) ::: "volatile"),

                    #[cfg(not(target_arch = "arm"))]
                    _ => {},
                }
            }
        }
    };
}

macro_rules! sro {
    (#[$attr:meta] $name:ident) => {
        #[$attr]
        pub mod $name {
            sr!($name);
        }
    }
}

macro_rules! rw {
    (#[$attr:meta] $name:ident : $r:ident) => {
        #[$attr]
        pub mod $name {
            /// Reads the special register
            #[inline(always)]
            pub unsafe fn read() -> u32 {
                let r: u32;
                match () {
                    #[cfg(target_arch = "arm")]
                    () => asm!(concat!("mov ", "$0,", stringify!($r)) : "=r"(r) ::: "volatile"),

                    #[cfg(not(target_arch = "arm"))]
                    () => r = 0,
                }
                r
            }

            /// Writes to the special register
            #[inline(always)]
            pub unsafe fn write(r: u32) {
                match r {
                    #[cfg(target_arch = "arm")]
                    _ => asm!(concat!("mov ", stringify!($r), ",$0") :: "r"(r) ::: "volatile"),

                    #[cfg(not(target_arch = "arm"))]
                    _ => {}
                }
            }
        }
    }
}

srw!(#[doc = "Main Stack Pointer"] msp);
srw!(#[doc = "Process Stack Pointer"] psp);
rw!(#[doc = "Link Register"] lr: r14);
rw!(#[doc = "Program Counter"] pc: r15);
srw!(#[doc = "Application Program Status Register"] apsr);
sro!(#[doc = "Interrupt Program Status Register"] ipsr);
sro!(#[doc = "Exception Program Status Register"] epsr);
srw!(#[doc = "Priority Mask Register"] primask);
srw!(#[doc = "Fault Mask Register"] faultmask);
srw!(#[doc = "Base Priority Mask Register"] basepri);
srw!(#[doc = "Control Register"] control);