aboutsummaryrefslogtreecommitdiff
path: root/src/peripheral/nvic.rs
diff options
context:
space:
mode:
authorGravatar Adam Greig <adam@adamgreig.com> 2023-10-16 01:33:34 +0100
committerGravatar Adam Greig <adam@adamgreig.com> 2023-10-16 01:57:48 +0100
commit0a701d68b51da9468a9a5e518667d4c037102e85 (patch)
treeea97c5f9726b46e5f9aef2721208645fa37d9750 /src/peripheral/nvic.rs
parentc52330f333afe5358b5b6cccb4837eeb92af2759 (diff)
downloadcortex-m-0a701d68b51da9468a9a5e518667d4c037102e85.tar.gz
cortex-m-0a701d68b51da9468a9a5e518667d4c037102e85.tar.zst
cortex-m-0a701d68b51da9468a9a5e518667d4c037102e85.zip
Move cortex-m crate into cortex-m directory
Diffstat (limited to 'src/peripheral/nvic.rs')
-rw-r--r--src/peripheral/nvic.rs272
1 files changed, 0 insertions, 272 deletions
diff --git a/src/peripheral/nvic.rs b/src/peripheral/nvic.rs
deleted file mode 100644
index fccd6a2..0000000
--- a/src/peripheral/nvic.rs
+++ /dev/null
@@ -1,272 +0,0 @@
-//! Nested Vector Interrupt Controller
-
-use volatile_register::RW;
-#[cfg(not(armv6m))]
-use volatile_register::{RO, WO};
-
-use crate::interrupt::InterruptNumber;
-use crate::peripheral::NVIC;
-
-/// Register block
-#[repr(C)]
-pub struct RegisterBlock {
- /// Interrupt Set-Enable
- pub iser: [RW<u32>; 16],
-
- _reserved0: [u32; 16],
-
- /// Interrupt Clear-Enable
- pub icer: [RW<u32>; 16],
-
- _reserved1: [u32; 16],
-
- /// Interrupt Set-Pending
- pub ispr: [RW<u32>; 16],
-
- _reserved2: [u32; 16],
-
- /// Interrupt Clear-Pending
- pub icpr: [RW<u32>; 16],
-
- _reserved3: [u32; 16],
-
- /// Interrupt Active Bit (not present on Cortex-M0 variants)
- #[cfg(not(armv6m))]
- pub iabr: [RO<u32>; 16],
- #[cfg(armv6m)]
- _reserved4: [u32; 16],
-
- _reserved5: [u32; 16],
-
- #[cfg(armv8m)]
- /// Interrupt Target Non-secure (only present on Arm v8-M)
- pub itns: [RW<u32>; 16],
- #[cfg(not(armv8m))]
- _reserved6: [u32; 16],
-
- _reserved7: [u32; 16],
-
- /// Interrupt Priority
- ///
- /// On ARMv7-M, 124 word-sized registers are available. Each of those
- /// contains of 4 interrupt priorities of 8 byte each.The architecture
- /// specifically allows accessing those along byte boundaries, so they are
- /// represented as 496 byte-sized registers, for convenience, and to allow
- /// atomic priority updates.
- ///
- /// On ARMv6-M, the registers must only be accessed along word boundaries,
- /// so convenient byte-sized representation wouldn't work on that
- /// architecture.
- #[cfg(not(armv6m))]
- pub ipr: [RW<u8>; 496],
-
- /// Interrupt Priority
- ///
- /// On ARMv7-M, 124 word-sized registers are available. Each of those
- /// contains of 4 interrupt priorities of 8 byte each.The architecture
- /// specifically allows accessing those along byte boundaries, so they are
- /// represented as 496 byte-sized registers, for convenience, and to allow
- /// atomic priority updates.
- ///
- /// On ARMv6-M, the registers must only be accessed along word boundaries,
- /// so convenient byte-sized representation wouldn't work on that
- /// architecture.
- #[cfg(armv6m)]
- pub ipr: [RW<u32>; 8],
-
- #[cfg(not(armv6m))]
- _reserved8: [u32; 580],
-
- /// Software Trigger Interrupt
- #[cfg(not(armv6m))]
- pub stir: WO<u32>,
-}
-
-impl NVIC {
- /// Request an IRQ in software
- ///
- /// Writing a value to the INTID field is the same as manually pending an interrupt by setting
- /// the corresponding interrupt bit in an Interrupt Set Pending Register. This is similar to
- /// [`NVIC::pend`].
- ///
- /// This method is not available on ARMv6-M chips.
- ///
- /// [`NVIC::pend`]: #method.pend
- #[cfg(not(armv6m))]
- #[inline]
- pub fn request<I>(interrupt: I)
- where
- I: InterruptNumber,
- {
- let nr = interrupt.number();
-
- // NOTE(ptr) this is a write to a stateless register
- unsafe { (*Self::PTR).stir.write(u32::from(nr)) }
- }
-
- /// Disables `interrupt`
- #[inline]
- pub fn mask<I>(interrupt: I)
- where
- I: InterruptNumber,
- {
- 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)) }
- }
-
- /// Enables `interrupt`
- ///
- /// This function is `unsafe` because it can break mask-based critical sections
- #[inline]
- pub unsafe fn unmask<I>(interrupt: I)
- where
- I: InterruptNumber,
- {
- 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))
- }
-
- /// Returns the NVIC priority of `interrupt`
- ///
- /// *NOTE* NVIC encodes priority in the highest bits of a byte so values like `1` and `2` map
- /// to the same priority. Also for NVIC priorities, a lower value (e.g. `16`) has higher
- /// priority (urgency) than a larger value (e.g. `32`).
- #[inline]
- pub fn get_priority<I>(interrupt: I) -> u8
- where
- I: InterruptNumber,
- {
- #[cfg(not(armv6m))]
- {
- let nr = interrupt.number();
- // NOTE(unsafe) atomic read with no side effects
- unsafe { (*Self::PTR).ipr[usize::from(nr)].read() }
- }
-
- #[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;
- prio as u8
- }
- }
-
- /// Is `interrupt` active or pre-empted and stacked
- #[cfg(not(armv6m))]
- #[inline]
- pub fn is_active<I>(interrupt: I) -> bool
- where
- I: InterruptNumber,
- {
- let nr = interrupt.number();
- let mask = 1 << (nr % 32);
-
- // NOTE(unsafe) atomic read with no side effects
- unsafe { ((*Self::PTR).iabr[usize::from(nr / 32)].read() & mask) == mask }
- }
-
- /// Checks if `interrupt` is enabled
- #[inline]
- pub fn is_enabled<I>(interrupt: I) -> bool
- where
- I: InterruptNumber,
- {
- let nr = interrupt.number();
- let mask = 1 << (nr % 32);
-
- // NOTE(unsafe) atomic read with no side effects
- unsafe { ((*Self::PTR).iser[usize::from(nr / 32)].read() & mask) == mask }
- }
-
- /// Checks if `interrupt` is pending
- #[inline]
- pub fn is_pending<I>(interrupt: I) -> bool
- where
- I: InterruptNumber,
- {
- let nr = interrupt.number();
- let mask = 1 << (nr % 32);
-
- // NOTE(unsafe) atomic read with no side effects
- unsafe { ((*Self::PTR).ispr[usize::from(nr / 32)].read() & mask) == mask }
- }
-
- /// Forces `interrupt` into pending state
- #[inline]
- pub fn pend<I>(interrupt: I)
- where
- I: InterruptNumber,
- {
- 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)) }
- }
-
- /// Sets the "priority" of `interrupt` to `prio`
- ///
- /// *NOTE* See [`get_priority`](struct.NVIC.html#method.get_priority) method for an explanation
- /// of how NVIC priorities work.
- ///
- /// 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`](crate::register::basepri)) and compromise memory safety.
- #[inline]
- pub unsafe fn set_priority<I>(&mut self, interrupt: I, prio: u8)
- where
- I: InterruptNumber,
- {
- #[cfg(not(armv6m))]
- {
- 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);
-
- (value & !mask) | prio
- })
- }
- }
-
- /// Clears `interrupt`'s pending state
- #[inline]
- pub fn unpend<I>(interrupt: I)
- where
- I: InterruptNumber,
- {
- 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)) }
- }
-
- #[cfg(armv6m)]
- #[inline]
- fn ipr_index<I>(interrupt: I) -> usize
- where
- I: InterruptNumber,
- {
- usize::from(interrupt.number()) / 4
- }
-
- #[cfg(armv6m)]
- #[inline]
- fn ipr_shift<I>(interrupt: I) -> usize
- where
- I: InterruptNumber,
- {
- (usize::from(interrupt.number()) % 4) * 8
- }
-}