-
Notifications
You must be signed in to change notification settings - Fork 162
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
Support for non-standard exception and interrupts (clean) #223
Conversation
riscv-pac
: New ExceptionNumber
and *InterruptNumber
traitsriscv-pac
: New ExceptionNumber
, CoreInterruptNumber
, and ExternalInterruptNumber
traits
My only doubt is: should I guess Let me know what you think and I will update this PR accordingly. |
3c24f5e
to
7a98baa
Compare
riscv-pac
: New ExceptionNumber
, CoreInterruptNumber
, and ExternalInterruptNumber
traits
In the end, I pushed all the changes of #211 to this PR, but with a cleaner commit history. In my last commit, I also added three attribute-like macros in
use riscv_rt::{core_interrupt, entry, exception, external_interrupt};
use riscv::interrupt::{Exception, Interrupt}; // standard enums that implement the riscv-pac traits
#[core_interrupt(Interrupt::SupervisorTimer)]
unsafe fn supervisor_timer() -> ! {
// do something here
loop {}
}
// this won't compile, cause ExternalInterruptNumber trait is not implemented!
// #[external_interrupt(Interrupt::SupervisorSoft)]
// fn supervisor_soft() {
// // do something here
// loop {}
// }
#[exception(Exception::Breakpoint)]
unsafe fn breakpoint(_trap: &mut riscv_rt::TrapFrame) -> ! {
// do something here
loop {}
} |
My recommendation would be to stick with |
if sstatus.spie() { | ||
sstatus::set_spie(); | ||
} | ||
sstatus::set_spp(sstatus.spp()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar suggestion to the machine interrupt handler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, not sure about what is wrong with the current implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, not sure about what is wrong with the current implementation
Nothing, on second inspection I saw the call to csrrs
. I was mistaken before, and thought csrrw
was called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor style suggestions, and a couple suggestions for not clobbering CSR fields in machine + supervisor nested interrupt handlers.
Ok, so the only thing that I miss is improving the I will also use |
e36fdc0
to
274df75
Compare
Sorry for the delay, I took a few days off to disconnect. New stuff in
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
pub enum Trap<I, E> { | ||
Interrupt(I), | ||
Exception(E), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you decided to redefine Trap
using generics for the interrupt and exception variants?
If this is to allow external users to use a custom Interrupt
and Exception
type, maybe we could also provide a top-level alias that defaults to the local Interrupt
and Exception
type?
Something like:
pub type DefaultTrap = Trap<Interrupt, Exception>;
Another option could be to call the generic:
pub enum GenericTrap<I, E> {
// ...
}
with the alias as:
pub type Trap = GenericTrap<Interrupt, Exception>;
With some notes in the docs, I think the custom implementation would be easy to figure out for those that want it.
Using the latter would minimize the effort of integrating the breaking changes, while still allowing external users to define their own Trap
type for non-standard interrupts/exceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the idea now is updating svd2rust so PACs do this kind of type binding in pac::interrupt. PACs could either re-export the Exception and CoreInterrupt enums that are in riscv or define their custom type. Also the interface with mcause can be adjusted to hide this complexity to final users.
I'll do a PoC and share it with you.
My PR for You can check the outcome for the E310x chip here. @rmsyn , this is perhaps the most interesting fragment of the module: pub use riscv::{
interrupt::{disable, enable, free, nested},
CoreInterruptNumber, ExceptionNumber, HartIdNumber, PriorityNumber,
};
pub type Trap = riscv::interrupt::Trap<CoreInterrupt, Exception>;
#[doc = r" Retrieves the cause of a trap in the current hart."]
#[doc = r""]
#[doc = r" If the raw cause is not a valid interrupt or exception for the target, it returns an error."]
#[inline]
pub fn try_cause() -> riscv::result::Result<Trap> {
riscv::interrupt::try_cause()
}
#[doc = r" Retrieves the cause of a trap in the current hart (machine mode)."]
#[doc = r""]
#[doc = r" If the raw cause is not a valid interrupt or exception for the target, it panics."]
#[inline]
pub fn cause() -> Trap {
try_cause().unwrap()
} The idea is "substituting"/adapting |
Yes, everything looks awesome! This is exactly what I was suggesting, except the location of the alias is up a level of abstraction. I got a little confused when trying to directly upgrade while playing around with the code. Given the context of including these changes in Maybe for those using the At least, maybe some doc-tests on the |
I added new docs for |
c298a2f
to
0e657a8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know what you think!
LGTM. Awesome work @romancardenas
I agree, this clarifies how interrupts work in a RISC-V environment. Our docs on the separation can also help introduce the difference between the CLIC/CLINT (core-local) and PLIC (external) interrupt peripherals. This took me some time to get my head around. |
Let's wait a couple of days in case anyone wants to leave an additional review and then merge to master. |
How does this work for RP2350, where there is a need to have applications build for both Cortex-M and RISC-V, with no code changes? |
I still have that target in my to-study list. But I think it should be compatible. Note that the idea is changing the enumeration of interrupts and exceptions available on a target at compile time. So there will not be run-time changes. |
The proposed syntax is this, right? #[external_interrupt(ExternalInterrupt::UART)]
unsafe fn external_uart() -> ! {
} That's completely unlike what cortex-m-rt does. Will it (cortex-m-rt) be changed to match, or will the two architectures just be different? |
Oh and to clarify I mean https://github.com/rp-rs/rp-hal/blob/main/rp235x-hal-examples/src/bin/blinky.rs has to build with both |
Projects targetting that kind of architecture could feature-gate based on target, conditionally defining different trap handlers for each target. Ostensibly, they would want to do that indepently of the changes in this PR, since there are different traps that need handling, right? |
I plan to open a PR in |
I guess that in this kind of scenario, you would be doing this like |
cfg_attr I can live with. Different function signatures would be a problem. |
Function signatures should be the same except for exception handlers that need access to the trap frame, as each platform has a different TrapFrame struct to save the context. |
@adamgreig looks like @rmsyn 's review is still not eligible to unblock the merging |
Sorry, should be fixed now. |
If nobody opposes, I will merge this PR tomorrow by the end of the weekly meeting |
Ok, it seems we cannot easily bypass clippy warnings right now. I will look, as the current setup is inconvenient for all the use cases. In the meantime, I fixed the new issues arising in I will add this PR to the merge queue so it is merged as soon as it gets a positive review. |
I'll wait until you merge the changes here, and rebase on top of the clippy fixes. |
First PR resulting from #211
This PR presents the last version of
riscv-pac
. Namely, we have a newExceptionNumber
trait.Also, the
InterruptNumber
trait now comes with two new marker traits:CoreInterruptNumber
andExternalInterruptNumber
.This will allow us to filter interrupt sources.
Another change is that the
InterruptNumber
trait now deals withusize
instead ofu16
.The motivation of this change is the RISC-V ISA specification (there is more information about this in #211)
As a side effect, I also updated the
riscv-peripheral
trait to use the new approach.