Skip to content

Commit 66e1d70

Browse files
committed
add high level API to set priority of system handlers
1 parent e3b7357 commit 66e1d70

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

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: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,3 +669,116 @@ 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+
// #[cfg(not(armv6m))]
699+
// DebugMonitor, // unclear whether this has configurable priority
700+
/// Pend SV interrupt
701+
PendSV,
702+
703+
/// System Tick interrupt
704+
SysTick,
705+
706+
// Make this enum extensible
707+
#[doc(hidden)]
708+
__DO_NOT_MATCH_AGAINST_THIS_VARIANT__,
709+
}
710+
711+
impl SystemHandler {
712+
fn index(&self) -> u8 {
713+
match *self {
714+
#[cfg(not(armv6m))]
715+
SystemHandler::MemoryManagement => 4,
716+
#[cfg(not(armv6m))]
717+
SystemHandler::BusFault => 5,
718+
#[cfg(not(armv6m))]
719+
SystemHandler::UsageFault => 6,
720+
#[cfg(any(armv8m, target_arch = "x86_64"))]
721+
SystemHandler::SecureFault => 7,
722+
SystemHandler::SVCall => 11,
723+
SystemHandler::PendSV => 14,
724+
SystemHandler::SysTick => 15,
725+
SystemHandler::__DO_NOT_MATCH_AGAINST_THIS_VARIANT__ => unreachable!(),
726+
}
727+
}
728+
}
729+
730+
impl SCB {
731+
/// Returns the hardware priority of `system_handler`
732+
///
733+
/// *NOTE*: Hardware priority does not exactly match logical priority levels. See
734+
/// [`NVIC.get_priority`](struct.NVIC.html#method.get_priority) for more details.
735+
pub fn get_priority(system_handler: SystemHandler) -> u8 {
736+
let index = system_handler.index();
737+
738+
#[cfg(not(armv6m))]
739+
{
740+
// NOTE(unsafe) atomic read with no side effects
741+
unsafe { (*Self::ptr()).shpr[usize::from(index - 4)].read() }
742+
}
743+
744+
#[cfg(armv6m)]
745+
{
746+
// NOTE(unsafe) atomic read with no side effects
747+
let shpr = unsafe { (*Self::ptr()).shpr[usize::from((index - 8) / 4)].read() };
748+
let prio = (shpr >> (index % 4)) & 0x000000ff;
749+
prio as u8
750+
}
751+
}
752+
753+
/// Sets the hardware priority of `system_handler` to `prio`
754+
///
755+
/// *NOTE*: Hardware priority does not exactly match logical priority levels. See
756+
/// [`NVIC.get_priority`](struct.NVIC.html#method.get_priority) for more details.
757+
///
758+
/// On ARMv6-M, updating a system handler priority requires a read-modify-write operation. On
759+
/// ARMv7-M, the operation is performed in a single, atomic write operation.
760+
///
761+
/// # Unsafety
762+
///
763+
/// Changing priority levels can break priority-based critical sections (see
764+
/// [`register::basepri`](../register/basepri/index.html)) and compromise memory safety.
765+
pub unsafe fn set_priority(&mut self, system_handler: SystemHandler, prio: u8) {
766+
let index = system_handler.index();
767+
768+
#[cfg(not(armv6m))]
769+
{
770+
self.shpr[usize::from(index - 4)].write(prio)
771+
}
772+
773+
#[cfg(armv6m)]
774+
{
775+
self.shpr[usize::from((index - 8) / 4)].modify(|value| {
776+
let shift = index % 4;
777+
let mask = 0x000000ff << shift;
778+
let prio = u32::from(prio) << shift;
779+
780+
(value & !mask) | prio
781+
});
782+
}
783+
}
784+
}

0 commit comments

Comments
 (0)