Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

riscv-rt: Add mtvec-align features for the vector table alignment #259

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
57 changes: 0 additions & 57 deletions riscv-rt/src/interrupts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,64 +14,7 @@
//! code to adapt for the target needs. In this case, you may need to opt out this module.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a few lines of documentation for vectored mode about the RISCV_MTVEC_ALIGN environment variable and why it is necessary? You should also mention that, in most of the cases, this environment variable must be handled by the PAC crate, not users directly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not good at documentation, so I attempted something. Feel free to suggest an alternative.

//! To do so, activate the `no-interrupts` feature of the `riscv-rt` crate.

#[cfg(not(feature = "v-trap"))]
extern "C" {
fn SupervisorSoft();
fn MachineSoft();
fn SupervisorTimer();
fn MachineTimer();
fn SupervisorExternal();
fn MachineExternal();
}

/// Array with all the core interrupt handlers sorted according to their interrupt source code.
///
/// # Note
///
/// This array is necessary only in direct mode (i.e., `v-trap` feature disabled).
#[cfg(not(feature = "v-trap"))]
#[no_mangle]
pub static __CORE_INTERRUPTS: [Option<unsafe extern "C" fn()>; 12] = [
None,
Some(SupervisorSoft),
None,
Some(MachineSoft),
None,
Some(SupervisorTimer),
None,
Some(MachineTimer),
None,
Some(SupervisorExternal),
None,
Some(MachineExternal),
];

/// It calls the corresponding interrupt handler depending on the interrupt source code.
///
/// # Note
///
/// This function is only required in direct mode (i.e., `v-trap` feature disabled).
/// In vectored mode, interrupt handler dispatching is performed directly by hardware.
///
/// # Safety
///
/// This function must be called only from the [`crate::start_trap_rust`] function.
/// Do **NOT** call this function directly.
#[cfg(not(feature = "v-trap"))]
#[inline]
#[no_mangle]
pub unsafe extern "C" fn _dispatch_core_interrupt(code: usize) {
extern "C" {
fn DefaultHandler();
}
match __CORE_INTERRUPTS.get(code) {
Some(Some(handler)) => handler(),
_ => DefaultHandler(),
}
}

// In vectored mode, we also must provide a vector table
#[cfg(feature = "v-trap")]
#[riscv::pac_enum(unsafe CoreInterruptNumber)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum Interrupt {
Expand Down
22 changes: 13 additions & 9 deletions riscv/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,19 +265,14 @@ impl PacEnumItem {
}

fn vector_table(&self) -> TokenStream2 {
let mut align = match std::env::var("RISCV_MTVEC_ALIGN") {
let align = match std::env::var("RISCV_MTVEC_ALIGN") {
Ok(x) => x.parse::<u32>().ok(),
Err(std::env::VarError::NotPresent) => Some(4),
Err(std::env::VarError::NotUnicode(_)) => None,
};
if let Some(value) = align {
if !value.is_power_of_two() || value < 4 {
align = None;
}
}
let align = match align {
Some(x) => x,
None => {
Some(x) if x.is_power_of_two() && 4 <= x => x,
_ => {
return quote!(compile_error!(
"RISCV_MTVEC_ALIGN is not a power of 2 (minimum 4)"
))
Expand Down Expand Up @@ -333,6 +328,8 @@ core::arch::global_asm!("
let max_discriminant = self.max_number;
let valid_matches = self.valid_matches();

let is_core_interrupt = matches!(attr, PacTrait::Interrupt(InterruptType::Core));

// Push the trait implementation
res.push(quote! {
unsafe impl riscv::#trait_name for #name {
Expand Down Expand Up @@ -368,19 +365,26 @@ core::arch::global_asm!("

let handlers = self.handlers(&trap_config);
let interrupt_array = self.handlers_array();
let cfg_v_trap = match is_core_interrupt {
true => Some(quote!(#[cfg(not(feature = "v-trap"))])),
false => None,
};

// Push the interrupt handler functions and the interrupt array
res.push(quote! {
#cfg_v_trap
extern "C" {
#(#handlers;)*
}

#cfg_v_trap
#[doc(hidden)]
#[no_mangle]
pub static #vector_table: [Option<unsafe extern "C" fn(#(#array_signature),*)>; #max_discriminant + 1] = [
#(#interrupt_array),*
];

#cfg_v_trap
#[inline]
#[no_mangle]
unsafe extern "C" fn #dispatch_fn_name(#(#dispatch_fn_args),*) {
Expand All @@ -396,7 +400,7 @@ core::arch::global_asm!("
});
}

if let PacTrait::Interrupt(InterruptType::Core) = attr {
if is_core_interrupt {
res.push(self.vector_table());
}

Expand Down
Loading