1
1
//! System Control Block
2
2
3
+ use core:: convert:: TryFrom ;
3
4
use core:: ptr;
4
5
5
6
use volatile_register:: RW ;
@@ -254,106 +255,126 @@ impl SCB {
254
255
}
255
256
256
257
impl SCB {
257
- /// Returns the active exception number
258
+ /// Returns the `ActiveVector` containing the active exception number.
258
259
#[ 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) }
282
267
}
283
268
}
284
269
285
270
/// Processor core exceptions (internal interrupts)
286
271
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
287
272
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
288
273
#[ cfg_attr( feature = "std" , derive( PartialOrd , Hash ) ) ]
274
+ #[ repr( i8 ) ]
289
275
pub enum Exception {
290
276
/// Non maskable interrupt
291
- NonMaskableInt ,
277
+ NonMaskableInt = - 14 ,
292
278
293
279
/// Hard fault interrupt
294
- HardFault ,
280
+ HardFault = - 13 ,
295
281
296
282
/// Memory management interrupt (not present on Cortex-M0 variants)
297
283
#[ cfg( not( armv6m) ) ]
298
- MemoryManagement ,
284
+ MemoryManagement = - 12 ,
299
285
300
286
/// Bus fault interrupt (not present on Cortex-M0 variants)
301
287
#[ cfg( not( armv6m) ) ]
302
- BusFault ,
288
+ BusFault = - 11 ,
303
289
304
290
/// Usage fault interrupt (not present on Cortex-M0 variants)
305
291
#[ cfg( not( armv6m) ) ]
306
- UsageFault ,
292
+ UsageFault = - 10 ,
307
293
308
294
/// Secure fault interrupt (only on ARMv8-M)
309
295
#[ cfg( any( armv8m, native) ) ]
310
- SecureFault ,
296
+ SecureFault = - 9 ,
311
297
312
298
/// SV call interrupt
313
- SVCall ,
299
+ SVCall = - 5 ,
314
300
315
301
/// Debug monitor interrupt (not present on Cortex-M0 variants)
316
302
#[ cfg( not( armv6m) ) ]
317
- DebugMonitor ,
303
+ DebugMonitor = - 4 ,
318
304
319
305
/// Pend SV interrupt
320
- PendSV ,
306
+ PendSV = - 2 ,
321
307
322
308
/// System Tick interrupt
323
- SysTick ,
309
+ SysTick = - 1 ,
324
310
}
325
311
326
312
impl Exception {
327
- /// Returns the IRQ number of this `Exception`
313
+ /// Create an `Exception` from an IRQ number.
328
314
///
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`.
330
316
#[ 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 ,
335
321
#[ cfg( not( armv6m) ) ]
336
- Exception :: MemoryManagement => - 12 ,
322
+ - 12 => Self :: MemoryManagement ,
337
323
#[ cfg( not( armv6m) ) ]
338
- Exception :: BusFault => - 11 ,
324
+ - 11 => Self :: BusFault ,
339
325
#[ cfg( not( armv6m) ) ]
340
- Exception :: UsageFault => - 10 ,
326
+ - 10 => Self :: UsageFault ,
341
327
#[ cfg( any( armv8m, native) ) ]
342
- Exception :: SecureFault => - 9 ,
343
- Exception :: SVCall => - 5 ,
328
+ - 9 => Self :: SecureFault ,
329
+ - 5 => Self :: SVCall ,
344
330
#[ 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 ( ) ,
348
335
}
349
336
}
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
+ }
350
371
}
351
372
352
373
/// Active exception number
353
374
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
354
375
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
355
376
#[ cfg_attr( feature = "std" , derive( PartialOrd , Hash ) ) ]
356
- pub enum VectActive {
377
+ pub enum ActiveVector {
357
378
/// Thread mode
358
379
ThreadMode ,
359
380
@@ -362,34 +383,38 @@ pub enum VectActive {
362
383
363
384
/// Device specific exception (external interrupts)
364
385
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 )
366
387
irqn : u16 ,
367
388
} ,
368
389
}
369
390
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]`.
372
396
#[ 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) ,
393
418
} )
394
419
}
395
420
}
0 commit comments