use esp32c6::{INTERRUPT_CORE0, PLIC_MX};
pub use esp32c6::{Interrupt, Peripherals};
pub use riscv::interrupt;
pub use riscv::register::mcause;
#[cfg(all(feature = "riscv-esp32c6", not(feature = "riscv-esp32c6-backend")))]
compile_error!("Building for the esp32c6, but 'riscv-esp32c6-backend not selected'");
#[inline(always)]
pub fn run<F>(priority: u8, f: F)
where
F: FnOnce(),
{
unsafe {
if priority == 1 {
f();
(*PLIC_MX::ptr())
.mxint_thresh()
.write(|w| w.cpu_mxint_thresh().bits(1));
} else {
let initial = (*PLIC_MX::ptr())
.mxint_thresh()
.read()
.cpu_mxint_thresh()
.bits();
f();
(*PLIC_MX::ptr())
.mxint_thresh()
.write(|w| w.cpu_mxint_thresh().bits(initial));
}
}
}
#[inline(always)]
pub unsafe fn lock<T, R>(ptr: *mut T, ceiling: u8, f: impl FnOnce(&mut T) -> R) -> R {
unsafe {
if ceiling == (15) {
critical_section::with(|_| f(&mut *ptr))
} else {
let current = (*PLIC_MX::ptr())
.mxint_thresh()
.read()
.cpu_mxint_thresh()
.bits();
(*PLIC_MX::ptr())
.mxint_thresh()
.write(|w| w.cpu_mxint_thresh().bits(ceiling + 1));
let r = f(&mut *ptr);
(*PLIC_MX::ptr())
.mxint_thresh()
.write(|w| w.cpu_mxint_thresh().bits(current));
r
}
}
}
#[inline(always)]
pub fn pend(int: Interrupt) {
unsafe {
let peripherals = Peripherals::steal();
match int {
Interrupt::FROM_CPU_INTR0 => peripherals
.INTPRI
.cpu_intr_from_cpu_0()
.write(|w| w.cpu_intr_from_cpu_0().bit(true)),
Interrupt::FROM_CPU_INTR1 => peripherals
.INTPRI
.cpu_intr_from_cpu_1()
.write(|w| w.cpu_intr_from_cpu_1().bit(true)),
Interrupt::FROM_CPU_INTR2 => peripherals
.INTPRI
.cpu_intr_from_cpu_2()
.write(|w| w.cpu_intr_from_cpu_2().bit(true)),
Interrupt::FROM_CPU_INTR3 => peripherals
.INTPRI
.cpu_intr_from_cpu_3()
.write(|w| w.cpu_intr_from_cpu_3().bit(true)),
_ => panic!("Unsupported software interrupt"), };
}
}
pub fn unpend(int: Interrupt) {
unsafe {
let peripherals = Peripherals::steal();
match int {
Interrupt::FROM_CPU_INTR0 => peripherals
.INTPRI
.cpu_intr_from_cpu_0()
.write(|w| w.cpu_intr_from_cpu_0().bit(false)),
Interrupt::FROM_CPU_INTR1 => peripherals
.INTPRI
.cpu_intr_from_cpu_1()
.write(|w| w.cpu_intr_from_cpu_1().bit(false)),
Interrupt::FROM_CPU_INTR2 => peripherals
.INTPRI
.cpu_intr_from_cpu_2()
.write(|w| w.cpu_intr_from_cpu_2().bit(false)),
Interrupt::FROM_CPU_INTR3 => peripherals
.INTPRI
.cpu_intr_from_cpu_3()
.write(|w| w.cpu_intr_from_cpu_3().bit(false)),
_ => panic!("Unsupported software interrupt"),
};
}
}
pub fn enable(int: Interrupt, prio: u8, cpu_int_id: u8) {
unsafe {
(INTERRUPT_CORE0::ptr() as *mut u32)
.offset(int as isize)
.write_volatile(cpu_int_id as u32);
(*PLIC_MX::ptr())
.mxint_pri(cpu_int_id as usize)
.write(|w| w.bits(prio as u32));
(*PLIC_MX::ptr())
.mxint_enable()
.modify(|r, w| w.bits((1 << cpu_int_id) | r.bits()));
}
}