-
Notifications
You must be signed in to change notification settings - Fork 178
riscv
: Use riscv_pac::CoreInterruptNumber
in xip
registers
#331
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
Conversation
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.
LGTM
riscv/src/register/mip.rs
Outdated
pub unsafe fn clear_pending<I: CoreInterruptNumber>(&mut self, interrupt: I) { | ||
self.bits = bf_insert(self.bits, interrupt.number(), 1, 0); | ||
} |
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.
I think we might face an issue when using the Mip::clear_pending
method. For example:
- We read the
mip
register and store its value inMip
. Interrupt i is pending, while interrupt j is not. - Interrupt j triggers and now
mip
registers this interrupt as pending - We clear the interrupt i in
Mip
and write its value tomip
. As interrupts are cleared by writing a 0 in pending interrupts, we accidentally clear interrupt j.
Perhaps it is better to remove this method and only leave the atomic version mip::clear_pending
@rmsyn any thoughts?
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.
I agree with your reasoning above, and may even want to remove the public write(mip: Mip)
implementation, though we could also just provide documentation warning about the situation you described. We could replace it with and/or add a modify
-style implementation, where the user provides a closure for a read-modify-write procedure.
Something like:
impl Mip {
/// Performs a read-modify-write procedure on the [Mip] CSR.
///
/// # Example
///
/// ```rust, no_run
/// use riscv::register::Mip;
///
/// Mip::modify_pending(|mip| {
/// if mip.is_pending(MTIMER) {
/// mip.clear_pending(MTIMER);
/// }
///
/// // ... do other mip things
///
/// // return the modified in-memory structure to write
/// mip
/// });
/// ```
pub fn modify_pending(f: FnOnce(Self) -> Self) {
unsafe { write(f(read())) }
}
}
There is still the off chance that the above runs into the same issue regarding an interrupt firing while processing the closure, but the tighter timing decreases the likelihood.
We could also provide some documentation that for the most control, users should reach for the free is_pending
and clear_pending
functions.
The closure approach does somewhat limit how the user responds to the interrupts since they can't pass any local variables.
I set all |
I don't think that really addresses the issue you brought up, since a previous value could still clear an interrupt that fired in between the Another potential solution is to manually implement Again, the only sure way I see to resolve the issue is to force atomic operations, or some form of tracking for changes. For example, add a Maybe there are other solutions? |
ad91bcc
to
335f3a7
Compare
I would go for a read-only mechanism for |
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.
I would go for a read-only mechanism for
xip
registers, withunsafe fn clear_pending<I>()
functions that use atomic instructions to clear interrupts. If a given target presents a more sophisticatedxip
register, it should be reimplemented on the PAC or in anriscv-chipid
crate that reexposes parts ofriscv
and reimplements the remaining.
That sounds like a much simpler solution! LGTM
The methods for unpending interrupts via xip registers are marked as
unsafe
, as per the RISCV ISA specification:Therefore, each platform may provide a safe abstraction of these functions for their target when applies.