11//! System Control Block
22
3+ use core:: convert:: TryFrom ;
34use core:: ptr;
45
56use volatile_register:: RW ;
@@ -254,106 +255,126 @@ impl SCB {
254255}
255256
256257impl SCB {
257- /// Returns the active exception number
258+ /// Returns the `ActiveVector` containing the active exception number.
258259 #[ inline]
259- pub fn vect_active ( ) -> VectActive {
260- let icsr =
261- unsafe { ptr:: read_volatile ( & ( * SCB :: PTR ) . icsr as * const _ as * const u32 ) } & 0x1FF ;
262-
263- match icsr as u16 {
264- 0 => VectActive :: ThreadMode ,
265- 2 => VectActive :: Exception ( Exception :: NonMaskableInt ) ,
266- 3 => VectActive :: Exception ( Exception :: HardFault ) ,
267- #[ cfg( not( armv6m) ) ]
268- 4 => VectActive :: Exception ( Exception :: MemoryManagement ) ,
269- #[ cfg( not( armv6m) ) ]
270- 5 => VectActive :: Exception ( Exception :: BusFault ) ,
271- #[ cfg( not( armv6m) ) ]
272- 6 => VectActive :: Exception ( Exception :: UsageFault ) ,
273- #[ cfg( any( armv8m, native) ) ]
274- 7 => VectActive :: Exception ( Exception :: SecureFault ) ,
275- 11 => VectActive :: Exception ( Exception :: SVCall ) ,
276- #[ cfg( not( armv6m) ) ]
277- 12 => VectActive :: Exception ( Exception :: DebugMonitor ) ,
278- 14 => VectActive :: Exception ( Exception :: PendSV ) ,
279- 15 => VectActive :: Exception ( Exception :: SysTick ) ,
280- irqn => VectActive :: Interrupt { irqn : irqn - 16 } ,
281- }
260+ pub fn vect_active ( ) -> ActiveVector {
261+ let icsr = unsafe { ptr:: read_volatile ( & ( * SCB :: PTR ) . icsr as * const _ as * const u32 ) } ;
262+ let isrn = ( icsr & 0x1FF ) as u16 ;
263+
264+ // NOTE(unsafe): `isrn` is in range [0, 511] and contains
265+ // a valid `Exception` if in range [2, 15].
266+ unsafe { ActiveVector :: new_unchecked ( isrn) }
282267 }
283268}
284269
285270/// Processor core exceptions (internal interrupts)
286271#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
287272#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
288273#[ cfg_attr( feature = "std" , derive( PartialOrd , Hash ) ) ]
274+ #[ repr( i8 ) ]
289275pub enum Exception {
290276 /// Non maskable interrupt
291- NonMaskableInt ,
277+ NonMaskableInt = - 14 ,
292278
293279 /// Hard fault interrupt
294- HardFault ,
280+ HardFault = - 13 ,
295281
296282 /// Memory management interrupt (not present on Cortex-M0 variants)
297283 #[ cfg( not( armv6m) ) ]
298- MemoryManagement ,
284+ MemoryManagement = - 12 ,
299285
300286 /// Bus fault interrupt (not present on Cortex-M0 variants)
301287 #[ cfg( not( armv6m) ) ]
302- BusFault ,
288+ BusFault = - 11 ,
303289
304290 /// Usage fault interrupt (not present on Cortex-M0 variants)
305291 #[ cfg( not( armv6m) ) ]
306- UsageFault ,
292+ UsageFault = - 10 ,
307293
308294 /// Secure fault interrupt (only on ARMv8-M)
309295 #[ cfg( any( armv8m, native) ) ]
310- SecureFault ,
296+ SecureFault = - 9 ,
311297
312298 /// SV call interrupt
313- SVCall ,
299+ SVCall = - 5 ,
314300
315301 /// Debug monitor interrupt (not present on Cortex-M0 variants)
316302 #[ cfg( not( armv6m) ) ]
317- DebugMonitor ,
303+ DebugMonitor = - 4 ,
318304
319305 /// Pend SV interrupt
320- PendSV ,
306+ PendSV = - 2 ,
321307
322308 /// System Tick interrupt
323- SysTick ,
309+ SysTick = - 1 ,
324310}
325311
326312impl Exception {
327- /// Returns the IRQ number of this `Exception`
313+ /// Create an `Exception` from an IRQ number.
328314 ///
329- /// The return value is always within the closed range `[-1 , -14]`
315+ /// `irqn` must be in the range `[-14 , -1]` and contain a valid `Exception`.
330316 #[ inline]
331- pub fn irqn ( self ) -> i8 {
332- match self {
333- Exception :: NonMaskableInt => - 14 ,
334- Exception :: HardFault => - 13 ,
317+ const unsafe fn new_unchecked ( irqn : i8 ) -> Self {
318+ match irqn {
319+ - 14 => Self :: NonMaskableInt ,
320+ - 13 => Self :: HardFault ,
335321 #[ cfg( not( armv6m) ) ]
336- Exception :: MemoryManagement => - 12 ,
322+ - 12 => Self :: MemoryManagement ,
337323 #[ cfg( not( armv6m) ) ]
338- Exception :: BusFault => - 11 ,
324+ - 11 => Self :: BusFault ,
339325 #[ cfg( not( armv6m) ) ]
340- Exception :: UsageFault => - 10 ,
326+ - 10 => Self :: UsageFault ,
341327 #[ cfg( any( armv8m, native) ) ]
342- Exception :: SecureFault => - 9 ,
343- Exception :: SVCall => - 5 ,
328+ - 9 => Self :: SecureFault ,
329+ - 5 => Self :: SVCall ,
344330 #[ cfg( not( armv6m) ) ]
345- Exception :: DebugMonitor => -4 ,
346- Exception :: PendSV => -2 ,
347- Exception :: SysTick => -1 ,
331+ -4 => Self :: DebugMonitor ,
332+ -2 => Self :: PendSV ,
333+ -1 => Self :: SysTick ,
334+ _ => core:: hint:: unreachable_unchecked ( ) ,
348335 }
349336 }
337+
338+ /// Returns the IRQ number of this `Exception`.
339+ ///
340+ /// The return value is always within the closed range `[-14, -1]`.
341+ #[ inline]
342+ pub const fn irqn ( self ) -> i8 {
343+ self as i8
344+ }
345+ }
346+
347+ impl TryFrom < i8 > for Exception {
348+ type Error = i8 ;
349+
350+ #[ inline]
351+ fn try_from ( irqn : i8 ) -> Result < Self , Self :: Error > {
352+ Ok ( match irqn {
353+ -14 => Self :: NonMaskableInt ,
354+ -13 => Self :: HardFault ,
355+ #[ cfg( not( armv6m) ) ]
356+ -12 => Self :: MemoryManagement ,
357+ #[ cfg( not( armv6m) ) ]
358+ -11 => Self :: BusFault ,
359+ #[ cfg( not( armv6m) ) ]
360+ -10 => Self :: UsageFault ,
361+ #[ cfg( any( armv8m, native) ) ]
362+ -9 => Self :: SecureFault ,
363+ -5 => Self :: SVCall ,
364+ #[ cfg( not( armv6m) ) ]
365+ -4 => Self :: DebugMonitor ,
366+ -2 => Self :: PendSV ,
367+ -1 => Self :: SysTick ,
368+ _ => return Err ( irqn) ,
369+ } )
370+ }
350371}
351372
352373/// Active exception number
353374#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
354375#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
355376#[ cfg_attr( feature = "std" , derive( PartialOrd , Hash ) ) ]
356- pub enum VectActive {
377+ pub enum ActiveVector {
357378 /// Thread mode
358379 ThreadMode ,
359380
@@ -362,34 +383,38 @@ pub enum VectActive {
362383
363384 /// Device specific exception (external interrupts)
364385 Interrupt {
365- /// Interrupt number. This number is always within half open range `[0, 512) ` (9 bit)
386+ /// Interrupt number. This number is always in range `[0, 495] ` (9- bit integer - 16 )
366387 irqn : u16 ,
367388 } ,
368389}
369390
370- impl VectActive {
371- /// Converts a vector number into `VectActive`
391+ impl ActiveVector {
392+ /// Create an `ActiveVector` from an ISR number.
393+ ///
394+ /// `isrn` must be in the range `[0, 511]` and contain a valid
395+ /// `Exception` variant if in range `[2, 15]`.
372396 #[ inline]
373- pub fn from ( vect_active : u16 ) -> Option < Self > {
374- Some ( match vect_active {
375- 0 => VectActive :: ThreadMode ,
376- 2 => VectActive :: Exception ( Exception :: NonMaskableInt ) ,
377- 3 => VectActive :: Exception ( Exception :: HardFault ) ,
378- #[ cfg( not( armv6m) ) ]
379- 4 => VectActive :: Exception ( Exception :: MemoryManagement ) ,
380- #[ cfg( not( armv6m) ) ]
381- 5 => VectActive :: Exception ( Exception :: BusFault ) ,
382- #[ cfg( not( armv6m) ) ]
383- 6 => VectActive :: Exception ( Exception :: UsageFault ) ,
384- #[ cfg( any( armv8m, native) ) ]
385- 7 => VectActive :: Exception ( Exception :: SecureFault ) ,
386- 11 => VectActive :: Exception ( Exception :: SVCall ) ,
387- #[ cfg( not( armv6m) ) ]
388- 12 => VectActive :: Exception ( Exception :: DebugMonitor ) ,
389- 14 => VectActive :: Exception ( Exception :: PendSV ) ,
390- 15 => VectActive :: Exception ( Exception :: SysTick ) ,
391- irqn if ( 16 ..512 ) . contains ( & irqn) => VectActive :: Interrupt { irqn : irqn - 16 } ,
392- _ => return None ,
397+ const unsafe fn new_unchecked ( isrn : u16 ) -> Self {
398+ match isrn {
399+ 0 => Self :: ThreadMode ,
400+ 2 ..=15 => Self :: Exception ( Exception :: new_unchecked ( isrn as i8 - 16 ) ) ,
401+ 16 ..=511 => Self :: Interrupt { irqn : isrn - 16 } ,
402+ _ => core:: hint:: unreachable_unchecked ( ) ,
403+ }
404+ }
405+ }
406+
407+ impl TryFrom < u16 > for ActiveVector {
408+ type Error = u16 ;
409+
410+ /// Try creating an `ActiveVector` from an ISR number.
411+ #[ inline]
412+ fn try_from ( isrn : u16 ) -> Result < Self , Self :: Error > {
413+ Ok ( match isrn {
414+ 0 => Self :: ThreadMode ,
415+ 2 ..=15 => Self :: Exception ( Exception :: try_from ( isrn as i8 - 16 ) . or ( Err ( isrn) ) ?) ,
416+ 16 ..=511 => Self :: Interrupt { irqn : isrn - 16 } ,
417+ _ => return Err ( isrn) ,
393418 } )
394419 }
395420}
0 commit comments