Use PLIC_MX instead of INTPRI to set interrupt priorities

This doesn't fix the GPIO interrupt triggering during a higher priority
CPU task, but does fix rtic-monotonics. I am unsure how to fix the
former as PLIC_MX doesn't have a function like `cpu_intr_from_cpu_x` to
pend/unpend CPU interrupts, and if the CPU interrupts are enabled with
PLIC_MX instead of INTPRI then the MCU just hangs when there is a CPU
interrupt.
This commit is contained in:
Eli Hastings 2025-02-26 11:39:09 +00:00 committed by Henrik Tjäder
parent ef09e4b65f
commit 9305963752
2 changed files with 58 additions and 36 deletions

View file

@ -35,7 +35,7 @@ pub mod prelude {
pub use fugit::{self, ExtU64, ExtU64Ceil}; pub use fugit::{self, ExtU64, ExtU64Ceil};
} }
use crate::TimerQueueBackend; use crate::TimerQueueBackend;
use esp32c6::{INTERRUPT_CORE0, INTPRI, SYSTIMER}; use esp32c6::{INTERRUPT_CORE0, PLIC_MX, SYSTIMER};
use rtic_time::timer_queue::TimerQueue; use rtic_time::timer_queue::TimerQueue;
/// Timer implementing [`TimerQueueBackend`]. /// Timer implementing [`TimerQueueBackend`].
@ -57,13 +57,13 @@ impl TimerBackend {
.write_volatile(cpu_interrupt_number as u32); .write_volatile(cpu_interrupt_number as u32);
// Set the interrupt's priority: // Set the interrupt's priority:
(*INTPRI::ptr()) (*PLIC_MX::ptr())
.cpu_int_pri(cpu_interrupt_number as usize) .mxint_pri(cpu_interrupt_number as usize)
.write(|w| w.bits(15 as u32)); .write(|w| w.bits(15 as u32));
// Finally, enable the CPU interrupt: // Finally, enable the CPU interrupt:
(*INTPRI::ptr()) (*PLIC_MX::ptr())
.cpu_int_enable() .mxint_enable()
.modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits()));
} }

View file

@ -1,5 +1,5 @@
pub use esp32c6::{Interrupt, Peripherals}; pub use esp32c6::{Interrupt, Peripherals};
use esp32c6::{INTERRUPT_CORE0, INTPRI}; use esp32c6::{INTERRUPT_CORE0, INTPRI, PLIC_MX};
pub use riscv::interrupt; pub use riscv::interrupt;
pub use riscv::register::mcause; pub use riscv::register::mcause;
@ -15,25 +15,25 @@ where
//if priority is 1, priority thresh should be 1 //if priority is 1, priority thresh should be 1
f(); f();
unsafe { unsafe {
(*INTPRI::ptr()) (*PLIC_MX::ptr())
.cpu_int_thresh() .mxint_thresh()
.write(|w| w.cpu_int_thresh().bits(1)); .write(|w| w.cpu_mxint_thresh().bits(1));
} }
} else { } else {
//read current thresh //read current thresh
let initial = unsafe { let initial = unsafe {
(*INTPRI::ptr()) (*PLIC_MX::ptr())
.cpu_int_thresh() .mxint_thresh()
.read() .read()
.cpu_int_thresh() .cpu_mxint_thresh()
.bits() .bits()
}; };
f(); f();
//write back old thresh //write back old thresh
unsafe { unsafe {
(*INTPRI::ptr()) (*PLIC_MX::ptr())
.cpu_int_thresh() .mxint_thresh()
.write(|w| w.cpu_int_thresh().bits(initial)); .write(|w| w.cpu_mxint_thresh().bits(initial));
} }
} }
} }
@ -57,29 +57,33 @@ where
#[inline(always)] #[inline(always)]
pub unsafe fn lock<T, R>(ptr: *mut T, ceiling: u8, f: impl FnOnce(&mut T) -> R) -> R { pub unsafe fn lock<T, R>(ptr: *mut T, ceiling: u8, f: impl FnOnce(&mut T) -> R) -> R {
if ceiling == (15) { if ceiling == (15) {
//turn off interrupts completely, were at max prio // Turn off interrupts completely, we're at max prio
let r = critical_section::with(|_| f(&mut *ptr)); let r = critical_section::with(|_| f(&mut *ptr));
r r
} else { } else {
let current = unsafe { let current = unsafe {
(*INTPRI::ptr()) (*PLIC_MX::ptr())
.cpu_int_thresh() .mxint_thresh()
.read() .read()
.cpu_int_thresh() .cpu_mxint_thresh()
.bits() .bits()
}; };
// esp32c6 lets interrupts with prio equal to threshold through so we up it by one
unsafe { unsafe {
(*INTPRI::ptr()) (*PLIC_MX::ptr())
.cpu_int_thresh() .mxint_thresh()
.write(|w| w.cpu_int_thresh().bits(ceiling + 1)); .write(|w| w.cpu_mxint_thresh().bits(ceiling + 1));
} //esp32c6 lets interrupts with prio equal to threshold through so we up it by one
let r = f(&mut *ptr);
unsafe {
(*INTPRI::ptr())
.cpu_int_thresh()
.write(|w| w.cpu_int_thresh().bits(current));
} }
let r = f(&mut *ptr);
unsafe {
(*PLIC_MX::ptr())
.mxint_thresh()
.write(|w| w.cpu_mxint_thresh().bits(current));
}
r r
} }
} }
@ -144,14 +148,32 @@ pub fn enable(int: Interrupt, prio: u8, cpu_int_id: u8) {
.offset(int as isize) .offset(int as isize)
.write_volatile(cpu_int_id as u32); .write_volatile(cpu_int_id as u32);
// Set the interrupt's priority: match int {
(*INTPRI::ptr()) Interrupt::FROM_CPU_INTR0
.cpu_int_pri(cpu_int_id as usize) | Interrupt::FROM_CPU_INTR1
.write(|w| w.bits(prio as u32)); | Interrupt::FROM_CPU_INTR2
| Interrupt::FROM_CPU_INTR3 => {
// Set the interrupt's priority:
(*INTPRI::ptr())
.cpu_int_pri(cpu_int_id as usize)
.write(|w| w.bits(prio as u32));
// Finally, enable the CPU interrupt: // Finally, enable the CPU interrupt:
(*INTPRI::ptr()) (*INTPRI::ptr())
.cpu_int_enable() .cpu_int_enable()
.modify(|r, w| w.bits((1 << cpu_int_id) | r.bits())); .modify(|r, w| w.bits((1 << cpu_int_id) | r.bits()));
}
_ => {
// Set the interrupt's priority:
(*PLIC_MX::ptr())
.mxint_pri(cpu_int_id as usize)
.write(|w| w.bits(prio as u32));
// Finally, enable the CPU interrupt:
(*PLIC_MX::ptr())
.mxint_enable()
.modify(|r, w| w.bits((1 << cpu_int_id) | r.bits()));
}
}
} }
} }