use super::{InterruptKind, Priority, RunLevel};
use crate::{interrupt::ElevatedRunLevel, soc::pac::CLIC};
#[cfg(feature = "rt")]
pub(super) fn init() {
let clic = unsafe { CLIC::steal() };
clic.int_config()
.modify(|_, w| unsafe { w.mnlbits().bits(3) });
for int in clic.int_attr_iter() {
int.modify(|_, w| {
w.shv().hardware();
w.trig().positive_level()
});
}
}
pub(super) fn enable_cpu_interrupt_raw(cpu_interrupt: u32) {
let clic = unsafe { CLIC::steal() };
clic.int_ie(cpu_interrupt as usize)
.write(|w| w.int_ie().set_bit());
}
pub(super) fn set_kind_raw(cpu_interrupt: u32, kind: InterruptKind) {
let clic = unsafe { CLIC::steal() };
clic.int_attr(cpu_interrupt as usize)
.modify(|_, w| match kind {
InterruptKind::Level => w.trig().positive_level(),
InterruptKind::Edge => w.trig().positive_edge(),
});
}
pub(super) fn set_priority_raw(cpu_interrupt: u32, priority: Priority) {
let clic = unsafe { CLIC::steal() };
let prio_bits = prio_to_bits(RunLevel::Interrupt(ElevatedRunLevel::from_priority(
priority,
)));
clic.int_ctl(cpu_interrupt as usize)
.write(|w| unsafe { w.bits(prio_bits) });
}
pub(super) fn clear_raw(cpu_interrupt: u32) {
let clic = unsafe { CLIC::steal() };
clic.int_ip(cpu_interrupt as usize)
.write(|w| w.int_ip().clear_bit());
}
pub(super) fn cpu_interrupt_priority_raw(cpu_interrupt: u32) -> u8 {
let clic = unsafe { CLIC::steal() };
let prio_level = clic.int_ctl(cpu_interrupt as usize).read().bits() as usize;
bits_to_prio(prio_level)
}
pub(super) fn change_current_runlevel(level: RunLevel) -> u8 {
let current_runlevel = current_runlevel();
unsafe { mintthresh::write(prio_to_bits(level) as usize) };
current_runlevel
}
pub(crate) fn mil() -> usize {
mintstatus::read().mil()
}
pub(super) fn current_runlevel() -> u8 {
let mintthresh = mintthresh::read();
let mil = mil();
let level = mil.max(mintthresh);
bits_to_prio(level)
}
fn prio_to_bits(priority: RunLevel) -> u8 {
if priority.is_thread() {
0
} else {
0x1F | ((u32::from(priority) as u8 - 1) << 5)
}
}
fn bits_to_prio(bits: usize) -> u8 {
if bits < 0x1f {
0
} else {
((bits >> 5) + 1) as u8
}
}
mod mintthresh {
riscv::read_csr_as_usize!(0x347);
riscv::write_csr_as_usize!(0x347);
}
mod mintstatus {
macro_rules! assert {
($($tt:tt)*) => {
::core::assert!($($tt)*)
};
}
riscv::read_only_csr! {
Mintstatus: 0xfb1,
mask: usize::MAX,
}
riscv::read_only_csr_field! {
Mintstatus,
mil: [24:31],
}
}
#[cfg(feature = "rt")]
core::arch::global_asm!(
r#"
.section .trap, "ax"
/* Prevent the compiler from generating 2-byte instruction in the vector tables */
.option push
.option norvc
/**
* Vectored interrupt table. MTVT CSR points here.
*
* If an interrupt occurs and is configured as (hardware) vectored, the CPU will jump to
* MTVT[31:0] + 4 * interrupt_id
*
* In the case of the ESP32P4/ESP32C5, the interrupt matrix, between the CPU interrupt lines
* and the peripherals, offers 32 lines, and the lower 16 interrupts are used for CLINT.
*/
.balign 0x40
.global _mtvt_table
.type _mtvt_table, @function
_mtvt_table:
.word 0
.word _start_Trap1_trap
.word _start_Trap2_trap
.word _start_Trap3_trap
.word _start_Trap4_trap
.word _start_Trap5_trap
.word _start_Trap6_trap
.word _start_Trap7_trap
.word _start_Trap8_trap
.word _start_Trap9_trap
.word _start_Trap10_trap
.word _start_Trap11_trap
.word _start_Trap12_trap
.word _start_Trap13_trap
.word _start_Trap14_trap
.word _start_Trap15_trap
.word _start_Trap16_trap
.word _start_Trap17_trap
.word _start_Trap18_trap
.word _start_Trap19_trap
.word _start_Trap20_trap
.word _start_Trap21_trap
.word _start_Trap22_trap
.word _start_Trap23_trap
.word _start_Trap24_trap
.word _start_Trap25_trap
.word _start_Trap26_trap
.word _start_Trap27_trap
.word _start_Trap28_trap
.word _start_Trap29_trap
.word _start_Trap30_trap
.word _start_Trap31_trap
.word _start_Trap32_trap
.word _start_Trap33_trap
.word _start_Trap34_trap
.word _start_Trap35_trap
.word _start_Trap36_trap
.word _start_Trap37_trap
.word _start_Trap38_trap
.word _start_Trap39_trap
.word _start_Trap40_trap
.word _start_Trap41_trap
.word _start_Trap42_trap
.word _start_Trap43_trap
.word _start_Trap44_trap
.word _start_Trap45_trap
.word _start_Trap46_trap
.word _start_Trap47_trap
.size _mtvt_table, .-_mtvt_table
.option pop
"#
);