aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml23
-rw-r--r--asm/basepri_max-cm7-r0p1.s12
-rw-r--r--asm/basepri_max.s4
-rw-r--r--asm/basepri_r.s4
-rw-r--r--asm/basepri_w-cm7-r0p1.s12
-rw-r--r--asm/basepri_w.s4
-rw-r--r--asm/bkpt.s4
-rw-r--r--asm/control.s4
-rw-r--r--asm/cpsid.s4
-rw-r--r--asm/cpsie.s4
-rw-r--r--asm/dmb.s4
-rw-r--r--asm/dsb.s4
-rw-r--r--asm/faultmask.s4
-rw-r--r--asm/isb.s4
-rw-r--r--asm/msp_r.s4
-rw-r--r--asm/msp_w.s4
-rw-r--r--asm/nop.s4
-rw-r--r--asm/primask.s4
-rw-r--r--asm/psp_r.s4
-rw-r--r--asm/psp_w.s4
-rw-r--r--asm/sev.s4
-rw-r--r--asm/wfe.s4
-rw-r--r--asm/wfi.s4
-rw-r--r--build.rs42
-rw-r--r--src/asm.rs134
-rw-r--r--src/interrupt.rs32
-rw-r--r--src/itm.rs2
-rw-r--r--src/lib.rs8
-rw-r--r--src/macros.rs6
-rw-r--r--src/peripheral/mod.rs2
-rw-r--r--src/register/apsr.rs5
-rw-r--r--src/register/basepri.rs39
-rw-r--r--src/register/basepri_max.rs25
-rw-r--r--src/register/control.rs25
-rw-r--r--src/register/faultmask.rs26
-rw-r--r--src/register/lr.rs15
-rw-r--r--src/register/mod.rs20
-rw-r--r--src/register/msp.rs33
-rw-r--r--src/register/pc.rs15
-rw-r--r--src/register/primask.rs25
-rw-r--r--src/register/psp.rs33
41 files changed, 511 insertions, 103 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 2582ae5..ceee903 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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
diff --git a/build.rs b/build.rs
index 4d5a706..4866ed2 100644
--- a/build.rs
+++ b/build.rs
@@ -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");
}
}
diff --git a/src/asm.rs b/src/asm.rs
index 9a2d481..6e90f09 100644
--- a/src/asm.rs
+++ b/src/asm.rs
@@ -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!(),
}
}
diff --git a/src/itm.rs b/src/itm.rs
index 02ada53..0e32e3c 100644
--- a/src/itm.rs
+++ b/src/itm.rs
@@ -1,4 +1,6 @@
//! Instrumentation Trace Macrocell
+//!
+//! **NOTE** This module is only available on ARMv7-M and newer
use core::{fmt, mem, ptr, slice};
diff --git a/src/lib.rs b/src/lib.rs
index 6af60d7..802a2d5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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!(),
}
}