11//! System Control Block
22
3+ use core:: convert:: TryFrom ;
34use core:: ptr;
45
56use volatile_register:: RW ;
@@ -167,106 +168,126 @@ impl SCB {
167168}
168169
169170impl SCB {
170- /// Returns the active exception number
171+ /// Returns the `Vector` containing the active exception number.
171172 #[ inline]
172- pub fn vect_active ( ) -> VectActive {
173- let icsr =
174- unsafe { ptr:: read_volatile ( & ( * SCB :: PTR ) . icsr as * const _ as * const u32 ) } & 0x1FF ;
175-
176- match icsr as u16 {
177- 0 => VectActive :: ThreadMode ,
178- 2 => VectActive :: Exception ( Exception :: NonMaskableInt ) ,
179- 3 => VectActive :: Exception ( Exception :: HardFault ) ,
180- #[ cfg( not( armv6m) ) ]
181- 4 => VectActive :: Exception ( Exception :: MemoryManagement ) ,
182- #[ cfg( not( armv6m) ) ]
183- 5 => VectActive :: Exception ( Exception :: BusFault ) ,
184- #[ cfg( not( armv6m) ) ]
185- 6 => VectActive :: Exception ( Exception :: UsageFault ) ,
186- #[ cfg( any( armv8m, native) ) ]
187- 7 => VectActive :: Exception ( Exception :: SecureFault ) ,
188- 11 => VectActive :: Exception ( Exception :: SVCall ) ,
189- #[ cfg( not( armv6m) ) ]
190- 12 => VectActive :: Exception ( Exception :: DebugMonitor ) ,
191- 14 => VectActive :: Exception ( Exception :: PendSV ) ,
192- 15 => VectActive :: Exception ( Exception :: SysTick ) ,
193- irqn => VectActive :: Interrupt { irqn : irqn - 16 } ,
194- }
173+ pub fn vect_active ( ) -> Vector {
174+ let icsr = unsafe { ptr:: read_volatile ( & ( * SCB :: PTR ) . icsr as * const _ as * const u32 ) } ;
175+ let isrn = ( icsr & 0x1FF ) as u16 ;
176+
177+ // NOTE(unsafe): `isrn` is in range [0, 511] and contains
178+ // a valid `Exception` if in range [2, 15].
179+ unsafe { Vector :: new_unchecked ( isrn) }
195180 }
196181}
197182
198183/// Processor core exceptions (internal interrupts)
199184#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
200185#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
201186#[ cfg_attr( feature = "std" , derive( PartialOrd , Hash ) ) ]
187+ #[ repr( i8 ) ]
202188pub enum Exception {
203189 /// Non maskable interrupt
204- NonMaskableInt ,
190+ NonMaskableInt = - 14 ,
205191
206192 /// Hard fault interrupt
207- HardFault ,
193+ HardFault = - 13 ,
208194
209195 /// Memory management interrupt (not present on Cortex-M0 variants)
210196 #[ cfg( not( armv6m) ) ]
211- MemoryManagement ,
197+ MemoryManagement = - 12 ,
212198
213199 /// Bus fault interrupt (not present on Cortex-M0 variants)
214200 #[ cfg( not( armv6m) ) ]
215- BusFault ,
201+ BusFault = - 11 ,
216202
217203 /// Usage fault interrupt (not present on Cortex-M0 variants)
218204 #[ cfg( not( armv6m) ) ]
219- UsageFault ,
205+ UsageFault = - 10 ,
220206
221207 /// Secure fault interrupt (only on ARMv8-M)
222208 #[ cfg( any( armv8m, native) ) ]
223- SecureFault ,
209+ SecureFault = - 9 ,
224210
225211 /// SV call interrupt
226- SVCall ,
212+ SVCall = - 5 ,
227213
228214 /// Debug monitor interrupt (not present on Cortex-M0 variants)
229215 #[ cfg( not( armv6m) ) ]
230- DebugMonitor ,
216+ DebugMonitor = - 4 ,
231217
232218 /// Pend SV interrupt
233- PendSV ,
219+ PendSV = - 2 ,
234220
235221 /// System Tick interrupt
236- SysTick ,
222+ SysTick = - 1 ,
237223}
238224
239225impl Exception {
240- /// Returns the IRQ number of this `Exception`
226+ /// Create an `Exception` from an IRQ number.
241227 ///
242- /// The return value is always within the closed range `[-1 , -14]`
228+ /// `irqn` must be in the range `[-14 , -1]` and contain a valid `Exception`.
243229 #[ inline]
244- pub fn irqn ( self ) -> i8 {
245- match self {
246- Exception :: NonMaskableInt => - 14 ,
247- Exception :: HardFault => - 13 ,
230+ const unsafe fn new_unchecked ( irqn : i8 ) -> Self {
231+ match irqn {
232+ - 14 => Self :: NonMaskableInt ,
233+ - 13 => Self :: HardFault ,
248234 #[ cfg( not( armv6m) ) ]
249- Exception :: MemoryManagement => - 12 ,
235+ - 12 => Self :: MemoryManagement ,
250236 #[ cfg( not( armv6m) ) ]
251- Exception :: BusFault => - 11 ,
237+ - 11 => Self :: BusFault ,
252238 #[ cfg( not( armv6m) ) ]
253- Exception :: UsageFault => - 10 ,
239+ - 10 => Self :: UsageFault ,
254240 #[ cfg( any( armv8m, native) ) ]
255- Exception :: SecureFault => - 9 ,
256- Exception :: SVCall => - 5 ,
241+ - 9 => Self :: SecureFault ,
242+ - 5 => Self :: SVCall ,
257243 #[ cfg( not( armv6m) ) ]
258- Exception :: DebugMonitor => -4 ,
259- Exception :: PendSV => -2 ,
260- Exception :: SysTick => -1 ,
244+ -4 => Self :: DebugMonitor ,
245+ -2 => Self :: PendSV ,
246+ -1 => Self :: SysTick ,
247+ _ => core:: hint:: unreachable_unchecked ( ) ,
261248 }
262249 }
250+
251+ /// Returns the IRQ number of this `Exception`.
252+ ///
253+ /// The return value is always within the closed range `[-14, -1]`.
254+ #[ inline]
255+ pub const fn irqn ( self ) -> i8 {
256+ self as i8
257+ }
258+ }
259+
260+ impl TryFrom < i8 > for Exception {
261+ type Error = i8 ;
262+
263+ #[ inline]
264+ fn try_from ( irqn : i8 ) -> Result < Self , Self :: Error > {
265+ Ok ( match irqn {
266+ -14 => Self :: NonMaskableInt ,
267+ -13 => Self :: HardFault ,
268+ #[ cfg( not( armv6m) ) ]
269+ -12 => Self :: MemoryManagement ,
270+ #[ cfg( not( armv6m) ) ]
271+ -11 => Self :: BusFault ,
272+ #[ cfg( not( armv6m) ) ]
273+ -10 => Self :: UsageFault ,
274+ #[ cfg( any( armv8m, native) ) ]
275+ -9 => Self :: SecureFault ,
276+ -5 => Self :: SVCall ,
277+ #[ cfg( not( armv6m) ) ]
278+ -4 => Self :: DebugMonitor ,
279+ -2 => Self :: PendSV ,
280+ -1 => Self :: SysTick ,
281+ _ => return Err ( irqn) ,
282+ } )
283+ }
263284}
264285
265- /// Active exception number
286+ /// Exception/Interrupt Vector
266287#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
267288#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
268289#[ cfg_attr( feature = "std" , derive( PartialOrd , Hash ) ) ]
269- pub enum VectActive {
290+ pub enum Vector {
270291 /// Thread mode
271292 ThreadMode ,
272293
@@ -275,34 +296,38 @@ pub enum VectActive {
275296
276297 /// Device specific exception (external interrupts)
277298 Interrupt {
278- /// Interrupt number. This number is always within half open range `[0, 512) ` (9 bit)
299+ /// Interrupt number. This number is always in range `[0, 495] ` (9- bit integer - 16 )
279300 irqn : u16 ,
280301 } ,
281302}
282303
283- impl VectActive {
284- /// Converts a vector number into `VectActive`
304+ impl Vector {
305+ /// Create an `Vector` from an ISR number.
306+ ///
307+ /// `isrn` must be in the range `[0, 511]` and contain a valid
308+ /// `Exception` variant if in range `[2, 15]`.
285309 #[ inline]
286- pub fn from ( vect_active : u16 ) -> Option < Self > {
287- Some ( match vect_active {
288- 0 => VectActive :: ThreadMode ,
289- 2 => VectActive :: Exception ( Exception :: NonMaskableInt ) ,
290- 3 => VectActive :: Exception ( Exception :: HardFault ) ,
291- #[ cfg( not( armv6m) ) ]
292- 4 => VectActive :: Exception ( Exception :: MemoryManagement ) ,
293- #[ cfg( not( armv6m) ) ]
294- 5 => VectActive :: Exception ( Exception :: BusFault ) ,
295- #[ cfg( not( armv6m) ) ]
296- 6 => VectActive :: Exception ( Exception :: UsageFault ) ,
297- #[ cfg( any( armv8m, native) ) ]
298- 7 => VectActive :: Exception ( Exception :: SecureFault ) ,
299- 11 => VectActive :: Exception ( Exception :: SVCall ) ,
300- #[ cfg( not( armv6m) ) ]
301- 12 => VectActive :: Exception ( Exception :: DebugMonitor ) ,
302- 14 => VectActive :: Exception ( Exception :: PendSV ) ,
303- 15 => VectActive :: Exception ( Exception :: SysTick ) ,
304- irqn if ( 16 ..512 ) . contains ( & irqn) => VectActive :: Interrupt { irqn : irqn - 16 } ,
305- _ => return None ,
310+ const unsafe fn new_unchecked ( isrn : u16 ) -> Self {
311+ match isrn {
312+ 0 => Self :: ThreadMode ,
313+ 2 ..=15 => Self :: Exception ( Exception :: new_unchecked ( isrn as i8 - 16 ) ) ,
314+ 16 ..=511 => Self :: Interrupt { irqn : isrn - 16 } ,
315+ _ => core:: hint:: unreachable_unchecked ( ) ,
316+ }
317+ }
318+ }
319+
320+ impl TryFrom < u16 > for Vector {
321+ type Error = u16 ;
322+
323+ /// Try creating an `Vector` from an ISR number.
324+ #[ inline]
325+ fn try_from ( isrn : u16 ) -> Result < Self , Self :: Error > {
326+ Ok ( match isrn {
327+ 0 => Self :: ThreadMode ,
328+ 2 ..=15 => Self :: Exception ( Exception :: try_from ( isrn as i8 - 16 ) . or ( Err ( isrn) ) ?) ,
329+ 16 ..=511 => Self :: Interrupt { irqn : isrn - 16 } ,
330+ _ => return Err ( isrn) ,
306331 } )
307332 }
308333}
0 commit comments