aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bors[bot] <26634292+bors[bot]@users.noreply.github.com> 2020-07-22 07:12:25 +0000
committerGravatar GitHub <noreply@github.com> 2020-07-22 07:12:25 +0000
commit9dee813277e200f431d0f63522fafe327cdb5034 (patch)
treec5c70526f9d7a84db4352ad9f423c49a00c8d5fb
parent498a7a12529bc652727afa5768f4bd5357991401 (diff)
parenta83e5f342711ad9436b95623b6326e58350160ab (diff)
downloadcortex-m-9dee813277e200f431d0f63522fafe327cdb5034.tar.gz
cortex-m-9dee813277e200f431d0f63522fafe327cdb5034.tar.zst
cortex-m-9dee813277e200f431d0f63522fafe327cdb5034.zip
Merge #241
241: Add new InterruptNumber trait r=therealprof a=adamgreig This is a first go at the new trait needed for https://github.com/rust-embedded/svd2rust/pull/455 since we removed `Nr` from bare-metal. In this case I've written it as `unsafe trait InterruptNumber: Into<u16>` rather than providing a conversion method inside the trait; I think this is neat and idiomatic but please correct me if there's a reason to not do it like this. [Here's](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4f2f8b9604b5a62298f9907780d844c7) a playground link showing an example implementation. Co-authored-by: Adam Greig <adam@adamgreig.com>
-rw-r--r--CHANGELOG.md5
-rw-r--r--src/interrupt.rs23
-rw-r--r--src/peripheral/nvic.rs64
3 files changed, 58 insertions, 34 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 274eb80..a58686f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
+### Added
+
+- New `InterruptNumber` trait is now required on interrupt arguments to the
+ various NVIC functions, replacing the previous use of `Nr` from bare-metal.
+
## [v0.6.2] - 2020-01-12
### Added
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
}
}