aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bors[bot] <bors[bot]@users.noreply.github.com> 2018-10-26 18:32:52 +0000
committerGravatar bors[bot] <bors[bot]@users.noreply.github.com> 2018-10-26 18:32:52 +0000
commitbe6c39c725d2ae0cf50e36e07a27fd9a882cb71d (patch)
tree7e97467b81b2ec7a8552ac92681ce6f710187b3b
parente3b7357002f0fa739253c78623f825e0e8a7f1ab (diff)
parente2bda1a5cdda37cec2ea9e1aab2e990f7701da3a (diff)
downloadcortex-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.sh4
-rw-r--r--src/lib.rs1
-rw-r--r--src/peripheral/mod.rs1
-rw-r--r--src/peripheral/nvic.rs5
-rw-r--r--src/peripheral/scb.rs112
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
diff --git a/src/lib.rs b/src/lib.rs
index d00fabd..fda3e01 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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
+ });
+ }
+ }
+}