aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Adam Greig <adam@adamgreig.com> 2020-07-09 01:44:23 +0100
committerGravatar Adam Greig <adam@adamgreig.com> 2020-07-21 23:13:59 +0100
commitb5ad45c7409da165d4cdd24c7af29dadbe8eb6cb (patch)
tree825bae3028b9fce036166e1166e1425b24dcd760
parent9021bcd85dd6364942dc20a7ad2e49c4600693b6 (diff)
downloadcortex-m-b5ad45c7409da165d4cdd24c7af29dadbe8eb6cb.tar.gz
cortex-m-b5ad45c7409da165d4cdd24c7af29dadbe8eb6cb.tar.zst
cortex-m-b5ad45c7409da165d4cdd24c7af29dadbe8eb6cb.zip
Add new InterruptNumber trait
-rw-r--r--src/interrupt.rs23
-rw-r--r--src/peripheral/nvic.rs64
2 files changed, 53 insertions, 34 deletions
diff --git a/src/interrupt.rs b/src/interrupt.rs
index 4d5ef0f..c5da48d 100644
--- a/src/interrupt.rs
+++ b/src/interrupt.rs
@@ -1,8 +1,27 @@
//! Interrupts
-// use core::sync::atomic::{self, Ordering};
+pub use bare_metal::{CriticalSection, Mutex};
-pub use bare_metal::{CriticalSection, Mutex, Nr};
+/// Trait for enums of external interrupt numbers.
+///
+/// This trait should be implemented by a peripheral access crate (PAC)
+/// on its enum of available external interrupts for a specific device.
+/// Each variant must convert to a u16 of its interrupt number,
+/// which is its exception number - 16.
+///
+/// # Safety
+///
+/// This trait must only be implemented on enums of device interrupts. Each
+/// enum variant must represent a distinct value (no duplicates are permitted),
+/// and must always return the same value (do not change at runtime).
+///
+/// These requirements ensure safe nesting of critical sections.
+pub unsafe trait InterruptNumber: Copy {
+ /// Return the interrupt number associated with this variant.
+ ///
+ /// See trait documentation for safety requirements.
+ fn number(self) -> u16;
+}
/// Disables all interrupts
#[inline]
diff --git a/src/peripheral/nvic.rs b/src/peripheral/nvic.rs
index 6627e60..a2f85f4 100644
--- a/src/peripheral/nvic.rs
+++ b/src/peripheral/nvic.rs
@@ -4,7 +4,7 @@ use volatile_register::RW;
#[cfg(not(armv6m))]
use volatile_register::{RO, WO};
-use crate::interrupt::Nr;
+use crate::interrupt::InterruptNumber;
use crate::peripheral::NVIC;
/// Register block
@@ -86,9 +86,9 @@ impl NVIC {
#[inline]
pub fn request<I>(&mut self, interrupt: I)
where
- I: Nr,
+ I: InterruptNumber,
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
unsafe {
self.stir.write(u32::from(nr));
@@ -99,9 +99,9 @@ impl NVIC {
#[inline]
pub fn mask<I>(interrupt: I)
where
- I: Nr,
+ I: InterruptNumber,
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
// NOTE(unsafe) this is a write to a stateless register
unsafe { (*Self::ptr()).icer[usize::from(nr / 32)].write(1 << (nr % 32)) }
}
@@ -112,9 +112,9 @@ impl NVIC {
#[inline]
pub unsafe fn unmask<I>(interrupt: I)
where
- I: Nr,
+ I: InterruptNumber,
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
// NOTE(ptr) this is a write to a stateless register
(*Self::ptr()).iser[usize::from(nr / 32)].write(1 << (nr % 32))
}
@@ -127,11 +127,11 @@ impl NVIC {
#[inline]
pub fn get_priority<I>(interrupt: I) -> u8
where
- I: Nr,
+ I: InterruptNumber,
{
#[cfg(not(armv6m))]
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
// NOTE(unsafe) atomic read with no side effects
unsafe { (*Self::ptr()).ipr[usize::from(nr)].read() }
}
@@ -139,8 +139,8 @@ impl NVIC {
#[cfg(armv6m)]
{
// NOTE(unsafe) atomic read with no side effects
- let ipr_n = unsafe { (*Self::ptr()).ipr[Self::ipr_index(&interrupt)].read() };
- let prio = (ipr_n >> Self::ipr_shift(&interrupt)) & 0x0000_00ff;
+ let ipr_n = unsafe { (*Self::ptr()).ipr[Self::ipr_index(interrupt)].read() };
+ let prio = (ipr_n >> Self::ipr_shift(interrupt)) & 0x0000_00ff;
prio as u8
}
}
@@ -150,9 +150,9 @@ impl NVIC {
#[inline]
pub fn is_active<I>(interrupt: I) -> bool
where
- I: Nr,
+ I: InterruptNumber,
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
let mask = 1 << (nr % 32);
// NOTE(unsafe) atomic read with no side effects
@@ -163,9 +163,9 @@ impl NVIC {
#[inline]
pub fn is_enabled<I>(interrupt: I) -> bool
where
- I: Nr,
+ I: InterruptNumber,
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
let mask = 1 << (nr % 32);
// NOTE(unsafe) atomic read with no side effects
@@ -176,9 +176,9 @@ impl NVIC {
#[inline]
pub fn is_pending<I>(interrupt: I) -> bool
where
- I: Nr,
+ I: InterruptNumber,
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
let mask = 1 << (nr % 32);
// NOTE(unsafe) atomic read with no side effects
@@ -189,9 +189,9 @@ impl NVIC {
#[inline]
pub fn pend<I>(interrupt: I)
where
- I: Nr,
+ I: InterruptNumber,
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
// NOTE(unsafe) atomic stateless write; ICPR doesn't store any state
unsafe { (*Self::ptr()).ispr[usize::from(nr / 32)].write(1 << (nr % 32)) }
@@ -212,19 +212,19 @@ impl NVIC {
#[inline]
pub unsafe fn set_priority<I>(&mut self, interrupt: I, prio: u8)
where
- I: Nr,
+ I: InterruptNumber,
{
#[cfg(not(armv6m))]
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
self.ipr[usize::from(nr)].write(prio)
}
#[cfg(armv6m)]
{
- self.ipr[Self::ipr_index(&interrupt)].modify(|value| {
- let mask = 0x0000_00ff << Self::ipr_shift(&interrupt);
- let prio = u32::from(prio) << Self::ipr_shift(&interrupt);
+ self.ipr[Self::ipr_index(interrupt)].modify(|value| {
+ let mask = 0x0000_00ff << Self::ipr_shift(interrupt);
+ let prio = u32::from(prio) << Self::ipr_shift(interrupt);
(value & !mask) | prio
})
@@ -235,9 +235,9 @@ impl NVIC {
#[inline]
pub fn unpend<I>(interrupt: I)
where
- I: Nr,
+ I: InterruptNumber,
{
- let nr = interrupt.nr();
+ let nr = interrupt.number();
// NOTE(unsafe) atomic stateless write; ICPR doesn't store any state
unsafe { (*Self::ptr()).icpr[usize::from(nr / 32)].write(1 << (nr % 32)) }
@@ -245,19 +245,19 @@ impl NVIC {
#[cfg(armv6m)]
#[inline]
- fn ipr_index<I>(interrupt: &I) -> usize
+ fn ipr_index<I>(interrupt: I) -> usize
where
- I: Nr,
+ I: InterruptNumber,
{
- usize::from(interrupt.nr()) / 4
+ usize::from(interrupt.number()) / 4
}
#[cfg(armv6m)]
#[inline]
- fn ipr_shift<I>(interrupt: &I) -> usize
+ fn ipr_shift<I>(interrupt: I) -> usize
where
- I: Nr,
+ I: InterruptNumber,
{
- (usize::from(interrupt.nr()) % 4) * 8
+ (usize::from(interrupt.number()) % 4) * 8
}
}