Skip to content

Commit 0b51fee

Browse files
committed
Refactor VectActive to ActiveVector and pass it to DefaultHandler.
1 parent 36188bf commit 0b51fee

File tree

3 files changed

+115
-86
lines changed

3 files changed

+115
-86
lines changed

Diff for: cortex-m-rt/macros/src/lib.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,13 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
187187
&& f.vis == Visibility::Inherited
188188
&& f.sig.abi.is_none()
189189
&& f.sig.inputs.len() == 1
190+
&& match &f.sig.inputs[0] {
191+
FnArg::Typed(arg) => match arg.ty.as_ref() {
192+
Type::Path(t) => true,
193+
_ => false,
194+
},
195+
_ => false,
196+
}
190197
&& f.sig.generics.params.is_empty()
191198
&& f.sig.generics.where_clause.is_none()
192199
&& f.sig.variadic.is_none()
@@ -202,7 +209,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
202209
if !valid_signature {
203210
return parse::Error::new(
204211
fspan,
205-
"`DefaultHandler` must have signature `unsafe fn(i16) [-> !]`",
212+
"`DefaultHandler` must have signature `unsafe fn(ActiveVector) [-> !]`",
206213
)
207214
.to_compile_error()
208215
.into();
@@ -222,11 +229,8 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
222229
pub unsafe extern "C" fn #tramp_ident() {
223230
extern crate core;
224231

225-
const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32;
226-
227-
let irqn = unsafe { (core::ptr::read_volatile(SCB_ICSR) & 0x1FF) as i16 - 16 };
228-
229-
#ident(irqn)
232+
let vect_active = ::cortex_m::peripheral::SCB::vect_active();
233+
#ident(vect_active)
230234
}
231235

232236
#f

Diff for: src/peripheral/scb.rs

+97-72
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! System Control Block
22
3+
use core::convert::TryFrom;
34
use core::ptr;
45

56
use volatile_register::RW;
@@ -254,106 +255,126 @@ impl SCB {
254255
}
255256

256257
impl 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)]
289275
pub 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

326312
impl 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
}

Diff for: xtask/src/lib.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,16 @@ pub fn install_targets(targets: &mut dyn Iterator<Item = &str>, toolchain: Optio
1616
assert!(status.success(), "rustup command failed: {:?}", rustup);
1717
}
1818

19-
// Check that serde and PartialOrd works with VectActive
19+
// Check that serde and PartialOrd works with ActiveVector
2020
pub fn check_host_side() {
21-
use cortex_m::peripheral::{itm::LocalTimestampOptions, scb::VectActive};
21+
use cortex_m::peripheral::{itm::LocalTimestampOptions, scb::ActiveVector};
2222

2323
// check serde
2424
{
25-
let v = VectActive::from(22).unwrap();
26-
let json = serde_json::to_string(&v).expect("Failed to serialize VectActive");
27-
let deser_v: VectActive =
28-
serde_json::from_str(&json).expect("Failed to deserialize VectActive");
25+
let v = ActiveVector::try_from(22).unwrap();
26+
let json = serde_json::to_string(&v).expect("Failed to serialize ActiveVector");
27+
let deser_v: ActiveVector =
28+
serde_json::from_str(&json).expect("Failed to deserialize ActiveVector");
2929
assert_eq!(deser_v, v);
3030

3131
let lts = LocalTimestampOptions::EnabledDiv4;
@@ -37,8 +37,8 @@ pub fn check_host_side() {
3737

3838
// check PartialOrd
3939
{
40-
let a = VectActive::from(19).unwrap();
41-
let b = VectActive::from(20).unwrap();
40+
let a = ActiveVector::try_from(19).unwrap();
41+
let b = ActiveVector::try_from(20).unwrap();
4242
assert!(a < b);
4343
}
4444

0 commit comments

Comments
 (0)