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 ;
@@ -167,106 +168,126 @@ impl SCB {
167
168
}
168
169
169
170
impl SCB {
170
- /// Returns the active exception number
171
+ /// Returns the `Vector` containing the active exception number.
171
172
#[ 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) }
195
180
}
196
181
}
197
182
198
183
/// Processor core exceptions (internal interrupts)
199
184
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
200
185
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
201
186
#[ cfg_attr( feature = "std" , derive( PartialOrd , Hash ) ) ]
187
+ #[ repr( i8 ) ]
202
188
pub enum Exception {
203
189
/// Non maskable interrupt
204
- NonMaskableInt ,
190
+ NonMaskableInt = - 14 ,
205
191
206
192
/// Hard fault interrupt
207
- HardFault ,
193
+ HardFault = - 13 ,
208
194
209
195
/// Memory management interrupt (not present on Cortex-M0 variants)
210
196
#[ cfg( not( armv6m) ) ]
211
- MemoryManagement ,
197
+ MemoryManagement = - 12 ,
212
198
213
199
/// Bus fault interrupt (not present on Cortex-M0 variants)
214
200
#[ cfg( not( armv6m) ) ]
215
- BusFault ,
201
+ BusFault = - 11 ,
216
202
217
203
/// Usage fault interrupt (not present on Cortex-M0 variants)
218
204
#[ cfg( not( armv6m) ) ]
219
- UsageFault ,
205
+ UsageFault = - 10 ,
220
206
221
207
/// Secure fault interrupt (only on ARMv8-M)
222
208
#[ cfg( any( armv8m, native) ) ]
223
- SecureFault ,
209
+ SecureFault = - 9 ,
224
210
225
211
/// SV call interrupt
226
- SVCall ,
212
+ SVCall = - 5 ,
227
213
228
214
/// Debug monitor interrupt (not present on Cortex-M0 variants)
229
215
#[ cfg( not( armv6m) ) ]
230
- DebugMonitor ,
216
+ DebugMonitor = - 4 ,
231
217
232
218
/// Pend SV interrupt
233
- PendSV ,
219
+ PendSV = - 2 ,
234
220
235
221
/// System Tick interrupt
236
- SysTick ,
222
+ SysTick = - 1 ,
237
223
}
238
224
239
225
impl Exception {
240
- /// Returns the IRQ number of this `Exception`
226
+ /// Create an `Exception` from an IRQ number.
241
227
///
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`.
243
229
#[ 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 ,
248
234
#[ cfg( not( armv6m) ) ]
249
- Exception :: MemoryManagement => - 12 ,
235
+ - 12 => Self :: MemoryManagement ,
250
236
#[ cfg( not( armv6m) ) ]
251
- Exception :: BusFault => - 11 ,
237
+ - 11 => Self :: BusFault ,
252
238
#[ cfg( not( armv6m) ) ]
253
- Exception :: UsageFault => - 10 ,
239
+ - 10 => Self :: UsageFault ,
254
240
#[ cfg( any( armv8m, native) ) ]
255
- Exception :: SecureFault => - 9 ,
256
- Exception :: SVCall => - 5 ,
241
+ - 9 => Self :: SecureFault ,
242
+ - 5 => Self :: SVCall ,
257
243
#[ 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 ( ) ,
261
248
}
262
249
}
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
+ }
263
284
}
264
285
265
- /// Active exception number
286
+ /// Exception/Interrupt Vector
266
287
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
267
288
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
268
289
#[ cfg_attr( feature = "std" , derive( PartialOrd , Hash ) ) ]
269
- pub enum VectActive {
290
+ pub enum Vector {
270
291
/// Thread mode
271
292
ThreadMode ,
272
293
@@ -275,34 +296,38 @@ pub enum VectActive {
275
296
276
297
/// Device specific exception (external interrupts)
277
298
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 )
279
300
irqn : u16 ,
280
301
} ,
281
302
}
282
303
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]`.
285
309
#[ 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) ,
306
331
} )
307
332
}
308
333
}
0 commit comments