Skip to content

Commit 73e32c9

Browse files
committed
Feature-gate trap-related code in riscv
1 parent 18cc082 commit 73e32c9

File tree

8 files changed

+83
-53
lines changed

8 files changed

+83
-53
lines changed

riscv-rt/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- Adapted to new `riscv` version.
13+
1014
## [v0.16.0] - 2025-09-08
1115

1216
### Added

riscv-rt/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ targets = [
2424
riscv-target-parser = { path = "../riscv-target-parser", version = "0.1.2" }
2525

2626
[dependencies]
27-
riscv = { path = "../riscv", version = "0.15.0" }
27+
riscv = { path = "../riscv", version = "0.15.0", features = ["rt"] }
2828
riscv-pac = { path = "../riscv-pac", version = "0.2.0" }
2929
riscv-rt-macros = { path = "macros", version = "0.6.0" }
3030

@@ -38,7 +38,7 @@ pre-init = []
3838
post-init = []
3939
s-mode = ["riscv-rt-macros/s-mode"]
4040
single-hart = []
41-
v-trap = ["riscv-rt-macros/v-trap"]
41+
v-trap = ["riscv-rt-macros/v-trap", "riscv/rt-v-trap"]
4242
u-boot = ["riscv-rt-macros/u-boot", "single-hart"]
4343
no-interrupts = []
4444
no-exceptions = []

riscv-rt/src/interrupts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
//! you may need to opt out this module. To do so, activate the `no-interrupts` feature of the
1818
//! `riscv-rt` crate.
1919
20-
// In vectored mode, we also must provide a vector table
2120
#[riscv::pac_enum(unsafe CoreInterruptNumber)]
2221
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
2322
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23+
#[allow(dead_code)] // otherwise compiler complains about Interrupt not being used
2424
enum Interrupt {
2525
SupervisorSoft = 1,
2626
MachineSoft = 3,

riscv/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111

1212
- Add `miselect` CSR
1313
- Improved assembly macro handling in asm.rs
14+
- New `rt` and `rt-v-trap` features to opt-in `riscv-rt`-related code in `riscv::pac_enum` macro.
15+
16+
# Changed
17+
18+
- Now, `riscv::pac_enum` macro only includes trap-related code if `rt` or `rt-v-trap` features are enabled.
1419

1520
## [v0.15.0] - 2025-09-08
1621

riscv/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ targets = [
2323
default = ["riscv-macros"]
2424
s-mode = []
2525
critical-section-single-hart = ["critical-section/restore-state-bool"]
26+
rt = ["riscv-macros/rt"]
27+
rt-v-trap = ["rt", "riscv-macros/rt-v-trap"]
2628

2729
[dependencies]
2830
critical-section = "1.2.0"

riscv/macros/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ edition = "2021"
1515
[lib]
1616
proc-macro = true
1717

18+
[features]
19+
rt = []
20+
rt-v-trap = ["rt"]
21+
1822
[dependencies]
1923
proc-macro2 = "1.0"
2024
quote = "1.0"

riscv/macros/src/lib.rs

Lines changed: 54 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use syn::{
1111
};
1212

1313
/// Struct to represent a function parameter.
14+
#[cfg(feature = "rt")]
1415
struct FunctionParam {
1516
/// Name of the parameter.
1617
param_name: TokenStream2,
@@ -20,6 +21,7 @@ struct FunctionParam {
2021

2122
/// Configuration parameters of a trap. It is useful to abstract the
2223
/// differences between exception handlers and core interrupt handlers.
24+
#[cfg(feature = "rt")]
2325
struct TrapConfig {
2426
/// Name of the default handler (e.g., `DefaultHandler` for core interrupts).
2527
default_handler: TokenStream2,
@@ -31,6 +33,7 @@ struct TrapConfig {
3133
handlers_array_name: TokenStream2,
3234
}
3335

36+
#[cfg(feature = "rt")]
3437
impl TrapConfig {
3538
/// Vector with all the input parameters expected when declaring extern handler functions
3639
fn extern_signature(&self) -> Vec<TokenStream2> {
@@ -107,6 +110,7 @@ impl PacTrait {
107110
}
108111

109112
/// For Exception or an Interrupt enums, it returns the trap configuration details.
113+
#[cfg(feature = "rt")]
110114
fn trap_config(&self) -> Option<TrapConfig> {
111115
match self {
112116
Self::Exception => Some(TrapConfig {
@@ -163,6 +167,7 @@ impl InterruptType {
163167
}
164168

165169
/// Returns a token stream representing the name of the array of interrupt service routines
170+
#[cfg(feature = "rt")]
166171
fn isr_array_name(&self) -> TokenStream2 {
167172
match self {
168173
Self::Core => quote!(__CORE_INTERRUPTS),
@@ -171,6 +176,7 @@ impl InterruptType {
171176
}
172177

173178
/// Returns a token stream representing the name of the interrupt dispatch function
179+
#[cfg(feature = "rt")]
174180
fn dispatch_fn_name(&self) -> TokenStream2 {
175181
match self {
176182
Self::Core => quote!(_dispatch_core_interrupt),
@@ -239,6 +245,7 @@ impl PacEnumItem {
239245
}
240246

241247
/// Returns a vector of token streams representing the interrupt handler functions
248+
#[cfg(feature = "rt")]
242249
fn handlers(&self, trap_config: &TrapConfig) -> Vec<TokenStream2> {
243250
let signature = trap_config.extern_signature();
244251
self.numbers
@@ -252,6 +259,7 @@ impl PacEnumItem {
252259
/// Returns a sorted vector of token streams representing all the elements of the interrupt array.
253260
/// If an interrupt number is not present in the enum, the corresponding element is `None`.
254261
/// Otherwise, it is `Some(<interrupt_handler>)`.
262+
#[cfg(feature = "rt")]
255263
fn handlers_array(&self) -> Vec<TokenStream2> {
256264
let mut vectors = vec![];
257265
for i in 0..=self.max_number {
@@ -264,6 +272,7 @@ impl PacEnumItem {
264272
vectors
265273
}
266274

275+
#[cfg(feature = "rt-v-trap")]
267276
fn vector_table(&self) -> TokenStream2 {
268277
let align = match std::env::var("RISCV_MTVEC_ALIGN") {
269278
Ok(x) => x.parse::<u32>().ok(),
@@ -280,7 +289,7 @@ impl PacEnumItem {
280289
};
281290
let mut asm = format!(
282291
r#"
283-
#[cfg(all(feature = "v-trap", any(target_arch = "riscv32", target_arch = "riscv64")))]
292+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
284293
core::arch::global_asm!("
285294
.section .trap.vector, \"ax\"
286295
.global _vector_table
@@ -328,8 +337,6 @@ core::arch::global_asm!("
328337
let max_discriminant = self.max_number;
329338
let valid_matches = self.valid_matches();
330339

331-
let is_core_interrupt = matches!(attr, PacTrait::Interrupt(InterruptType::Core));
332-
333340
// Push the trait implementation
334341
res.push(quote! {
335342
unsafe impl riscv::#trait_name for #name {
@@ -354,54 +361,51 @@ core::arch::global_asm!("
354361
res.push(quote! { unsafe impl riscv::#marker_trait_name for #name {} });
355362
}
356363

364+
#[cfg(feature = "rt")]
357365
if let Some(trap_config) = attr.trap_config() {
358-
let default_handler = &trap_config.default_handler;
359-
let extern_signature = trap_config.extern_signature();
360-
let handler_input = trap_config.handler_input();
361-
let array_signature = trap_config.array_signature();
362-
let dispatch_fn_name = &trap_config.dispatch_fn_name;
363-
let dispatch_fn_args = &trap_config.dispatch_fn_signature();
364-
let vector_table = &trap_config.handlers_array_name;
365-
366-
let handlers = self.handlers(&trap_config);
367-
let interrupt_array = self.handlers_array();
368-
let cfg_v_trap = match is_core_interrupt {
369-
true => Some(quote!(#[cfg(not(feature = "v-trap"))])),
370-
false => None,
371-
};
372-
373-
// Push the interrupt handler functions and the interrupt array
374-
res.push(quote! {
375-
#cfg_v_trap
376-
extern "C" {
377-
#(#handlers;)*
366+
match attr {
367+
#[cfg(feature = "rt-v-trap")]
368+
PacTrait::Interrupt(InterruptType::Core) => {
369+
res.push(self.vector_table());
378370
}
379-
380-
#cfg_v_trap
381-
#[doc(hidden)]
382-
#[no_mangle]
383-
pub static #vector_table: [Option<unsafe extern "C" fn(#(#array_signature),*)>; #max_discriminant + 1] = [
384-
#(#interrupt_array),*
385-
];
386-
387-
#cfg_v_trap
388-
#[inline]
389-
#[no_mangle]
390-
unsafe extern "C" fn #dispatch_fn_name(#(#dispatch_fn_args),*) {
391-
extern "C" {
392-
fn #default_handler(#(#extern_signature),*);
393-
}
394-
395-
match #vector_table.get(code) {
396-
Some(Some(handler)) => handler(#(#handler_input),*),
397-
_ => #default_handler(#(#handler_input),*),
398-
}
371+
_ => {
372+
let default_handler = &trap_config.default_handler;
373+
let extern_signature = trap_config.extern_signature();
374+
let handler_input = trap_config.handler_input();
375+
let array_signature = trap_config.array_signature();
376+
let dispatch_fn_name = &trap_config.dispatch_fn_name;
377+
let dispatch_fn_args = &trap_config.dispatch_fn_signature();
378+
let vector_table = &trap_config.handlers_array_name;
379+
380+
let handlers = self.handlers(&trap_config);
381+
let interrupt_array = self.handlers_array();
382+
383+
res.push(quote! {
384+
extern "C" {
385+
#(#handlers;)*
386+
}
387+
388+
#[doc(hidden)]
389+
#[no_mangle]
390+
pub static #vector_table: [Option<unsafe extern "C" fn(#(#array_signature),*)>; #max_discriminant + 1] = [
391+
#(#interrupt_array),*
392+
];
393+
394+
#[inline]
395+
#[no_mangle]
396+
unsafe extern "C" fn #dispatch_fn_name(#(#dispatch_fn_args),*) {
397+
extern "C" {
398+
fn #default_handler(#(#extern_signature),*);
399+
}
400+
401+
match #vector_table.get(code) {
402+
Some(Some(handler)) => handler(#(#handler_input),*),
403+
_ => #default_handler(#(#handler_input),*),
404+
}
405+
}
406+
});
399407
}
400-
});
401-
}
402-
403-
if is_core_interrupt {
404-
res.push(self.vector_table());
408+
}
405409
}
406410

407411
res
@@ -413,8 +417,8 @@ core::arch::global_asm!("
413417
/// As these traits are unsafe, the macro must be called with the `unsafe` keyword followed by the trait name.
414418
/// In this way, we warn callers that they must comply with the requirements of the trait.
415419
///
416-
/// The trait name must be one of `ExceptionNumber`, `InterruptNumber`, `PriorityNumber`, or `HartIdNumber`.
417-
/// Marker traits `CoreInterruptNumber` and `ExternalInterruptNumber` cannot be implemented using this macro.
420+
/// The trait name must be one of `ExceptionNumber`, `CoreInterruptNumber`, `ExternalInterruptNumber`,
421+
/// `PriorityNumber`, or `HartIdNumber`.
418422
///
419423
/// # Safety
420424
///

riscv/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@
3131
//! and may cause functional problems in systems where some interrupts must NOT be disabled
3232
//! or critical sections are managed as part of an RTOS. In these cases, you should use
3333
//! a target-specific implementation instead, typically provided by a HAL or RTOS crate.
34+
//!
35+
//! ## `rt`
36+
//!
37+
//! This feature enables code related to [`riscv-rt`](https://github.com/rust-embedded/riscv/tree/master/riscv-rt)
38+
//! runtime support in the `riscv::pac_enum` macro. Namely, it enables the generation of
39+
//! trap handler functions and dispatch functions.
40+
//!
41+
//! ## `rt-v-trap`
42+
//!
43+
//! This feature enables code related to vectored trap handling in addition to the `rt` feature.
44+
//! Namely, it enables the generation of a vector table and the corresponding assembly code for core interrupts.
3445
3546
#![no_std]
3647
#![allow(clippy::missing_safety_doc)]

0 commit comments

Comments
 (0)