diff options
author | 2023-10-16 01:33:34 +0100 | |
---|---|---|
committer | 2023-10-16 01:57:48 +0100 | |
commit | 0a701d68b51da9468a9a5e518667d4c037102e85 (patch) | |
tree | ea97c5f9726b46e5f9aef2721208645fa37d9750 /src/peripheral/nvic.rs | |
parent | c52330f333afe5358b5b6cccb4837eeb92af2759 (diff) | |
download | cortex-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.rs | 272 |
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 - } -} |