diff options
41 files changed, 511 insertions, 103 deletions
@@ -7,13 +7,28 @@ keywords = ["arm", "cortex-m", "register", "peripheral"] license = "MIT OR Apache-2.0" name = "cortex-m" repository = "https://github.com/japaric/cortex-m" -version = "0.4.3" +version = "0.4.4" + +[build-dependencies] +cc = "1.0.10" [dependencies] -aligned = "0.1.1" -bare-metal = "0.1.0" volatile-register = "0.2.0" -untagged-option = "0.1.1" + +[dependencies.aligned] +default-features = false +version = "0.1.2" + +[dependencies.bare-metal] +default-features = false +version = "0.1.2" + +[dependencies.untagged-option] +optional = true +version = "0.1.1" [features] cm7-r0p1 = [] +default = ["inline-asm", "singleton"] +inline-asm = [] +singleton = ["untagged-option"] diff --git a/asm/basepri_max-cm7-r0p1.s b/asm/basepri_max-cm7-r0p1.s new file mode 100644 index 0000000..f26d473 --- /dev/null +++ b/asm/basepri_max-cm7-r0p1.s @@ -0,0 +1,12 @@ +;; fn __basepri_max(u8) +;; executed in a critical section to work around a silicon erratum + .global __basepri_max +__basepri_max: + mrs r1, PRIMASK + cpsid i + tst.w r1, #1 + msr BASEPRI_MAX, r0 + it ne + bxne lr + cpsie i + bx lr diff --git a/asm/basepri_max.s b/asm/basepri_max.s new file mode 100644 index 0000000..0ac3a5e --- /dev/null +++ b/asm/basepri_max.s @@ -0,0 +1,4 @@ + .global __basepri_max +__basepri_max: + msr BASEPRI_MAX, r0 + bx lr diff --git a/asm/basepri_r.s b/asm/basepri_r.s new file mode 100644 index 0000000..9f727ab --- /dev/null +++ b/asm/basepri_r.s @@ -0,0 +1,4 @@ + .global __basepri_r +__basepri_r: + mrs r0, BASEPRI + bx lr diff --git a/asm/basepri_w-cm7-r0p1.s b/asm/basepri_w-cm7-r0p1.s new file mode 100644 index 0000000..1d1dce6 --- /dev/null +++ b/asm/basepri_w-cm7-r0p1.s @@ -0,0 +1,12 @@ +;; fn __basepri_w(u8) +;; executed in a critical section to work around a silicon erratum + .global __basepri_w +__basepri_w: + mrs r1, PRIMASK + cpsid i + tst.w r1, #1 + msr BASEPRI, r0 + it ne + bxne lr + cpsie i + bx lr diff --git a/asm/basepri_w.s b/asm/basepri_w.s new file mode 100644 index 0000000..b1f8709 --- /dev/null +++ b/asm/basepri_w.s @@ -0,0 +1,4 @@ + .global __basepri_w +__basepri_w: + msr BASEPRI, r0 + bx lr diff --git a/asm/bkpt.s b/asm/bkpt.s new file mode 100644 index 0000000..3d9d347 --- /dev/null +++ b/asm/bkpt.s @@ -0,0 +1,4 @@ + .global __bkpt +__bkpt: + bkpt + bx lr diff --git a/asm/control.s b/asm/control.s new file mode 100644 index 0000000..81c35e6 --- /dev/null +++ b/asm/control.s @@ -0,0 +1,4 @@ + .global __control +__control: + mrs r0, CONTROL + bx lr diff --git a/asm/cpsid.s b/asm/cpsid.s new file mode 100644 index 0000000..ae4701d --- /dev/null +++ b/asm/cpsid.s @@ -0,0 +1,4 @@ + .global __cpsid +__cpsid: + cpsid i + bx lr diff --git a/asm/cpsie.s b/asm/cpsie.s new file mode 100644 index 0000000..cba3a39 --- /dev/null +++ b/asm/cpsie.s @@ -0,0 +1,4 @@ + .global __cpsie +__cpsie: + cpsie i + bx lr diff --git a/asm/dmb.s b/asm/dmb.s new file mode 100644 index 0000000..9fd38dd --- /dev/null +++ b/asm/dmb.s @@ -0,0 +1,4 @@ + .global __dmb +__dmb: + dmb 0xF + bx lr diff --git a/asm/dsb.s b/asm/dsb.s new file mode 100644 index 0000000..a5f1da1 --- /dev/null +++ b/asm/dsb.s @@ -0,0 +1,4 @@ + .global __dsb +__dsb: + dsb 0xF + bx lr diff --git a/asm/faultmask.s b/asm/faultmask.s new file mode 100644 index 0000000..5f08370 --- /dev/null +++ b/asm/faultmask.s @@ -0,0 +1,4 @@ + .global __faultmask +__faultmask: + mrs r0, FAULTMASK + bx lr diff --git a/asm/isb.s b/asm/isb.s new file mode 100644 index 0000000..a007a79 --- /dev/null +++ b/asm/isb.s @@ -0,0 +1,4 @@ + .global __isb +__isb: + isb 0xF + bx lr diff --git a/asm/msp_r.s b/asm/msp_r.s new file mode 100644 index 0000000..b31a715 --- /dev/null +++ b/asm/msp_r.s @@ -0,0 +1,4 @@ + .global __msp_r +__msp_r: + mrs r0, MSP + bx lr diff --git a/asm/msp_w.s b/asm/msp_w.s new file mode 100644 index 0000000..c589c0e --- /dev/null +++ b/asm/msp_w.s @@ -0,0 +1,4 @@ + .global __msp_w +__msp_w: + msr MSP, r0 + bx lr diff --git a/asm/nop.s b/asm/nop.s new file mode 100644 index 0000000..2fd1bf6 --- /dev/null +++ b/asm/nop.s @@ -0,0 +1,4 @@ + .global __nop +__nop: + nop + bx lr diff --git a/asm/primask.s b/asm/primask.s new file mode 100644 index 0000000..a3ff709 --- /dev/null +++ b/asm/primask.s @@ -0,0 +1,4 @@ + .global __primask +__primask: + mrs r0, PRIMASK + bx lr diff --git a/asm/psp_r.s b/asm/psp_r.s new file mode 100644 index 0000000..1c5ff81 --- /dev/null +++ b/asm/psp_r.s @@ -0,0 +1,4 @@ + .global __psp_r +__psp_r: + mrs r0, PSP + bx lr diff --git a/asm/psp_w.s b/asm/psp_w.s new file mode 100644 index 0000000..8ad1559 --- /dev/null +++ b/asm/psp_w.s @@ -0,0 +1,4 @@ + .global __psp_w +__psp_w: + msr PSP, r0 + bx lr diff --git a/asm/sev.s b/asm/sev.s new file mode 100644 index 0000000..2fa80a0 --- /dev/null +++ b/asm/sev.s @@ -0,0 +1,4 @@ + .global __sev +__sev: + sev + bx lr diff --git a/asm/wfe.s b/asm/wfe.s new file mode 100644 index 0000000..8a30570 --- /dev/null +++ b/asm/wfe.s @@ -0,0 +1,4 @@ + .global __wfe +__wfe: + wfe + bx lr diff --git a/asm/wfi.s b/asm/wfi.s new file mode 100644 index 0000000..2f31cf6 --- /dev/null +++ b/asm/wfi.s @@ -0,0 +1,4 @@ + .global __wfi +__wfi: + wfi + bx lr @@ -1,18 +1,58 @@ +extern crate cc; + use std::env; fn main() { let target = env::var("TARGET").unwrap(); + if target.starts_with("thumb") && env::var_os("CARGO_FEATURE_INLINE_ASM").is_none() { + // NOTE we need to place each routine in a separate assembly file or the linker won't be + // able to discard the unused routines + let mut build = cc::Build::new(); + build + .file("asm/basepri_r.s") + .file("asm/bkpt.s") + .file("asm/control.s") + .file("asm/cpsid.s") + .file("asm/cpsie.s") + .file("asm/dmb.s") + .file("asm/dsb.s") + .file("asm/faultmask.s") + .file("asm/isb.s") + .file("asm/msp_r.s") + .file("asm/msp_w.s") + .file("asm/nop.s") + .file("asm/primask.s") + .file("asm/psp_r.s") + .file("asm/psp_w.s") + .file("asm/sev.s") + .file("asm/wfe.s") + .file("asm/wfi.s"); + + if env::var_os("CARGO_FEATURE_CM7_R0P1").is_some() { + build.file("asm/basepri_max-cm7-r0p1.s"); + build.file("asm/basepri_w-cm7-r0p1.s"); + } else { + build.file("asm/basepri_max.s"); + build.file("asm/basepri_w.s"); + } + + build.compile("asm"); + } + if target.starts_with("thumbv6m-") { + println!("cargo:rustc-cfg=cortex_m"); println!("cargo:rustc-cfg=armv6m"); } else if target.starts_with("thumbv7m-") { + println!("cargo:rustc-cfg=cortex_m"); println!("cargo:rustc-cfg=armv7m"); } else if target.starts_with("thumbv7em-") { + println!("cargo:rustc-cfg=cortex_m"); println!("cargo:rustc-cfg=armv7m"); //println!("cargo:rustc-cfg=armv7em"); } - if target.ends_with("eabihf") { + if target.ends_with("-eabihf") { println!("cargo:rustc-cfg=has_fpu"); } } @@ -1,16 +1,25 @@ //! Miscellaneous assembly instructions -/// Puts the processor in Debug state. Debuggers can pick this up as a -/// "breakpoint". +/// Puts the processor in Debug state. Debuggers can pick this up as a "breakpoint". /// -/// NOTE calling `bkpt` when the processor is not connected to a debugger will -/// cause an exception +/// **NOTE** calling `bkpt` when the processor is not connected to a debugger will cause an +/// exception. #[inline(always)] pub fn bkpt() { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => unsafe { asm!("bkpt" :::: "volatile") }, - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __bkpt(); + } + + __bkpt(); + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } @@ -19,19 +28,40 @@ pub fn bkpt() { #[inline] pub fn nop() { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => unsafe { asm!("nop" :::: "volatile") }, - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __nop(); + } + + __nop() + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } + /// Wait For Event #[inline] pub fn wfe() { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => unsafe { asm!("wfe" :::: "volatile") }, - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __wfe(); + } + + __wfe() + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } @@ -40,9 +70,19 @@ pub fn wfe() { #[inline] pub fn wfi() { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => unsafe { asm!("wfi" :::: "volatile") }, - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __wfi(); + } + + __wfi() + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } @@ -51,9 +91,19 @@ pub fn wfi() { #[inline] pub fn sev() { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => unsafe { asm!("sev" :::: "volatile") }, - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __sev(); + } + + __sev() + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } @@ -65,27 +115,48 @@ pub fn sev() { #[inline] pub fn isb() { match () { - #[cfg(target_arch = "arm")] - () => unsafe { asm!("isb 0xF" : : : "memory" : "volatile") }, - #[cfg(not(target_arch = "arm"))] + #[cfg(all(cortex_m, feature = "inline-asm"))] + () => unsafe { asm!("isb 0xF" ::: "memory" : "volatile") }, + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __isb(); + } + + __isb() + // XXX do we need a explicit compiler barrier here? + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } /// Data Synchronization Barrier /// -/// Acts as a special kind of memory barrier. No instruction in program order after this -/// instruction can execute until this instruction completes. This instruction completes only when -/// both: +/// Acts as a special kind of memory barrier. No instruction in program order after this instruction +/// can execute until this instruction completes. This instruction completes only when both: /// /// * any explicit memory access made before this instruction is complete /// * all cache and branch predictor maintenance operations before this instruction complete #[inline] pub fn dsb() { match () { - #[cfg(target_arch = "arm")] - () => unsafe { asm!("dsb 0xF" : : : "memory" : "volatile") }, - #[cfg(not(target_arch = "arm"))] + #[cfg(all(cortex_m, feature = "inline-asm"))] + () => unsafe { asm!("dsb 0xF" ::: "memory" : "volatile") }, + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __dsb(); + } + + __dsb() + // XXX do we need a explicit compiler barrier here? + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } @@ -98,9 +169,20 @@ pub fn dsb() { #[inline] pub fn dmb() { match () { - #[cfg(target_arch = "arm")] - () => unsafe { asm!("dmb 0xF" : : : "memory" : "volatile") }, - #[cfg(not(target_arch = "arm"))] + #[cfg(all(cortex_m, feature = "inline-asm"))] + () => unsafe { asm!("dmb 0xF" ::: "memory" : "volatile") }, + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __dmb(); + } + + __dmb() + // XXX do we need a explicit compiler barrier here? + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/interrupt.rs b/src/interrupt.rs index 5880dd4..b57cc80 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -1,16 +1,29 @@ //! Interrupts +// use core::sync::atomic::{self, Ordering}; + pub use bare_metal::{CriticalSection, Mutex, Nr}; /// Disables all interrupts #[inline] pub fn disable() { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => unsafe { asm!("cpsid i" ::: "memory" : "volatile"); }, - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __cpsid(); + } + + // XXX do we need a explicit compiler barrier here? + __cpsid(); + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } @@ -23,9 +36,20 @@ pub fn disable() { #[inline] pub unsafe fn enable() { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => asm!("cpsie i" ::: "memory" : "volatile"), - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => { + extern "C" { + fn __cpsie(); + } + + // XXX do we need a explicit compiler barrier here? + __cpsie(); + } + + #[cfg(not(cortex_m))] () => unimplemented!(), } } @@ -1,4 +1,6 @@ //! Instrumentation Trace Macrocell +//! +//! **NOTE** This module is only available on ARMv7-M and newer use core::{fmt, mem, ptr, slice}; @@ -9,19 +9,18 @@ #![deny(missing_docs)] #![deny(warnings)] -#![feature(asm)] -#![feature(const_fn)] +#![cfg_attr(feature = "inline-asm", feature(asm))] #![no_std] extern crate aligned; extern crate bare_metal; +#[cfg(feature = "singleton")] extern crate untagged_option; extern crate volatile_register; #[macro_use] mod macros; -#[macro_use] pub mod asm; pub mod exception; pub mod interrupt; @@ -32,4 +31,7 @@ pub mod peripheral; pub mod register; pub use peripheral::Peripherals; + +#[cfg(feature = "singleton")] +#[doc(hidden)] pub use untagged_option::UntaggedOption; diff --git a/src/macros.rs b/src/macros.rs index 7d2cf6a..7af64bc 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -50,13 +50,15 @@ macro_rules! iprintln { /// } /// ``` #[macro_export] +// TODO(stable) needs stable const `mem::uninitialized` OR stable const `MaybeUninit::new()` (RFC +// 1892) +#[cfg(feature = "singleton")] macro_rules! singleton { (: $ty:ty = $expr:expr) => { $crate::interrupt::free(|_| { static mut USED: bool = false; static mut VAR: $crate::UntaggedOption<$ty> = $crate::UntaggedOption { none: () }; - #[allow(unsafe_code)] let used = unsafe { USED }; if used { @@ -92,6 +94,7 @@ macro_rules! singleton { /// } /// ``` #[allow(dead_code)] +#[cfg(feature = "singleton")] const CFAIL: () = (); /// ``` @@ -107,4 +110,5 @@ const CFAIL: () = (); /// } /// ``` #[allow(dead_code)] +#[cfg(feature = "singleton")] const CPASS: () = (); diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 4462136..d46622d 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -84,6 +84,7 @@ use core::ops; use interrupt; +// NOTE(target_arch) is for documentation purposes #[cfg(any(armv7m, target_arch = "x86_64"))] pub mod cbp; pub mod cpuid; @@ -93,7 +94,6 @@ pub mod dwt; pub mod fpb; #[cfg(any(has_fpu, target_arch = "x86_64"))] pub mod fpu; -// NOTE(target_arch) is for documentation purposes #[cfg(any(armv7m, target_arch = "x86_64"))] pub mod itm; pub mod mpu; diff --git a/src/register/apsr.rs b/src/register/apsr.rs index 60dd364..280fd24 100644 --- a/src/register/apsr.rs +++ b/src/register/apsr.rs @@ -42,7 +42,7 @@ impl Apsr { #[inline] pub fn read() -> Apsr { match () { - #[cfg(target_arch = "arm")] + #[cfg(cortex_m)] () => { let r: u32; unsafe { @@ -50,7 +50,8 @@ pub fn read() -> Apsr { } Apsr { bits: r } } - #[cfg(not(target_arch = "arm"))] + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/basepri.rs b/src/register/basepri.rs index c9be9d3..086d8cf 100644 --- a/src/register/basepri.rs +++ b/src/register/basepri.rs @@ -4,7 +4,7 @@ #[inline] pub fn read() -> u8 { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => { let r: u32; unsafe { @@ -12,7 +12,17 @@ pub fn read() -> u8 { } r as u8 } - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __basepri_r() -> u8; + } + + __basepri_r() + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } @@ -21,20 +31,29 @@ pub fn read() -> u8 { /// /// **IMPORTANT** If you are using a Cortex-M7 device with revision r0p1 you MUST enable the /// `cm7-r0p1` Cargo feature or this function WILL misbehave. -#[cfg_attr(not(target_arch = "arm"), allow(unused_variables))] #[inline] -pub unsafe fn write(basepri: u8) { +pub unsafe fn write(_basepri: u8) { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => match () { #[cfg(not(feature = "cm7-r0p1"))] - () => asm!("msr BASEPRI, $0" :: "r"(basepri) : "memory" : "volatile"), + () => asm!("msr BASEPRI, $0" :: "r"(_basepri) : "memory" : "volatile"), #[cfg(feature = "cm7-r0p1")] - () => asm!("cpsid i - msr BASEPRI, $0 - cpsie i" :: "r"(basepri) : "memory" : "volatile"), + () => interrupt::free( + |_| asm!("msr BASEPRI, $0" :: "r"(_basepri) : "memory" : "volatile"), + ), }, - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => { + extern "C" { + fn __basepri_w(_: u8); + } + + __basepri_w(_basepri); + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/basepri_max.rs b/src/register/basepri_max.rs index c386e86..edcd11d 100644 --- a/src/register/basepri_max.rs +++ b/src/register/basepri_max.rs @@ -7,22 +7,31 @@ /// /// **IMPORTANT** If you are using a Cortex-M7 device with revision r0p1 you MUST enable the /// `cm7-r0p1` Cargo feature or this function WILL misbehave. -#[cfg_attr(not(target_arch = "arm"), allow(unused_variables))] #[inline] -pub fn write(basepri: u8) { +pub fn write(_basepri: u8) { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => unsafe { match () { #[cfg(not(feature = "cm7-r0p1"))] - () => asm!("msr BASEPRI_MAX, $0" :: "r"(basepri) : "memory" : "volatile"), + () => asm!("msr BASEPRI_MAX, $0" :: "r"(_basepri) : "memory" : "volatile"), #[cfg(feature = "cm7-r0p1")] - () => asm!("cpsid i - msr BASEPRI_MAX, $0 - cpsie i" :: "r"(basepri) : "memory" : "volatile"), + () => interrupt::free( + |_| asm!("msr BASEPRI_MAX, $0" :: "r"(_basepri) : "memory" : "volatile"), + ), } }, - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __basepri_max(_: u8); + } + + __basepri_max(_basepri) + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/control.rs b/src/register/control.rs index 93c497f..b6b6676 100644 --- a/src/register/control.rs +++ b/src/register/control.rs @@ -107,13 +107,30 @@ impl Fpca { #[inline] pub fn read() -> Control { match () { - #[cfg(target_arch = "arm")] + #[cfg(cortex_m)] () => { - let r: u32; - unsafe { asm!("mrs $0, CONTROL" : "=r"(r) ::: "volatile") } + let r = match () { + #[cfg(feature = "inline-asm")] + () => { + let r: u32; + unsafe { asm!("mrs $0, CONTROL" : "=r"(r) ::: "volatile") } + r + } + + #[cfg(not(feature = "inline-asm"))] + () => unsafe { + extern "C" { + fn __control() -> u32; + } + + __control() + }, + }; + Control { bits: r } } - #[cfg(not(target_arch = "arm"))] + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/faultmask.rs b/src/register/faultmask.rs index 3e0980e..9cd1892 100644 --- a/src/register/faultmask.rs +++ b/src/register/faultmask.rs @@ -25,17 +25,35 @@ impl Faultmask { #[inline] pub fn read() -> Faultmask { match () { - #[cfg(target_arch = "arm")] + #[cfg(cortex_m)] () => { - let r: u32; - unsafe { asm!("mrs $0, FAULTMASK" : "=r"(r) ::: "volatile") } + let r = match () { + #[cfg(feature = "inline-asm")] + () => { + let r: u32; + unsafe { asm!("mrs $0, FAULTMASK" : "=r"(r) ::: "volatile") } + r + } + + #[cfg(not(feature = "inline-asm"))] + () => unsafe { + extern "C" { + fn __faultmask() -> u32; + + } + + __faultmask() + }, + }; + if r & (1 << 0) == (1 << 0) { Faultmask::Inactive } else { Faultmask::Active } } - #[cfg(not(target_arch = "arm"))] + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/lr.rs b/src/register/lr.rs index ddbc07d..60828d0 100644 --- a/src/register/lr.rs +++ b/src/register/lr.rs @@ -4,25 +4,26 @@ #[inline] pub fn read() -> u32 { match () { - #[cfg(target_arch = "arm")] + #[cfg(cortex_m)] () => { let r: u32; unsafe { asm!("mov $0,R14" : "=r"(r) ::: "volatile") } r } - #[cfg(not(target_arch = "arm"))] + + #[cfg(not(cortex_m))] () => unimplemented!(), } } /// Writes `bits` to the CPU register -#[cfg_attr(not(target_arch = "arm"), allow(unused_variables))] #[inline] -pub unsafe fn write(bits: u32) { +pub unsafe fn write(_bits: u32) { match () { - #[cfg(target_arch = "arm")] - () => asm!("mov R14,$0" :: "r"(bits) :: "volatile"), - #[cfg(not(target_arch = "arm"))] + #[cfg(cortex_m)] + () => asm!("mov R14,$0" :: "r"(_bits) :: "volatile"), + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/mod.rs b/src/register/mod.rs index 17f6fda..37692c8 100644 --- a/src/register/mod.rs +++ b/src/register/mod.rs @@ -26,16 +26,30 @@ //! //! - Cortex-M* Devices Generic User Guide - Section 2.1.3 Core registers -pub mod apsr; #[cfg(not(armv6m))] pub mod basepri; + #[cfg(not(armv6m))] pub mod basepri_max; + pub mod control; + #[cfg(not(armv6m))] pub mod faultmask; -pub mod lr; + pub mod msp; -pub mod pc; + pub mod primask; + pub mod psp; + +// Accessing these registers requires inline assembly because their contents are tied to the current +// stack frame +#[cfg(feature = "nightly")] +pub mod apsr; + +#[cfg(feature = "nightly")] +pub mod lr; + +#[cfg(feature = "nightly")] +pub mod pc; diff --git a/src/register/msp.rs b/src/register/msp.rs index 3b83353..082a7fc 100644 --- a/src/register/msp.rs +++ b/src/register/msp.rs @@ -4,25 +4,44 @@ #[inline] pub fn read() -> u32 { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => { let r; unsafe { asm!("mrs $0,MSP" : "=r"(r) ::: "volatile") } r } - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __msp_r() -> u32; + } + + __msp_r() + }, + + #[cfg(not(cortex_m))] () => unimplemented!(), } } /// Writes `bits` to the CPU register -#[cfg_attr(not(target_arch = "arm"), allow(unused_variables))] #[inline] -pub unsafe fn write(bits: u32) { +pub unsafe fn write(_bits: u32) { match () { - #[cfg(target_arch = "arm")] - () => asm!("msr MSP,$0" :: "r"(bits) :: "volatile"), - #[cfg(not(target_arch = "arm"))] + #[cfg(all(cortex_m, feature = "inline-asm"))] + () => asm!("msr MSP,$0" :: "r"(_bits) :: "volatile"), + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => { + extern "C" { + fn __msp_w(_: u32); + } + + __msp_w(_bits); + } + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/pc.rs b/src/register/pc.rs index 7a7ef19..b41383d 100644 --- a/src/register/pc.rs +++ b/src/register/pc.rs @@ -4,25 +4,26 @@ #[inline] pub fn read() -> u32 { match () { - #[cfg(target_arch = "arm")] + #[cfg(cortex_m)] () => { let r; unsafe { asm!("mov $0,R15" : "=r"(r) ::: "volatile") } r } - #[cfg(not(target_arch = "arm"))] + + #[cfg(not(cortex_m))] () => unimplemented!(), } } /// Writes `bits` to the CPU register -#[cfg_attr(not(target_arch = "arm"), allow(unused_variables))] #[inline] -pub unsafe fn write(bits: u32) { +pub unsafe fn write(_bits: u32) { match () { - #[cfg(target_arch = "arm")] - () => asm!("mov R15,$0" :: "r"(bits) :: "volatile"), - #[cfg(not(target_arch = "arm"))] + #[cfg(cortex_m)] + () => asm!("mov R15,$0" :: "r"(_bits) :: "volatile"), + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/primask.rs b/src/register/primask.rs index c9dc39a..cb8faf9 100644 --- a/src/register/primask.rs +++ b/src/register/primask.rs @@ -25,17 +25,34 @@ impl Primask { #[inline] pub fn read() -> Primask { match () { - #[cfg(target_arch = "arm")] + #[cfg(cortex_m)] () => { - let r: u32; - unsafe { asm!("mrs $0, PRIMASK" : "=r"(r) ::: "volatile") } + let r = match () { + #[cfg(feature = "inline-asm")] + () => { + let r: u32; + unsafe { asm!("mrs $0, PRIMASK" : "=r"(r) ::: "volatile") } + r + } + + #[cfg(not(feature = "inline-asm"))] + () => { + extern "C" { + fn __primask() -> u32; + } + + unsafe { __primask() } + } + }; + if r & (1 << 0) == (1 << 0) { Primask::Inactive } else { Primask::Active } } - #[cfg(not(target_arch = "arm"))] + + #[cfg(not(cortex_m))] () => unimplemented!(), } } diff --git a/src/register/psp.rs b/src/register/psp.rs index d7232db..9f4889c 100644 --- a/src/register/psp.rs +++ b/src/register/psp.rs @@ -4,25 +4,44 @@ #[inline] pub fn read() -> u32 { match () { - #[cfg(target_arch = "arm")] + #[cfg(all(cortex_m, feature = "inline-asm"))] () => { let r; unsafe { asm!("mrs $0,PSP" : "=r"(r) ::: "volatile") } r } - #[cfg(not(target_arch = "arm"))] + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => unsafe { + extern "C" { + fn __psp_r() -> u32; + } + + __psp_r() + } + + #[cfg(not(cortex_m))] () => unimplemented!(), } } /// Writes `bits` to the CPU register -#[cfg_attr(not(target_arch = "arm"), allow(unused_variables))] #[inline] -pub unsafe fn write(bits: u32) { +pub unsafe fn write(_bits: u32) { match () { - #[cfg(target_arch = "arm")] - () => asm!("msr PSP,$0" :: "r"(bits) :: "volatile"), - #[cfg(not(target_arch = "arm"))] + #[cfg(all(cortex_m, feature = "inline-asm"))] + () => asm!("msr PSP,$0" :: "r"(_bits) :: "volatile"), + + #[cfg(all(cortex_m, not(feature = "inline-asm")))] + () => { + extern "C" { + fn __psp_w(_: u32); + } + + __psp_w(_bits); + } + + #[cfg(not(cortex_m))] () => unimplemented!(), } } |