From 2d99f9ad6c5cea3a697c7ad6030d8879ad356ded Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 21 Apr 2022 09:38:55 +0200 Subject: [PATCH 1/4] Add ability to set priority grouping. --- src/peripheral/scb.rs | 56 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index b9cf0e4b..3ad1e62e 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -119,6 +119,24 @@ mod fpu_consts { #[cfg(has_fpu)] use self::fpu_consts::*; +/// Priority Grouping +/// +/// Determines the split of group priority from subpriority. +#[derive(Debug, Clone, Copy)] +#[repr(u8)] +pub enum PriorityGrouping { + /// 4 bits for group priorities, 0 bits for subpriorities + Group4Sub0 = 0b011, // 0b0xx + /// 3 bits for group priorities, 1 bit for subpriorities + Group3Sub1 = 0b100, + /// 2 bits for group priorities, 2 bits for subpriorities + Group2Sub2 = 0b101, + /// 1 bit for group priorities, 3 bits for subpriorities + Group1Sub3 = 0b110, + /// 0 bits for group priorities, 4 bits for subpriorities + Group0Sub4 = 0b111, +} + #[cfg(has_fpu)] impl SCB { /// Shorthand for `set_fpu_access_mode(FpuAccessMode::Disabled)` @@ -839,7 +857,8 @@ impl SCB { } const SCB_AIRCR_VECTKEY: u32 = 0x05FA << 16; -const SCB_AIRCR_PRIGROUP_MASK: u32 = 0x7 << 8; +const SCB_AIRCR_PRIGROUP_POS: u32 = 8; +const SCB_AIRCR_PRIGROUP_MASK: u32 = 0x7 << SCB_AIRCR_PRIGROUP_POS; const SCB_AIRCR_SYSRESETREQ: u32 = 1 << 2; impl SCB { @@ -848,13 +867,11 @@ impl SCB { pub fn sys_reset() -> ! { crate::asm::dsb(); unsafe { - (*Self::PTR).aircr.modify( - |r| { - SCB_AIRCR_VECTKEY | // otherwise the write is ignored - r & SCB_AIRCR_PRIGROUP_MASK | // keep priority group unchanged - SCB_AIRCR_SYSRESETREQ - }, // set the bit - ) + (*Self::PTR).aircr.modify(|r| { + SCB_AIRCR_VECTKEY | // Unlock for writing. + r & SCB_AIRCR_PRIGROUP_MASK | // Keep priority grouping unchanged. + SCB_AIRCR_SYSRESETREQ // Set reset bit. + }) }; crate::asm::dsb(); loop { @@ -862,6 +879,29 @@ impl SCB { crate::asm::nop(); // avoid rust-lang/rust#28728 } } + + /// Set the priority grouping. + #[inline] + pub fn set_priority_grouping(&mut self, grouping: PriorityGrouping) { + unsafe { + self.aircr.write({ + SCB_AIRCR_VECTKEY | // Unlock for writing. + (grouping as u32) << SCB_AIRCR_PRIGROUP_POS + }); + } + } + + /// Get the priority grouping. + #[inline] + pub fn get_priority_grouping(&self) -> PriorityGrouping { + match self.aircr.read() & SCB_AIRCR_PRIGROUP_MASK >> SCB_AIRCR_PRIGROUP_POS { + 0b111 => PriorityGrouping::Group0Sub4, + 0b110 => PriorityGrouping::Group1Sub3, + 0b101 => PriorityGrouping::Group2Sub2, + 0b100 => PriorityGrouping::Group3Sub1, + /* 0b0xx */ _ => PriorityGrouping::Group4Sub0, + } + } } const SCB_ICSR_PENDSVSET: u32 = 1 << 28; From 208b0c3192e29244c4cfd609442f883cc1a47d24 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 22 Apr 2022 05:55:03 +0200 Subject: [PATCH 2/4] Allow encoding/decoding priority with priority grouping. --- src/peripheral/scb.rs | 104 +++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 16 deletions(-) diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index 3ad1e62e..c4942241 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -121,20 +121,89 @@ use self::fpu_consts::*; /// Priority Grouping /// -/// Determines the split of group priority from subpriority. +/// Determines the split of preemption priority from sub-priority. #[derive(Debug, Clone, Copy)] #[repr(u8)] pub enum PriorityGrouping { - /// 4 bits for group priorities, 0 bits for subpriorities - Group4Sub0 = 0b011, // 0b0xx - /// 3 bits for group priorities, 1 bit for subpriorities - Group3Sub1 = 0b100, - /// 2 bits for group priorities, 2 bits for subpriorities - Group2Sub2 = 0b101, - /// 1 bit for group priorities, 3 bits for subpriorities - Group1Sub3 = 0b110, - /// 0 bits for group priorities, 4 bits for subpriorities - Group0Sub4 = 0b111, + /// Priority grouping 0 + Prigroup0 = 0, + /// Priority grouping 1 + Prigroup1 = 1, + /// Priority grouping 2 + Prigroup2 = 2, + /// Priority grouping 3 + Prigroup3 = 3, + /// Priority grouping 4 + Prigroup4 = 4, + /// Priority grouping 5 + Prigroup5 = 5, + /// Priority grouping 6 + Prigroup6 = 6, + /// Priority grouping 7 + Prigroup7 = 7, +} + +impl PriorityGrouping { + #[inline] + const fn preemption_priority_bits(&self, nvic_prio_bits: u8) -> u8 { + let bits = 7 - *self as u8; + + if bits > nvic_prio_bits { + nvic_prio_bits + } else { + bits + } + } + + #[inline] + const fn sub_priority_bits(&self, nvic_prio_bits: u8) -> u8 { + let bits = *self as u8 + nvic_prio_bits; + + if bits <= 7 { + 0 + } else { + bits - 7 + } + } + + /// Encode `preemption_priority` and `sub_priority` to fit in `nvic_prio_bits`. + #[inline] + pub const fn encode_priority( + &self, + nvic_prio_bits: u8, + preemption_priority: u8, + sub_priority: u8, + ) -> u8 { + let preemption_priority_bits = self.preemption_priority_bits(nvic_prio_bits); + let sub_priority_bits = self.sub_priority_bits(nvic_prio_bits); + + let premption_priority_mask = (1 << preemption_priority_bits) - 1; + let sub_priority_mask = (1 << sub_priority_bits) - 1; + + debug_assert!(preemption_priority <= premption_priority_mask); + debug_assert!(sub_priority <= sub_priority_mask); + + let priority = ((preemption_priority & premption_priority_mask) << sub_priority_bits) + | (sub_priority & sub_priority_mask); + + // Priority is stored in the highest bits. + priority << (8 - nvic_prio_bits) + } + + /// Decode priority stored in `nvic_prio_bits` into a tuple consisting of + /// the preemption priority and sub-priority. + #[inline] + pub const fn decode_priority(&self, nvic_prio_bits: u8, mut priority: u8) -> (u8, u8) { + // Priority is stored in the highest bits. + priority >>= 8 - nvic_prio_bits; + + let sub_priority_bits = self.sub_priority_bits(nvic_prio_bits); + + let preemption_priority = priority >> sub_priority_bits; + let sub_priority = priority & ((1 << sub_priority_bits) - 1); + + (preemption_priority, sub_priority) + } } #[cfg(has_fpu)] @@ -895,11 +964,14 @@ impl SCB { #[inline] pub fn get_priority_grouping(&self) -> PriorityGrouping { match self.aircr.read() & SCB_AIRCR_PRIGROUP_MASK >> SCB_AIRCR_PRIGROUP_POS { - 0b111 => PriorityGrouping::Group0Sub4, - 0b110 => PriorityGrouping::Group1Sub3, - 0b101 => PriorityGrouping::Group2Sub2, - 0b100 => PriorityGrouping::Group3Sub1, - /* 0b0xx */ _ => PriorityGrouping::Group4Sub0, + 0 => PriorityGrouping::Prigroup0, + 1 => PriorityGrouping::Prigroup1, + 2 => PriorityGrouping::Prigroup2, + 3 => PriorityGrouping::Prigroup3, + 4 => PriorityGrouping::Prigroup4, + 5 => PriorityGrouping::Prigroup5, + 6 => PriorityGrouping::Prigroup6, + _ => PriorityGrouping::Prigroup7, } } } From 4e0526f6d3488835a6c9b0621bd623e1ffd09641 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 5 May 2022 14:53:26 +0200 Subject: [PATCH 3/4] Use generic constant for `NVIC_PRIO_BITS`. --- src/peripheral/scb.rs | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index c4942241..a666465e 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -124,7 +124,7 @@ use self::fpu_consts::*; /// Determines the split of preemption priority from sub-priority. #[derive(Debug, Clone, Copy)] #[repr(u8)] -pub enum PriorityGrouping { +pub enum PriorityGrouping { /// Priority grouping 0 Prigroup0 = 0, /// Priority grouping 1 @@ -143,21 +143,21 @@ pub enum PriorityGrouping { Prigroup7 = 7, } -impl PriorityGrouping { +impl PriorityGrouping { #[inline] - const fn preemption_priority_bits(&self, nvic_prio_bits: u8) -> u8 { + const fn preemption_priority_bits(&self) -> u8 { let bits = 7 - *self as u8; - if bits > nvic_prio_bits { - nvic_prio_bits + if bits > NVIC_PRIO_BITS { + NVIC_PRIO_BITS } else { bits } } #[inline] - const fn sub_priority_bits(&self, nvic_prio_bits: u8) -> u8 { - let bits = *self as u8 + nvic_prio_bits; + const fn sub_priority_bits(&self) -> u8 { + let bits = *self as u8 + NVIC_PRIO_BITS; if bits <= 7 { 0 @@ -168,14 +168,9 @@ impl PriorityGrouping { /// Encode `preemption_priority` and `sub_priority` to fit in `nvic_prio_bits`. #[inline] - pub const fn encode_priority( - &self, - nvic_prio_bits: u8, - preemption_priority: u8, - sub_priority: u8, - ) -> u8 { - let preemption_priority_bits = self.preemption_priority_bits(nvic_prio_bits); - let sub_priority_bits = self.sub_priority_bits(nvic_prio_bits); + pub const fn encode_priority(&self, preemption_priority: u8, sub_priority: u8) -> u8 { + let preemption_priority_bits = self.preemption_priority_bits(); + let sub_priority_bits = self.sub_priority_bits(); let premption_priority_mask = (1 << preemption_priority_bits) - 1; let sub_priority_mask = (1 << sub_priority_bits) - 1; @@ -187,17 +182,17 @@ impl PriorityGrouping { | (sub_priority & sub_priority_mask); // Priority is stored in the highest bits. - priority << (8 - nvic_prio_bits) + priority << (8 - NVIC_PRIO_BITS) } /// Decode priority stored in `nvic_prio_bits` into a tuple consisting of /// the preemption priority and sub-priority. #[inline] - pub const fn decode_priority(&self, nvic_prio_bits: u8, mut priority: u8) -> (u8, u8) { + pub const fn decode_priority(&self, mut priority: u8) -> (u8, u8) { // Priority is stored in the highest bits. - priority >>= 8 - nvic_prio_bits; + priority >>= 8 - NVIC_PRIO_BITS; - let sub_priority_bits = self.sub_priority_bits(nvic_prio_bits); + let sub_priority_bits = self.sub_priority_bits(); let preemption_priority = priority >> sub_priority_bits; let sub_priority = priority & ((1 << sub_priority_bits) - 1); @@ -951,7 +946,10 @@ impl SCB { /// Set the priority grouping. #[inline] - pub fn set_priority_grouping(&mut self, grouping: PriorityGrouping) { + pub fn set_priority_grouping( + &mut self, + grouping: PriorityGrouping, + ) { unsafe { self.aircr.write({ SCB_AIRCR_VECTKEY | // Unlock for writing. @@ -962,7 +960,9 @@ impl SCB { /// Get the priority grouping. #[inline] - pub fn get_priority_grouping(&self) -> PriorityGrouping { + pub fn get_priority_grouping( + &self, + ) -> PriorityGrouping { match self.aircr.read() & SCB_AIRCR_PRIGROUP_MASK >> SCB_AIRCR_PRIGROUP_POS { 0 => PriorityGrouping::Prigroup0, 1 => PriorityGrouping::Prigroup1, From 169cf04a5449070e46c3bd8327f06aa1ff9b32cc Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Fri, 6 May 2022 18:11:47 +0200 Subject: [PATCH 4/4] Update docs. --- src/peripheral/scb.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index a666465e..1362d4f0 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -166,7 +166,7 @@ impl PriorityGrouping { } } - /// Encode `preemption_priority` and `sub_priority` to fit in `nvic_prio_bits`. + /// Encode `preemption_priority` and `sub_priority` to fit in `NVIC_PRIO_BITS`. #[inline] pub const fn encode_priority(&self, preemption_priority: u8, sub_priority: u8) -> u8 { let preemption_priority_bits = self.preemption_priority_bits(); @@ -185,7 +185,7 @@ impl PriorityGrouping { priority << (8 - NVIC_PRIO_BITS) } - /// Decode priority stored in `nvic_prio_bits` into a tuple consisting of + /// Decode the priority stored in `NVIC_PRIO_BITS` into a tuple consisting of /// the preemption priority and sub-priority. #[inline] pub const fn decode_priority(&self, mut priority: u8) -> (u8, u8) {