Skip to content

Commit 924293d

Browse files
committed
Refactor VectActive to Vector and pass it to DefaultHandler.
1 parent d5d50a0 commit 924293d

File tree

3 files changed

+116
-87
lines changed

3 files changed

+116
-87
lines changed

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(Vector) [-> !]`",
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

src/peripheral/scb.rs

+98-73
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;
@@ -167,106 +168,126 @@ impl SCB {
167168
}
168169

169170
impl 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)]
202188
pub 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

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

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 `Vector`.
2020
pub fn check_host_side() {
21-
use cortex_m::peripheral::{itm::LocalTimestampOptions, scb::VectActive};
21+
use cortex_m::peripheral::{itm::LocalTimestampOptions, scb::Vector};
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 = Vector::try_from(22).unwrap();
26+
let json = serde_json::to_string(&v).expect("Failed to serialize Vector");
27+
let deser_v: Vector =
28+
serde_json::from_str(&json).expect("Failed to deserialize Vector");
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 = Vector::try_from(19).unwrap();
41+
let b = Vector::try_from(20).unwrap();
4242
assert!(a < b);
4343
}
4444

0 commit comments

Comments
 (0)