diff options
author | 2018-10-26 18:32:52 +0000 | |
---|---|---|
committer | 2018-10-26 18:32:52 +0000 | |
commit | be6c39c725d2ae0cf50e36e07a27fd9a882cb71d (patch) | |
tree | 7e97467b81b2ec7a8552ac92681ce6f710187b3b | |
parent | e3b7357002f0fa739253c78623f825e0e8a7f1ab (diff) | |
parent | e2bda1a5cdda37cec2ea9e1aab2e990f7701da3a (diff) | |
download | cortex-m-be6c39c725d2ae0cf50e36e07a27fd9a882cb71d.tar.gz cortex-m-be6c39c725d2ae0cf50e36e07a27fd9a882cb71d.tar.zst cortex-m-be6c39c725d2ae0cf50e36e07a27fd9a882cb71d.zip |
Merge #117
117: add high level API to set priority of system handlers r=therealprof a=japaric
needed for cortex-m-rtfm v0.4.x (it makes my life easier / it makes it easier to
support ARMv6-M)
r? @rust-embedded/cortex-m (anyone)
Co-authored-by: Jorge Aparicio <jorge@japaric.io>
-rw-r--r-- | ci/script.sh | 4 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/peripheral/mod.rs | 1 | ||||
-rw-r--r-- | src/peripheral/nvic.rs | 5 | ||||
-rw-r--r-- | src/peripheral/scb.rs | 112 |
5 files changed, 121 insertions, 2 deletions
diff --git a/ci/script.sh b/ci/script.sh index d1d9279..20a8ea2 100644 --- a/ci/script.sh +++ b/ci/script.sh @@ -1,6 +1,10 @@ set -euxo pipefail main() { + if [ $TRAVIS_RUST_VERSION = nightly ]; then + export RUSTFLAGS="-D warnings" + fi + cargo check --target $TARGET if [ $TRAVIS_RUST_VERSION = nightly ]; then @@ -32,7 +32,6 @@ #![cfg_attr(feature = "inline-asm", feature(asm))] #![deny(missing_docs)] -#![deny(warnings)] #![no_std] extern crate aligned; diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index fe52bd1..6aacb73 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -77,7 +77,6 @@ // TODO stand-alone registers: ICTR, ACTLR and STIR -#![allow(private_no_mangle_statics)] use core::marker::PhantomData; use core::ops; diff --git a/src/peripheral/nvic.rs b/src/peripheral/nvic.rs index 1a6a027..1005799 100644 --- a/src/peripheral/nvic.rs +++ b/src/peripheral/nvic.rs @@ -177,6 +177,11 @@ impl NVIC { /// /// On ARMv6-M, updating an interrupt priority requires a read-modify-write operation. On /// ARMv7-M, the operation is performed in a single atomic write operation. + /// + /// # Unsafety + /// + /// Changing priority levels can break priority-based critical sections (see + /// [`register::basepri`](../register/basepri/index.html)) and compromise memory safety. pub unsafe fn set_priority<I>(&mut self, interrupt: I, prio: u8) where I: Nr, diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index e773c9c..888a3db 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -669,3 +669,115 @@ impl SCB { } } } + +/// System handlers, exceptions with configurable priority +#[allow(non_camel_case_types)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum SystemHandler { + // NonMaskableInt, // priority is fixed + // HardFault, // priority is fixed + /// Memory management interrupt (not present on Cortex-M0 variants) + #[cfg(not(armv6m))] + MemoryManagement, + + /// Bus fault interrupt (not present on Cortex-M0 variants) + #[cfg(not(armv6m))] + BusFault, + + /// Usage fault interrupt (not present on Cortex-M0 variants) + #[cfg(not(armv6m))] + UsageFault, + + /// Secure fault interrupt (only on ARMv8-M) + #[cfg(any(armv8m, target_arch = "x86_64"))] + SecureFault, + + /// SV call interrupt + SVCall, + + /// Debug monitor interrupt (not present on Cortex-M0 variants) + #[cfg(not(armv6m))] + DebugMonitor, + + /// Pend SV interrupt + PendSV, + + /// System Tick interrupt + SysTick, +} + +impl SystemHandler { + fn index(&self) -> u8 { + match *self { + #[cfg(not(armv6m))] + SystemHandler::MemoryManagement => 4, + #[cfg(not(armv6m))] + SystemHandler::BusFault => 5, + #[cfg(not(armv6m))] + SystemHandler::UsageFault => 6, + #[cfg(any(armv8m, target_arch = "x86_64"))] + SystemHandler::SecureFault => 7, + SystemHandler::SVCall => 11, + #[cfg(not(armv6m))] + SystemHandler::DebugMonitor => 12, + SystemHandler::PendSV => 14, + SystemHandler::SysTick => 15, + } + } +} + +impl SCB { + /// Returns the hardware priority of `system_handler` + /// + /// *NOTE*: Hardware priority does not exactly match logical priority levels. See + /// [`NVIC.get_priority`](struct.NVIC.html#method.get_priority) for more details. + pub fn get_priority(system_handler: SystemHandler) -> u8 { + let index = system_handler.index(); + + #[cfg(not(armv6m))] + { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).shpr[usize::from(index - 4)].read() } + } + + #[cfg(armv6m)] + { + // NOTE(unsafe) atomic read with no side effects + let shpr = unsafe { (*Self::ptr()).shpr[usize::from((index - 8) / 4)].read() }; + let prio = (shpr >> (8 * (index % 4))) & 0x000000ff; + prio as u8 + } + } + + /// Sets the hardware priority of `system_handler` to `prio` + /// + /// *NOTE*: Hardware priority does not exactly match logical priority levels. See + /// [`NVIC.get_priority`](struct.NVIC.html#method.get_priority) for more details. + /// + /// On ARMv6-M, updating a system handler priority requires a read-modify-write operation. On + /// ARMv7-M, the operation is performed in a single, atomic write operation. + /// + /// # Unsafety + /// + /// Changing priority levels can break priority-based critical sections (see + /// [`register::basepri`](../register/basepri/index.html)) and compromise memory safety. + pub unsafe fn set_priority(&mut self, system_handler: SystemHandler, prio: u8) { + let index = system_handler.index(); + + #[cfg(not(armv6m))] + { + self.shpr[usize::from(index - 4)].write(prio) + } + + #[cfg(armv6m)] + { + self.shpr[usize::from((index - 8) / 4)].modify(|value| { + let shift = 8 * (index % 4); + let mask = 0x000000ff << shift; + let prio = u32::from(prio) << shift; + + (value & !mask) | prio + }); + } + } +} |