stm32_rust_template/arch/cortex_m4/
nvic.rs

1// NVIC (Nested Vectored Interrupt Controller) register definitions
2// Based on CMSIS Cortex-M4 core_cm4.h
3
4use super::super::super::mcu::stm32f407::PeripheralAccess;
5
6// NVIC Base Address
7pub const NVIC_BASE: u32 = 0xE000E100;
8
9// NVIC Register Block
10#[repr(C)]
11pub struct Nvic {
12    pub iser: [u32; 8], // Interrupt Set Enable Register
13    _reserved0: [u32; 24],
14    pub icer: [u32; 8], // Interrupt Clear Enable Register
15    _reserved1: [u32; 24],
16    pub ispr: [u32; 8], // Interrupt Set Pending Register
17    _reserved2: [u32; 24],
18    pub icpr: [u32; 8], // Interrupt Clear Pending Register
19    _reserved3: [u32; 24],
20    pub iabr: [u32; 8], // Interrupt Active bit Register
21    _reserved4: [u32; 56],
22    pub ip: [u8; 240], // Interrupt Priority Register (8Bit wide)
23    _reserved5: [u32; 644],
24    pub stir: u32, // Software Trigger Interrupt Register
25}
26
27// NVIC Peripheral Instance
28pub struct NVIC;
29
30impl PeripheralAccess for NVIC {
31    const BASE_ADDRESS: u32 = NVIC_BASE;
32    type RegisterBlock = Nvic;
33}
34
35// Software Triggered Interrupt Register Definitions
36pub const NVIC_STIR_INTID_POS: u32 = 0;
37pub const NVIC_STIR_INTID_MSK: u32 = 0x1FF;
38
39// Helper functions for NVIC
40impl Nvic {
41    /// Enable Interrupt
42    pub fn enable_irq(&mut self, irqn: u32) {
43        if irqn < 240 {
44            let index = (irqn >> 5) as usize;
45            let bit = irqn & 0x1F;
46            self.iser[index] |= 1 << bit;
47        }
48    }
49
50    /// Disable Interrupt
51    pub fn disable_irq(&mut self, irqn: u32) {
52        if irqn < 240 {
53            let index = (irqn >> 5) as usize;
54            let bit = irqn & 0x1F;
55            self.icer[index] |= 1 << bit;
56        }
57    }
58
59    /// Get Interrupt Enable status
60    pub fn get_enable_irq(&self, irqn: u32) -> bool {
61        if irqn < 240 {
62            let index = (irqn >> 5) as usize;
63            let bit = irqn & 0x1F;
64            (self.iser[index] & (1 << bit)) != 0
65        } else {
66            false
67        }
68    }
69
70    /// Set Pending Interrupt
71    pub fn set_pending_irq(&mut self, irqn: u32) {
72        if irqn < 240 {
73            let index = (irqn >> 5) as usize;
74            let bit = irqn & 0x1F;
75            self.ispr[index] |= 1 << bit;
76        }
77    }
78
79    /// Clear Pending Interrupt
80    pub fn clear_pending_irq(&mut self, irqn: u32) {
81        if irqn < 240 {
82            let index = (irqn >> 5) as usize;
83            let bit = irqn & 0x1F;
84            self.icpr[index] |= 1 << bit;
85        }
86    }
87
88    /// Get Pending Interrupt
89    pub fn get_pending_irq(&self, irqn: u32) -> bool {
90        if irqn < 240 {
91            let index = (irqn >> 5) as usize;
92            let bit = irqn & 0x1F;
93            (self.ispr[index] & (1 << bit)) != 0
94        } else {
95            false
96        }
97    }
98
99    /// Get Active Interrupt
100    pub fn get_active(&self, irqn: u32) -> bool {
101        if irqn < 240 {
102            let index = (irqn >> 5) as usize;
103            let bit = irqn & 0x1F;
104            (self.iabr[index] & (1 << bit)) != 0
105        } else {
106            false
107        }
108    }
109
110    /// Set Interrupt Priority
111    pub fn set_priority(&mut self, irqn: u32, priority: u8) {
112        if irqn < 240 {
113            self.ip[irqn as usize] = priority;
114        }
115    }
116
117    /// Get Interrupt Priority
118    pub fn get_priority(&self, irqn: u32) -> u8 {
119        if irqn < 240 {
120            self.ip[irqn as usize]
121        } else {
122            0
123        }
124    }
125
126    /// Trigger Software Interrupt
127    pub fn trigger_interrupt(&mut self, irqn: u32) {
128        if irqn < 240 {
129            self.stir = irqn & 0x1FF;
130        }
131    }
132}
133
134// Global functions similar to CMSIS
135pub fn nvic_enable_irq(irqn: u32) {
136    unsafe {
137        let nvic = &mut *(NVIC_BASE as *mut Nvic);
138        nvic.enable_irq(irqn);
139    }
140}
141
142pub fn nvic_disable_irq(irqn: u32) {
143    unsafe {
144        let nvic = &mut *(NVIC_BASE as *mut Nvic);
145        nvic.disable_irq(irqn);
146    }
147}
148
149pub fn nvic_set_pending_irq(irqn: u32) {
150    unsafe {
151        let nvic = &mut *(NVIC_BASE as *mut Nvic);
152        nvic.set_pending_irq(irqn);
153    }
154}
155
156pub fn nvic_clear_pending_irq(irqn: u32) {
157    unsafe {
158        let nvic = &mut *(NVIC_BASE as *mut Nvic);
159        nvic.clear_pending_irq(irqn);
160    }
161}
162
163pub fn nvic_get_pending_irq(irqn: u32) -> bool {
164    unsafe {
165        let nvic = &*(NVIC_BASE as *const Nvic);
166        nvic.get_pending_irq(irqn)
167    }
168}
169
170pub fn nvic_get_active(irqn: u32) -> bool {
171    unsafe {
172        let nvic = &*(NVIC_BASE as *const Nvic);
173        nvic.get_active(irqn)
174    }
175}
176
177pub fn nvic_set_priority(irqn: u32, priority: u32) {
178    unsafe {
179        let nvic = &mut *(NVIC_BASE as *mut Nvic);
180        nvic.set_priority(irqn, (priority as u8) << 4); // Assuming 4 bits for priority
181    }
182}
183
184pub fn nvic_get_priority(irqn: u32) -> u32 {
185    unsafe {
186        let nvic = &*(NVIC_BASE as *const Nvic);
187        (nvic.get_priority(irqn) >> 4) as u32
188    }
189}