From 93059637524f99cfe477042135badf842ada48a1 Mon Sep 17 00:00:00 2001 From: Eli Hastings Date: Wed, 26 Feb 2025 11:39:09 +0000 Subject: [PATCH] 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. --- rtic-monotonics/src/esp32c6.rs | 10 ++-- rtic/src/export/riscv_esp32c6.rs | 84 ++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/rtic-monotonics/src/esp32c6.rs b/rtic-monotonics/src/esp32c6.rs index 60a81752963..5cb872acbb3 100644 --- a/rtic-monotonics/src/esp32c6.rs +++ b/rtic-monotonics/src/esp32c6.rs @@ -35,7 +35,7 @@ pub mod prelude { pub use fugit::{self, ExtU64, ExtU64Ceil}; } use crate::TimerQueueBackend; -use esp32c6::{INTERRUPT_CORE0, INTPRI, SYSTIMER}; +use esp32c6::{INTERRUPT_CORE0, PLIC_MX, SYSTIMER}; use rtic_time::timer_queue::TimerQueue; /// Timer implementing [`TimerQueueBackend`]. @@ -57,13 +57,13 @@ impl TimerBackend { .write_volatile(cpu_interrupt_number as u32); // Set the interrupt's priority: - (*INTPRI::ptr()) - .cpu_int_pri(cpu_interrupt_number as usize) + (*PLIC_MX::ptr()) + .mxint_pri(cpu_interrupt_number as usize) .write(|w| w.bits(15 as u32)); // Finally, enable the CPU interrupt: - (*INTPRI::ptr()) - .cpu_int_enable() + (*PLIC_MX::ptr()) + .mxint_enable() .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); } diff --git a/rtic/src/export/riscv_esp32c6.rs b/rtic/src/export/riscv_esp32c6.rs index b06bf5d17d2..cf7ac3c97c0 100644 --- a/rtic/src/export/riscv_esp32c6.rs +++ b/rtic/src/export/riscv_esp32c6.rs @@ -1,5 +1,5 @@ pub use esp32c6::{Interrupt, Peripherals}; -use esp32c6::{INTERRUPT_CORE0, INTPRI}; +use esp32c6::{INTERRUPT_CORE0, INTPRI, PLIC_MX}; pub use riscv::interrupt; pub use riscv::register::mcause; @@ -15,25 +15,25 @@ where //if priority is 1, priority thresh should be 1 f(); unsafe { - (*INTPRI::ptr()) - .cpu_int_thresh() - .write(|w| w.cpu_int_thresh().bits(1)); + (*PLIC_MX::ptr()) + .mxint_thresh() + .write(|w| w.cpu_mxint_thresh().bits(1)); } } else { //read current thresh let initial = unsafe { - (*INTPRI::ptr()) - .cpu_int_thresh() + (*PLIC_MX::ptr()) + .mxint_thresh() .read() - .cpu_int_thresh() + .cpu_mxint_thresh() .bits() }; f(); //write back old thresh unsafe { - (*INTPRI::ptr()) - .cpu_int_thresh() - .write(|w| w.cpu_int_thresh().bits(initial)); + (*PLIC_MX::ptr()) + .mxint_thresh() + .write(|w| w.cpu_mxint_thresh().bits(initial)); } } } @@ -57,29 +57,33 @@ where #[inline(always)] pub unsafe fn lock(ptr: *mut T, ceiling: u8, f: impl FnOnce(&mut T) -> R) -> R { 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)); r } else { let current = unsafe { - (*INTPRI::ptr()) - .cpu_int_thresh() + (*PLIC_MX::ptr()) + .mxint_thresh() .read() - .cpu_int_thresh() + .cpu_mxint_thresh() .bits() }; + // esp32c6 lets interrupts with prio equal to threshold through so we up it by one unsafe { - (*INTPRI::ptr()) - .cpu_int_thresh() - .write(|w| w.cpu_int_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)); + (*PLIC_MX::ptr()) + .mxint_thresh() + .write(|w| w.cpu_mxint_thresh().bits(ceiling + 1)); } + + let r = f(&mut *ptr); + + unsafe { + (*PLIC_MX::ptr()) + .mxint_thresh() + .write(|w| w.cpu_mxint_thresh().bits(current)); + } + r } } @@ -144,14 +148,32 @@ pub fn enable(int: Interrupt, prio: u8, cpu_int_id: u8) { .offset(int as isize) .write_volatile(cpu_int_id as u32); - // Set the interrupt's priority: - (*INTPRI::ptr()) - .cpu_int_pri(cpu_int_id as usize) - .write(|w| w.bits(prio as u32)); + match int { + Interrupt::FROM_CPU_INTR0 + | Interrupt::FROM_CPU_INTR1 + | 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: - (*INTPRI::ptr()) - .cpu_int_enable() - .modify(|r, w| w.bits((1 << cpu_int_id) | r.bits())); + // Finally, enable the CPU interrupt: + (*INTPRI::ptr()) + .cpu_int_enable() + .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())); + } + } } }