1use crate::pac::Interrupt;
2use cortex_m::peripheral::NVIC;
3use cortex_m::peripheral::SCB;
4
5pub trait ScbInit {
6 fn init(self) -> Scb;
7}
8pub struct Scb {
9 pub(crate) scb: SCB,
10}
11impl ScbInit for SCB {
12 fn init(self) -> Scb {
13 Scb { scb: self }
14 }
15}
16
17pub trait NvicInit {
18 fn init(self) -> Nvic;
19}
20pub struct Nvic {
21 pub(crate) nvic: NVIC,
22}
23impl NvicInit for NVIC {
24 fn init(self) -> Nvic {
25 Nvic { nvic: self }
26 }
27}
28
29const SCB_AIRCR_VECTKEY_MASK: u32 = 0xFFFF << 16;
30const SCB_AIRCR_VECTKEY: u32 = 0x05FA << 16;
31const SCB_AIRCR_PRIGROUP_MASK: u32 = 0x7 << 8;
32impl Scb {
35 pub fn set_priority_grouping(&mut self, grouping: PriorityGrouping) {
37 let mask = !(SCB_AIRCR_VECTKEY_MASK | SCB_AIRCR_PRIGROUP_MASK);
38 let grouping: u32 = grouping.into();
39 cortex_m::asm::dsb();
40 unsafe {
41 self.scb
42 .aircr
43 .modify(|r| (r & mask) | SCB_AIRCR_VECTKEY | grouping)
44 };
45 cortex_m::asm::dsb();
46 }
47
48 pub fn get_priority_grouping(&self) -> PriorityGrouping {
49 self.scb.aircr.read().into()
50 }
51}
52
53impl Nvic {
54 pub fn set_priority(&mut self, it: Interrupt, priority: u8, disable: bool) {
62 if disable {
63 NVIC::mask(it);
64 }
65
66 unsafe {
67 self.nvic.set_priority(it, priority << 4);
69 }
70 }
71
72 pub fn enable(&mut self, it: Interrupt, en: bool) {
74 if en {
75 unsafe {
76 NVIC::unmask(it);
77 }
78 } else {
79 NVIC::mask(it);
80 }
81 }
82}
83
84pub enum PriorityGrouping {
85 Group0,
88 Group1,
91 Group2,
94 Group3,
97 Group4,
100 Unknown(u8),
101}
102
103impl From<PriorityGrouping> for u32 {
104 fn from(value: PriorityGrouping) -> Self {
105 match value {
106 PriorityGrouping::Group0 => 7 << 8,
107 PriorityGrouping::Group1 => 6 << 8,
108 PriorityGrouping::Group2 => 5 << 8,
109 PriorityGrouping::Group3 => 4 << 8,
110 PriorityGrouping::Group4 => 3 << 8,
111 PriorityGrouping::Unknown(v) => ((v as u32) << 8) & SCB_AIRCR_PRIGROUP_MASK,
112 }
113 }
114}
115
116impl From<u32> for PriorityGrouping {
117 fn from(value: u32) -> Self {
118 match (value & SCB_AIRCR_PRIGROUP_MASK) >> 8 {
119 7 => Self::Group0,
120 6 => Self::Group1,
121 5 => Self::Group2,
122 4 => Self::Group3,
123 3 => Self::Group4,
124 v => PriorityGrouping::Unknown(v as u8),
125 }
126 }
127}