Skip to content

Commit be6c39c

Browse files
bors[bot]japaric
andcommitted
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>
2 parents e3b7357 + e2bda1a commit be6c39c

File tree

5 files changed

+121
-2
lines changed

5 files changed

+121
-2
lines changed

ci/script.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
set -euxo pipefail
22

33
main() {
4+
if [ $TRAVIS_RUST_VERSION = nightly ]; then
5+
export RUSTFLAGS="-D warnings"
6+
fi
7+
48
cargo check --target $TARGET
59

610
if [ $TRAVIS_RUST_VERSION = nightly ]; then

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
3333
#![cfg_attr(feature = "inline-asm", feature(asm))]
3434
#![deny(missing_docs)]
35-
#![deny(warnings)]
3635
#![no_std]
3736

3837
extern crate aligned;

src/peripheral/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@
7777
7878
// TODO stand-alone registers: ICTR, ACTLR and STIR
7979

80-
#![allow(private_no_mangle_statics)]
8180

8281
use core::marker::PhantomData;
8382
use core::ops;

src/peripheral/nvic.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ impl NVIC {
177177
///
178178
/// On ARMv6-M, updating an interrupt priority requires a read-modify-write operation. On
179179
/// ARMv7-M, the operation is performed in a single atomic write operation.
180+
///
181+
/// # Unsafety
182+
///
183+
/// Changing priority levels can break priority-based critical sections (see
184+
/// [`register::basepri`](../register/basepri/index.html)) and compromise memory safety.
180185
pub unsafe fn set_priority<I>(&mut self, interrupt: I, prio: u8)
181186
where
182187
I: Nr,

src/peripheral/scb.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,3 +669,115 @@ impl SCB {
669669
}
670670
}
671671
}
672+
673+
/// System handlers, exceptions with configurable priority
674+
#[allow(non_camel_case_types)]
675+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
676+
pub enum SystemHandler {
677+
// NonMaskableInt, // priority is fixed
678+
// HardFault, // priority is fixed
679+
/// Memory management interrupt (not present on Cortex-M0 variants)
680+
#[cfg(not(armv6m))]
681+
MemoryManagement,
682+
683+
/// Bus fault interrupt (not present on Cortex-M0 variants)
684+
#[cfg(not(armv6m))]
685+
BusFault,
686+
687+
/// Usage fault interrupt (not present on Cortex-M0 variants)
688+
#[cfg(not(armv6m))]
689+
UsageFault,
690+
691+
/// Secure fault interrupt (only on ARMv8-M)
692+
#[cfg(any(armv8m, target_arch = "x86_64"))]
693+
SecureFault,
694+
695+
/// SV call interrupt
696+
SVCall,
697+
698+
/// Debug monitor interrupt (not present on Cortex-M0 variants)
699+
#[cfg(not(armv6m))]
700+
DebugMonitor,
701+
702+
/// Pend SV interrupt
703+
PendSV,
704+
705+
/// System Tick interrupt
706+
SysTick,
707+
}
708+
709+
impl SystemHandler {
710+
fn index(&self) -> u8 {
711+
match *self {
712+
#[cfg(not(armv6m))]
713+
SystemHandler::MemoryManagement => 4,
714+
#[cfg(not(armv6m))]
715+
SystemHandler::BusFault => 5,
716+
#[cfg(not(armv6m))]
717+
SystemHandler::UsageFault => 6,
718+
#[cfg(any(armv8m, target_arch = "x86_64"))]
719+
SystemHandler::SecureFault => 7,
720+
SystemHandler::SVCall => 11,
721+
#[cfg(not(armv6m))]
722+
SystemHandler::DebugMonitor => 12,
723+
SystemHandler::PendSV => 14,
724+
SystemHandler::SysTick => 15,
725+
}
726+
}
727+
}
728+
729+
impl SCB {
730+
/// Returns the hardware priority of `system_handler`
731+
///
732+
/// *NOTE*: Hardware priority does not exactly match logical priority levels. See
733+
/// [`NVIC.get_priority`](struct.NVIC.html#method.get_priority) for more details.
734+
pub fn get_priority(system_handler: SystemHandler) -> u8 {
735+
let index = system_handler.index();
736+
737+
#[cfg(not(armv6m))]
738+
{
739+
// NOTE(unsafe) atomic read with no side effects
740+
unsafe { (*Self::ptr()).shpr[usize::from(index - 4)].read() }
741+
}
742+
743+
#[cfg(armv6m)]
744+
{
745+
// NOTE(unsafe) atomic read with no side effects
746+
let shpr = unsafe { (*Self::ptr()).shpr[usize::from((index - 8) / 4)].read() };
747+
let prio = (shpr >> (8 * (index % 4))) & 0x000000ff;
748+
prio as u8
749+
}
750+
}
751+
752+
/// Sets the hardware priority of `system_handler` to `prio`
753+
///
754+
/// *NOTE*: Hardware priority does not exactly match logical priority levels. See
755+
/// [`NVIC.get_priority`](struct.NVIC.html#method.get_priority) for more details.
756+
///
757+
/// On ARMv6-M, updating a system handler priority requires a read-modify-write operation. On
758+
/// ARMv7-M, the operation is performed in a single, atomic write operation.
759+
///
760+
/// # Unsafety
761+
///
762+
/// Changing priority levels can break priority-based critical sections (see
763+
/// [`register::basepri`](../register/basepri/index.html)) and compromise memory safety.
764+
pub unsafe fn set_priority(&mut self, system_handler: SystemHandler, prio: u8) {
765+
let index = system_handler.index();
766+
767+
#[cfg(not(armv6m))]
768+
{
769+
self.shpr[usize::from(index - 4)].write(prio)
770+
}
771+
772+
#[cfg(armv6m)]
773+
{
774+
self.shpr[usize::from((index - 8) / 4)].modify(|value| {
775+
let shift = 8 * (index % 4);
776+
let mask = 0x000000ff << shift;
777+
let prio = u32::from(prio) << shift;
778+
779+
(value & !mask) | prio
780+
});
781+
}
782+
}
783+
}

0 commit comments

Comments
 (0)