aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jorge Aparicio <japaricious@gmail.com> 2016-09-27 18:35:29 -0500
committerGravatar Jorge Aparicio <japaricious@gmail.com> 2016-09-27 18:35:29 -0500
commitddc7f255b57d0e6aeb9f3b1b7466b2e5c0c5fff0 (patch)
treeac8332c9d63b45082f81ce419045c9b16db1b270
downloadcortex-m-ddc7f255b57d0e6aeb9f3b1b7466b2e5c0c5fff0.tar.gz
cortex-m-ddc7f255b57d0e6aeb9f3b1b7466b2e5c0c5fff0.tar.zst
cortex-m-ddc7f255b57d0e6aeb9f3b1b7466b2e5c0c5fff0.zip
initial commit
-rw-r--r--.gitignore3
-rw-r--r--Cargo.toml11
-rw-r--r--LICENSE-APACHE201
-rw-r--r--LICENSE-MIT25
-rw-r--r--README.md25
-rw-r--r--src/asm.rs35
-rw-r--r--src/interrupt.rs47
-rw-r--r--src/lib.rs78
-rw-r--r--src/peripheral/cpuid.rs30
-rw-r--r--src/peripheral/dcb.rs16
-rw-r--r--src/peripheral/dwt.rs43
-rw-r--r--src/peripheral/fpb.rs19
-rw-r--r--src/peripheral/fpu.rs17
-rw-r--r--src/peripheral/itm.rs54
-rw-r--r--src/peripheral/mod.rs149
-rw-r--r--src/peripheral/mpu.rs30
-rw-r--r--src/peripheral/nvic.rs25
-rw-r--r--src/peripheral/scb.rs37
-rw-r--r--src/peripheral/syst.rs16
-rw-r--r--src/peripheral/test.rs162
-rw-r--r--src/peripheral/tpiu.rs26
-rw-r--r--src/register.rs126
22 files changed, 1175 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b203ea6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*.rs.bk
+Cargo.lock
+target
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..2bb449a
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+authors = ["Jorge Aparicio <japaricious@gmail.com>"]
+description = "Low level access to Cortex-M processors"
+keywords = ["arm", "cortex-m", "register", "peripheral"]
+license = "MIT OR Apache-2.0"
+name = "cortex-m"
+repository = "https://github.com/japaric/cortex-m"
+version = "0.1.0"
+
+[dependencies]
+volatile-register = "0.1.0"
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..a43445e
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2016 Jorge Aparicio
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..0e58640
--- /dev/null
+++ b/README.md
@@ -0,0 +1,25 @@
+[![Build Status][travis]](https://travis-ci.org/japaric/cortex-m)
+
+[travis]: https://travis-ci.org/japaric/cortex-m.svg?branch=master
+
+# `cortex-m`
+
+> Low level access to Cortex-M processors
+
+## [Documentation](https://docs.rs/crate/cortex-m)
+
+## License
+
+Licensed under either of
+
+- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
+ http://www.apache.org/licenses/LICENSE-2.0)
+- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
+work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
+additional terms or conditions.
diff --git a/src/asm.rs b/src/asm.rs
new file mode 100644
index 0000000..3337626
--- /dev/null
+++ b/src/asm.rs
@@ -0,0 +1,35 @@
+//! Miscellaneous assembly instructions
+
+/// Puts the processor in Debug state. Debuggers can pick this up as a "breakpoint".
+///
+/// Optionally, an "immediate" value (in the 0-255 range) can be passed to `bkpt!`. The debugger can
+/// then read this value using the Program Counter (PC).
+#[macro_export]
+macro_rules! bkpt {
+ () => {
+ asm!("bkpt" :::: "volatile");
+ };
+ ($imm:expr) => {
+ asm!(concat!("bkpt #", stringify!($imm)) :::: "volatile");
+ };
+}
+
+/// Wait for event
+pub unsafe fn wfe() {
+ match () {
+ #[cfg(target_arch = "arm")]
+ () => asm!("wfe" :::: "volatile"),
+ #[cfg(not(target_arch = "arm"))]
+ () => {}
+ }
+}
+
+/// Wait for interupt
+pub unsafe fn wfi() {
+ match () {
+ #[cfg(target_arch = "arm")]
+ () => asm!("wfi" :::: "volatile"),
+ #[cfg(not(target_arch = "arm"))]
+ () => {}
+ }
+}
diff --git a/src/interrupt.rs b/src/interrupt.rs
new file mode 100644
index 0000000..6fb8aeb
--- /dev/null
+++ b/src/interrupt.rs
@@ -0,0 +1,47 @@
+//! Interrupts
+
+/// Disable interrupts, globally
+#[inline(always)]
+pub unsafe fn disable() {
+ match () {
+ #[cfg(target_arch = "arm")]
+ () => {
+ asm!("cpsid i" :::: "volatile");
+ }
+ #[cfg(not(target_arch = "arm"))]
+ () => {}
+ }
+}
+
+/// Enable interrupts, globally
+#[inline(always)]
+pub unsafe fn enable() {
+ match () {
+ #[cfg(target_arch = "arm")]
+ () => {
+ asm!("cpsie i" :::: "volatile");
+ }
+ #[cfg(not(target_arch = "arm"))]
+ () => {}
+ }
+}
+
+/// Execute closure `f` in an interrupt-free context.
+/// This as also known as a "critical section".
+pub unsafe fn free<F>(f: F)
+ where F: FnOnce()
+{
+ let primask = ::register::primask::read();
+
+ disable();
+
+ f();
+
+ // If the interrupts were enabled before our `disable` call, then re-enable them
+ // Otherwise, keep them disabled
+ // PRIMASK & 1 = 1 indicates that the interrupts were disabled
+ // PRIMASK & 1 = 0 indicates that they were enabled
+ if primask & 1 == 0 {
+ enable();
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..d8b7fa1
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,78 @@
+//! Low level access to Cortex-M processors
+//!
+//! This crate provides access to:
+//!
+//! - Core peripherals like NVIC, SCB and SysTick.
+//! - Core registers like CONTROL, MSP and PSR.
+//! - Interrupt manipulation mechanisms
+//! - Data structures like the vector table
+//! - Miscellaneous assembly instructions like `bkpt`
+//!
+
+#![deny(missing_docs)]
+#![deny(warnings)]
+#![feature(asm)]
+#![no_std]
+
+extern crate volatile_register;
+
+pub mod asm;
+pub mod interrupt;
+pub mod peripheral;
+pub mod register;
+
+/// Vector Table
+///
+/// # References
+///
+/// - ARMv7-M Architecture Reference Manual (issue E.b) - Section B1.5 - ARMv7-M exception model
+#[repr(C)]
+pub struct VectorTable {
+ /// Reset value of the Main Stack Pointer (MSP)
+ pub sp_main: &'static (),
+ /// Reset
+ pub reset: extern "C" fn() -> !,
+ /// Non Maskable Interrupt
+ pub nmi: Option<Handler>,
+ /// Hard Fault
+ pub hard_fault: Option<Handler>,
+ /// Memory Management
+ pub mem_manage: Option<Handler>,
+ /// Bus Fault
+ pub bus_fault: Option<Handler>,
+ /// Usage Fault
+ pub usage_fault: Option<Handler>,
+ reserved0: [u32; 4],
+ /// Supervisor Call
+ pub svcall: Option<Handler>,
+ /// Debug Monitor
+ pub debug_monitor: Option<Handler>,
+ reserved1: u32,
+ /// PendSV
+ pub pendsv: Option<Handler>,
+ /// SysTick
+ pub sys_tick: Option<Handler>,
+ /// Interrupts. An IMPLEMENTATION DEFINED number of them.
+ pub interrupts: [Option<Handler>; 0],
+}
+
+/// Returns the vector table
+pub fn vector_table() -> &'static VectorTable {
+ unsafe { deref(peripheral::scb().vtor.read() as usize) }
+}
+
+/// Exception/Interrupt Handler
+pub type Handler = unsafe extern "C" fn();
+
+#[cfg(test)]
+fn address<T>(r: &T) -> usize {
+ r as *const T as usize
+}
+
+unsafe fn deref<T>(a: usize) -> &'static T {
+ &*(a as *const T)
+}
+
+unsafe fn deref_mut<T>(a: usize) -> &'static mut T {
+ &mut *(a as *mut T)
+}
diff --git a/src/peripheral/cpuid.rs b/src/peripheral/cpuid.rs
new file mode 100644
index 0000000..0dc140f
--- /dev/null
+++ b/src/peripheral/cpuid.rs
@@ -0,0 +1,30 @@
+//! CPUID
+
+use volatile_register::RO;
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// CPUID base
+ pub base: RO<u32>,
+ reserved0: [u32; 15],
+ /// Processor Feature
+ pub pfr: [RO<u32>; 2],
+ /// Debug Feature
+ pub dfr: RO<u32>,
+ /// Auxiliary Feature
+ pub afr: RO<u32>,
+ /// Memory Model Feature
+ pub mmfr: [RO<u32>; 4],
+ /// Instruction Set Attribute
+ pub isar: [RO<u32>; 5],
+ reserved1: u32,
+ /// Cache Level ID
+ pub clidr: RO<u32>,
+ /// Cache Type
+ pub ctr: RO<u32>,
+ /// Cache Size ID
+ pub ccsidr: RO<u32>,
+ /// Cache Size Selection
+ pub csselr: RO<u32>,
+}
diff --git a/src/peripheral/dcb.rs b/src/peripheral/dcb.rs
new file mode 100644
index 0000000..93a056b
--- /dev/null
+++ b/src/peripheral/dcb.rs
@@ -0,0 +1,16 @@
+//! Debug Control Block
+
+use volatile_register::{RW, WO};
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Debug Halting Control and Status
+ pub dhcsr: RW<u32>,
+ /// Debug Core Register Selector
+ pub dcrsr: WO<u32>,
+ /// Debug Core Register Data
+ pub dcrdr: RW<u32>,
+ /// Debug Exception and Monitor Control
+ pub demcr: RW<u32>,
+}
diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs
new file mode 100644
index 0000000..ecd214e
--- /dev/null
+++ b/src/peripheral/dwt.rs
@@ -0,0 +1,43 @@
+//! Data Watchpoint and Trace unit
+
+use volatile_register::{RO, RW, WO};
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Control
+ pub ctrl: RW<u32>,
+ /// Cycle Count
+ pub cyccnt: RW<u32>,
+ /// CPI Count
+ pub cpicnt: RW<u32>,
+ /// Exception Overhead Count
+ pub exccnt: RW<u32>,
+ /// Sleep Count
+ pub sleepcnt: RW<u32>,
+ /// LSU Count
+ pub lsucnt: RW<u32>,
+ /// Folded-instruction Count
+ pub foldcnt: RW<u32>,
+ /// Program Counter Sample
+ pub pcsr: RO<u32>,
+ /// Comparators
+ pub c: [Comparator; 16],
+ reserved: [u32; 932],
+ /// Lock Access
+ pub lar: WO<u32>,
+ /// Lock Status
+ pub lsr: RO<u32>,
+}
+
+/// Comparator
+#[repr(C)]
+pub struct Comparator {
+ /// Comparator
+ pub comp: RW<u32>,
+ /// Comparator Mask
+ pub mask: RW<u32>,
+ /// Comparator Function
+ pub function: RW<u32>,
+ reserved: u32,
+}
diff --git a/src/peripheral/fpb.rs b/src/peripheral/fpb.rs
new file mode 100644
index 0000000..6aa6fbb
--- /dev/null
+++ b/src/peripheral/fpb.rs
@@ -0,0 +1,19 @@
+//! Flash Patch and Breakpoint unit
+
+use volatile_register::{RO, RW, WO};
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Control
+ pub ctrl: RW<u32>,
+ /// Remap
+ pub remap: RW<u32>,
+ /// Comparator
+ pub comp: [RW<u32>; 127],
+ reserved: [u32; 875],
+ /// Lock Access
+ pub lar: WO<u32>,
+ /// Lock Status
+ pub lsr: RO<u32>,
+}
diff --git a/src/peripheral/fpu.rs b/src/peripheral/fpu.rs
new file mode 100644
index 0000000..5bbf352
--- /dev/null
+++ b/src/peripheral/fpu.rs
@@ -0,0 +1,17 @@
+//! Floating Point Unit
+
+use volatile_register::{RO, RW};
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ reserved: u32,
+ /// Floating Point Context Control
+ pub fpccr: RW<u32>,
+ /// Floating Point Context Address
+ pub fpcar: RW<u32>,
+ /// Floating Point Default Status Control
+ pub fpdscr: RW<u32>,
+ /// Media and FP Feature
+ pub mvfr: [RO<u32>; 3],
+}
diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs
new file mode 100644
index 0000000..b56d1b5
--- /dev/null
+++ b/src/peripheral/itm.rs
@@ -0,0 +1,54 @@
+//! Instrumentation Trace Macrocell
+
+use volatile_register::{RO, RW, WO};
+
+use core::cell::UnsafeCell;
+use core::ptr;
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Stimulus Port
+ pub stim: [Stim; 256],
+ reserved0: [u32; 640],
+ /// Trace Enable
+ pub ter: [RW<u32>; 8],
+ reserved1: [u32; 8],
+ /// Trace Privilege
+ pub tpr: RW<u32>,
+ reserved2: [u32; 15],
+ /// Trace Control
+ pub tcr: RW<u32>,
+ reserved3: [u32; 75],
+ /// Lock Access
+ pub lar: WO<u32>,
+ /// Lock Status
+ pub lsr: RO<u32>,
+}
+
+/// Stimulus Port
+pub struct Stim {
+ register: UnsafeCell<u32>,
+}
+
+impl Stim {
+ /// Writes an `u8` payload into the stimulus port
+ pub fn write_u8(&self, value: u8) {
+ unsafe { ptr::write_volatile(self.register.get() as *mut u8, value) }
+ }
+
+ /// Writes an `u16` payload into the stimulus port
+ pub fn write_u16(&self, value: u16) {
+ unsafe { ptr::write_volatile(self.register.get() as *mut u16, value) }
+ }
+
+ /// Writes an `u32` payload into the stimulus port
+ pub fn write_u32(&self, value: u32) {
+ unsafe { ptr::write_volatile(self.register.get(), value) }
+ }
+
+ /// Returns `true` if the stimulus port is ready to accept more data
+ pub fn is_fifo_ready(&self) -> bool {
+ unsafe { ptr::read_volatile(self.register.get()) == 1 }
+ }
+}
diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs
new file mode 100644
index 0000000..9f02aa3
--- /dev/null
+++ b/src/peripheral/mod.rs
@@ -0,0 +1,149 @@
+//! Core peripherals
+//!
+//! # Notes
+//!
+//! - Although the `*_mut()` functions always return a valid/live reference, the API doesn't prevent
+//! the user from creating multiple mutable aliases. It's up to the user to ensure that no
+//! unsynchonized concurrent access is performed through these references.
+//!
+//! # 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
+//!
+//! - ARMv7-M Architecture Reference Manual (Issue E.b) - Chapter B3
+
+pub mod cpuid;
+pub mod dcb;
+pub mod dwt;
+pub mod fpb;
+pub mod fpu;
+pub mod itm;
+pub mod mpu;
+pub mod nvic;
+pub mod scb;
+pub mod syst;
+pub mod tpiu;
+
+mod test;
+
+const CPUID: usize = 0xE000_ED00;
+const DCB: usize = 0xE000_EDF0;
+const DWT: usize = 0xE000_1000;
+const FPB: usize = 0xE000_2000;
+const FPU: usize = 0xE000_EF30;
+const ITM: usize = 0xE000_0000;
+const MPU: usize = 0xE000_ED90;
+const NVIC: usize = 0xE000_E100;
+const SCB: usize = 0xE000_ED04;
+const SYST: usize = 0xE000_E010;
+const TPIU: usize = 0xE004_0000;
+
+// TODO stand-alone registers: ICTR, ACTLR and STIR
+
+/// `&cpuid::Registers`
+pub fn cpuid() -> &'static cpuid::Registers {
+ unsafe { ::deref(CPUID) }
+}
+
+/// `&dcb::Registers`
+pub fn dcb() -> &'static dcb::Registers {
+ unsafe { ::deref(DCB) }
+}
+
+/// `&mut dcb::Registers`
+pub unsafe fn dcb_mut() -> &'static mut dcb::Registers {
+ ::deref_mut(DCB)
+}
+
+/// `&dwt::Registers`
+pub fn dwt() -> &'static dwt::Registers {
+ unsafe { ::deref(DWT) }
+}
+
+/// `&mut dwt::Registers`
+pub unsafe fn dwt_mut() -> &'static mut dwt::Registers {
+ ::deref_mut(DWT)
+}
+
+/// `&fpb::Registers`
+pub fn fpb() -> &'static fpb::Registers {
+ unsafe { ::deref(FPB) }
+}
+
+/// `&mut fpb::Registers`
+pub unsafe fn fpb_mut() -> &'static mut fpb::Registers {
+ ::deref_mut(FPB)
+}
+
+/// `&fpu::Registers`
+pub fn fpu() -> &'static fpu::Registers {
+ unsafe { ::deref(FPU) }
+}
+
+/// `&mut fpu::Registers`
+pub unsafe fn fpu_mut() -> &'static mut fpu::Registers {
+ ::deref_mut(FPU)
+}
+
+/// `&itm::Registers`
+pub fn itm() -> &'static itm::Registers {
+ unsafe { ::deref(ITM) }
+}
+
+/// `&mut itm::Registers`
+pub unsafe fn itm_mut() -> &'static mut itm::Registers {
+ ::deref_mut(ITM)
+}
+
+/// `&mpu::Registers`
+pub fn mpu() -> &'static mpu::Registers {
+ unsafe { ::deref(MPU) }
+}
+
+/// `&mut mpu::Registers`
+pub unsafe fn mpu_mut() -> &'static mut mpu::Registers {
+ ::deref_mut(MPU)
+}
+
+/// `&nvic::Registers`
+pub fn nvic() -> &'static nvic::Registers {
+ unsafe { ::deref(NVIC) }
+}
+
+/// `&mut nvic::Registers`
+pub unsafe fn nvic_mut() -> &'static mut nvic::Registers {
+ ::deref_mut(NVIC)
+}
+
+/// `&scb::Registers`
+pub fn scb() -> &'static scb::Registers {
+ unsafe { ::deref(SCB) }
+}
+
+/// `&mut scb::Registers`
+pub unsafe fn scb_mut() -> &'static mut scb::Registers {
+ ::deref_mut(SCB)
+}
+
+/// `&syst::Registers`
+pub fn syst() -> &'static syst::Registers {
+ unsafe { ::deref(SYST) }
+}
+
+/// `&mut syst::Registers`
+pub unsafe fn syst_mut() -> &'static mut syst::Registers {
+ ::deref_mut(SYST)
+}
+
+/// `&tpiu::Registers`
+pub fn tpiu() -> &'static tpiu::Registers {
+ unsafe { ::deref(TPIU) }
+}
+
+/// `&mut tpiu::Registers`
+pub unsafe fn tpiu_mut() -> &'static mut tpiu::Registers {
+ ::deref_mut(TPIU)
+}
diff --git a/src/peripheral/mpu.rs b/src/peripheral/mpu.rs
new file mode 100644
index 0000000..e024e62
--- /dev/null
+++ b/src/peripheral/mpu.rs
@@ -0,0 +1,30 @@
+//! Memory Protection Unit
+
+use volatile_register::{RO, RW};
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Type
+ pub _type: RO<u32>,
+ /// Control
+ pub ctrl: RW<u32>,
+ /// Region Number
+ pub rnr: RW<u32>,
+ /// Region Base Address
+ pub rbar: RW<u32>,
+ /// Region Attribute and Size
+ pub rasr: RW<u32>,
+ /// Alias 1 of RBAR
+ pub rbar_a1: RW<u32>,
+ /// Alias 1 of RSAR
+ pub rsar_a1: RW<u32>,
+ /// Alias 2 of RBAR
+ pub rbar_a2: RW<u32>,
+ /// Alias 2 of RSAR
+ pub rsar_a2: RW<u32>,
+ /// Alias 3 of RBAR
+ pub rbar_a3: RW<u32>,
+ /// Alias 3 of RSAR
+ pub rsar_a3: RW<u32>,
+}
diff --git a/src/peripheral/nvic.rs b/src/peripheral/nvic.rs
new file mode 100644
index 0000000..4570c0f
--- /dev/null
+++ b/src/peripheral/nvic.rs
@@ -0,0 +1,25 @@
+//! Nested Vector Interrupt Controller
+
+use volatile_register::{RO, RW};
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Interrupt Set-Enable
+ pub iser: [RW<u32>; 16],
+ reserved0: [u32; 16],
+ /// Interrupt Clear-Enable
+ pub icer: [RW<u32>; 16],
+ reserved1: [u32; 16],
+ /// Interrupt Set-Pending
+ pub ispr: [RW<u32>; 16],
+ reserved2: [u32; 16],
+ /// Interrupt Clear-Pending
+ pub icpr: [RW<u32>; 16],
+ reserved3: [u32; 16],
+ /// Interrupt Active Bit
+ pub iabr: [RO<u32>; 16],
+ reserved4: [u32; 48],
+ /// Interrupt Priority
+ pub ipr: [RW<u32>; 124],
+}
diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs
new file mode 100644
index 0000000..d2b204a
--- /dev/null
+++ b/src/peripheral/scb.rs
@@ -0,0 +1,37 @@
+//! System Control Block
+
+use volatile_register::RW;
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Interrupt Control and State
+ pub icsr: RW<u32>,
+ /// Vector Table Offset
+ pub vtor: RW<u32>,
+ /// Application Interrupt and Reset Control
+ pub aircr: RW<u32>,
+ /// System Control
+ pub scr: RW<u32>,
+ /// Configuration and Control
+ pub ccr: RW<u32>,
+ /// System Handler Priority
+ pub shpr: [RW<u8>; 12],
+ /// System Handler Control and State
+ pub shpcrs: RW<u32>,
+ /// Configurable Fault Status
+ pub cfsr: RW<u32>,
+ /// HardFault Status
+ pub hfsr: RW<u32>,
+ /// Debug Fault Status
+ pub dfsr: RW<u32>,
+ /// MemManage Fault Address
+ pub mmar: RW<u32>,
+ /// BusFault Address
+ pub bfar: RW<u32>,
+ /// Auxiliary Fault Status
+ pub afsr: RW<u32>,
+ reserved: [u32; 18],
+ /// Coprocessor Access Control
+ pub cpacr: RW<u32>,
+}
diff --git a/src/peripheral/syst.rs b/src/peripheral/syst.rs
new file mode 100644
index 0000000..8ee70a1
--- /dev/null
+++ b/src/peripheral/syst.rs
@@ -0,0 +1,16 @@
+//! SysTick: System Timer
+
+use volatile_register::{RO, RW};
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Control and Status
+ pub csr: RW<u32>,
+ /// Reload Value
+ pub rvr: RW<u32>,
+ /// Current Value
+ pub cvr: RW<u32>,
+ /// Calibration Value
+ pub calib: RO<u32>,
+}
diff --git a/src/peripheral/test.rs b/src/peripheral/test.rs
new file mode 100644
index 0000000..c291b16
--- /dev/null
+++ b/src/peripheral/test.rs
@@ -0,0 +1,162 @@
+#[test]
+fn cpuid() {
+ let cpuid = ::peripheral::cpuid();
+
+ assert_eq!(::address(&cpuid.base), 0xE000_ED00);
+ assert_eq!(::address(&cpuid.pfr), 0xE000_ED40);
+ assert_eq!(::address(&cpuid.dfr), 0xE000_ED48);
+ assert_eq!(::address(&cpuid.afr), 0xE000_ED4C);
+ assert_eq!(::address(&cpuid.mmfr), 0xE000_ED50);
+ assert_eq!(::address(&cpuid.isar), 0xE000_ED60);
+ assert_eq!(::address(&cpuid.clidr), 0xE000_ED78);
+ assert_eq!(::address(&cpuid.ctr), 0xE000_ED7C);
+ assert_eq!(::address(&cpuid.ccsidr), 0xE000_ED80);
+ assert_eq!(::address(&cpuid.csselr), 0xE000_ED84);
+}
+
+#[test]
+fn dcb() {
+ for dcb in &[::peripheral::dcb(), unsafe { ::peripheral::dcb_mut() }] {
+ assert_eq!(::address(&dcb.dhcsr), 0xE000_EDF0);
+ assert_eq!(::address(&dcb.dcrsr), 0xE000_EDF4);
+ assert_eq!(::address(&dcb.dcrdr), 0xE000_EDF8);
+ assert_eq!(::address(&dcb.demcr), 0xE000_EDFC);
+ }
+}
+
+#[test]
+fn dwt() {
+ for dwt in &[::peripheral::dwt(), unsafe { ::peripheral::dwt_mut() }] {
+ assert_eq!(::address(&dwt.ctrl), 0xE000_1000);
+ assert_eq!(::address(&dwt.cyccnt), 0xE000_1004);
+ assert_eq!(::address(&dwt.cpicnt), 0xE000_1008);
+ assert_eq!(::address(&dwt.exccnt), 0xE000_100C);
+ assert_eq!(::address(&dwt.sleepcnt), 0xE000_1010);
+ assert_eq!(::address(&dwt.lsucnt), 0xE000_1014);
+ assert_eq!(::address(&dwt.foldcnt), 0xE000_1018);
+ assert_eq!(::address(&dwt.pcsr), 0xE000_101C);
+ assert_eq!(::address(&dwt.c[0].comp), 0xE000_1020);
+ assert_eq!(::address(&dwt.c[0].mask), 0xE000_1024);
+ assert_eq!(::address(&dwt.c[0].function), 0xE000_1028);
+ assert_eq!(::address(&dwt.c[1].comp), 0xE000_1030);
+ assert_eq!(::address(&dwt.c[1].mask), 0xE000_1034);
+ assert_eq!(::address(&dwt.c[1].function), 0xE000_1038);
+ assert_eq!(::address(&dwt.lar), 0xE000_1FB0);
+ assert_eq!(::address(&dwt.lsr), 0xE000_1FB4);
+ }
+}
+
+#[test]
+fn fpb() {
+ for fpb in &[::peripheral::fpb(), unsafe { ::peripheral::fpb_mut() }] {
+ assert_eq!(::address(&fpb.ctrl), 0xE000_2000);
+ assert_eq!(::address(&fpb.remap), 0xE000_2004);
+ assert_eq!(::address(&fpb.comp), 0xE000_2008);
+ assert_eq!(::address(&fpb.comp[1]), 0xE000_200C);
+ assert_eq!(::address(&fpb.lar), 0xE000_2FB0);
+ assert_eq!(::address(&fpb.lsr), 0xE000_2FB4);
+ }
+}
+
+#[test]
+fn fpu() {
+ for fpu in &[::peripheral::fpu(), unsafe { ::peripheral::fpu_mut() }] {
+ assert_eq!(::address(&fpu.fpccr), 0xE000_EF34);
+ assert_eq!(::address(&fpu.fpcar), 0xE000_EF38);
+ assert_eq!(::address(&fpu.fpdscr), 0xE000_EF3C);
+ assert_eq!(::address(&fpu.mvfr), 0xE000_EF40);
+ assert_eq!(::address(&fpu.mvfr[1]), 0xE000_EF44);
+ assert_eq!(::address(&fpu.mvfr[2]), 0xE000_EF48);
+ }
+}
+
+#[test]
+fn itm() {
+ for itm in &[::peripheral::itm(), unsafe { ::peripheral::itm_mut() }] {
+ assert_eq!(::address(&itm.stim), 0xE000_0000);
+ assert_eq!(::address(&itm.ter), 0xE000_0E00);
+ assert_eq!(::address(&itm.tpr), 0xE000_0E40);
+ assert_eq!(::address(&itm.tcr), 0xE000_0E80);
+ assert_eq!(::address(&itm.lar), 0xE000_0FB0);
+ assert_eq!(::address(&itm.lsr), 0xE000_0FB4);
+ }
+}
+
+#[test]
+fn mpu() {
+ for mpu in &[::peripheral::mpu(), unsafe { ::peripheral::mpu_mut() }] {
+ assert_eq!(::address(&mpu._type), 0xE000ED90);
+ assert_eq!(::address(&mpu.ctrl), 0xE000ED94);
+ assert_eq!(::address(&mpu.rnr), 0xE000ED98);
+ assert_eq!(::address(&mpu.rbar), 0xE000ED9C);
+ assert_eq!(::address(&mpu.rasr), 0xE000EDA0);
+ assert_eq!(::address(&mpu.rbar_a1), 0xE000EDA4);
+ assert_eq!(::address(&mpu.rsar_a1), 0xE000EDA8);
+ assert_eq!(::address(&mpu.rbar_a2), 0xE000EDAC);
+ assert_eq!(::address(&mpu.rsar_a2), 0xE000EDB0);
+ assert_eq!(::address(&mpu.rbar_a3), 0xE000EDB4);
+ assert_eq!(::address(&mpu.rsar_a3), 0xE000EDB8);
+ }
+}
+
+#[test]
+fn nvic() {
+ for nvic in &[::peripheral::nvic(), unsafe { ::peripheral::nvic_mut() }] {
+ assert_eq!(::address(&nvic.iser), 0xE000E100);
+ assert_eq!(::address(&nvic.iser[15]), 0xE000E13C);
+ assert_eq!(::address(&nvic.icer), 0xE000E180);
+ assert_eq!(::address(&nvic.icer[7]), 0xE000E19C);
+ assert_eq!(::address(&nvic.icer[15]), 0xE000E1BC);
+ assert_eq!(::address(&nvic.ispr), 0xE000E200);
+ assert_eq!(::address(&nvic.ispr[15]), 0xE000E23C);
+ assert_eq!(::address(&nvic.icpr), 0xE000E280);
+ assert_eq!(::address(&nvic.icpr[15]), 0xE000E2BC);
+ assert_eq!(::address(&nvic.iabr), 0xE000E300);
+ assert_eq!(::address(&nvic.iabr[15]), 0xE000E33C);
+ assert_eq!(::address(&nvic.ipr), 0xE000E400);
+ assert_eq!(::address(&nvic.ipr[59]), 0xE000E4EC);
+ }
+}
+
+#[test]
+fn scb() {
+ for scb in &[::peripheral::scb(), unsafe { ::peripheral::scb_mut() }] {
+ assert_eq!(::address(&scb.icsr), 0xE000_ED04);
+ assert_eq!(::address(&scb.vtor), 0xE000_ED08);
+ assert_eq!(::address(&scb.aircr), 0xE000_ED0C);
+ assert_eq!(::address(&scb.scr), 0xE000_ED10);
+ assert_eq!(::address(&scb.ccr), 0xE000_ED14);
+ assert_eq!(::address(&scb.shpr), 0xE000_ED18);
+ assert_eq!(::address(&scb.shpcrs), 0xE000_ED24);
+ assert_eq!(::address(&scb.cfsr), 0xE000_ED28);
+ assert_eq!(::address(&scb.hfsr), 0xE000_ED2C);
+ assert_eq!(::address(&scb.dfsr), 0xE000_ED30);
+ assert_eq!(::address(&scb.mmar), 0xE000_ED34);
+ assert_eq!(::address(&scb.bfar), 0xE000_ED38);
+ assert_eq!(::address(&scb.afsr), 0xE000_ED3C);
+ assert_eq!(::address(&scb.cpacr), 0xE000_ED88);
+ }
+}
+
+#[test]
+fn syst() {
+ for syst in &[::peripheral::syst(), unsafe { ::peripheral::syst_mut() }] {
+ assert_eq!(::address(&syst.csr), 0xE000_E010);
+ assert_eq!(::address(&syst.rvr), 0xE000_E014);
+ assert_eq!(::address(&syst.cvr), 0xE000_E018);
+ assert_eq!(::address(&syst.calib), 0xE000_E01C);
+ }
+}
+
+#[test]
+fn tpiu() {
+ for tpiu in &[::peripheral::tpiu(), unsafe { ::peripheral::tpiu_mut() }] {
+ assert_eq!(::address(&tpiu.sspsr), 0xE004_0000);
+ assert_eq!(::address(&tpiu.cspsr), 0xE004_0004);
+ assert_eq!(::address(&tpiu.acpr), 0xE004_0010);
+ assert_eq!(::address(&tpiu.sppr), 0xE004_00F0);
+ assert_eq!(::address(&tpiu.lar), 0xE004_0FB0);
+ assert_eq!(::address(&tpiu.lsr), 0xE004_0FB4);
+ assert_eq!(::address(&tpiu._type), 0xE004_0FC8);
+ }
+}
diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs
new file mode 100644
index 0000000..5047351
--- /dev/null
+++ b/src/peripheral/tpiu.rs
@@ -0,0 +1,26 @@
+//! Trace Port Interface Unit
+
+use volatile_register::{RO, RW, WO};
+
+/// Registers
+#[repr(C)]
+pub struct Registers {
+ /// Supported Parallel Port Sizes
+ pub sspsr: RO<u32>,
+ /// Current Parallel Port Size
+ pub cspsr: RW<u32>,
+ reserved0: [u32; 2],
+ /// Asynchronous Clock Prescaler
+ pub acpr: RW<u32>,
+ reserved1: [u32; 55],
+ /// Selected Pin Control
+ pub sppr: RW<u32>,
+ reserved2: [u32; 943],
+ /// Lock Access
+ pub lar: WO<u32>,
+ /// Lock Status
+ pub lsr: RO<u32>,
+ reserved3: [u32; 4],
+ /// TPIU Type
+ pub _type: RO<u32>,
+}
diff --git a/src/register.rs b/src/register.rs
new file mode 100644
index 0000000..66add6b
--- /dev/null
+++ b/src/register.rs
@@ -0,0 +1,126 @@
+//! 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!("msr ", stringify!($name), ",$0") : "=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!("mrs ", "$0,", stringify!($name)) :: "r"(r) ::: "volatile"),
+
+ #[cfg(not(target_arch = "arm"))]
+ _ => {},
+ }
+ }
+ }
+ };
+}
+
+macro_rules! sro {
+ (#[$attr:meta] $name:ident) => {
+ #[$attr]
+ pub mod $name {
+ #![doc = "yay"]
+
+ 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 ", stringify!($r), ",$0") : "=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 ", "$0,", stringify!($r)) :: "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: r15);
+rw!(#[doc = "Program Counter"] pc: r14);
+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);