Tweak xtensa interrupt handling (#2148)

* Tweak xtensa interrupt handling

* Deduplicate peripheral interrupt handling
This commit is contained in:
Dániel Buga 2024-09-17 10:10:21 +02:00 committed by GitHub
parent 45806dfba0
commit cc4c6e1a8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -490,37 +490,42 @@ mod vectored {
interrupt::get() & interrupt::get_mask() & CPU_INTERRUPT_LEVELS[level as usize];
if cpu_interrupt_mask & CPU_INTERRUPT_INTERNAL != 0 {
// Let's handle CPU-internal interrupts (NMI, Timer, Software, Profiling).
// These are rarely used by the HAL.
// Mask the relevant bits
let cpu_interrupt_mask = cpu_interrupt_mask & CPU_INTERRUPT_INTERNAL;
// Pick one
let cpu_interrupt_nr = cpu_interrupt_mask.trailing_zeros();
if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 {
// If the interrupt is edge triggered, we need to clear the request on the CPU's
// side.
if ((1 << cpu_interrupt_nr) & CPU_INTERRUPT_EDGE) != 0 {
interrupt::clear(1 << cpu_interrupt_nr);
}
if let Some(handler) = cpu_interrupt_nr_to_cpu_interrupt_handler(cpu_interrupt_nr) {
handler(level, save_frame);
}
} else if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 {
let cpu_interrupt_mask = cpu_interrupt_mask & CPU_INTERRUPT_EDGE;
let cpu_interrupt_nr = cpu_interrupt_mask.trailing_zeros();
interrupt::clear(1 << cpu_interrupt_nr);
// for edge interrupts cannot rely on the interrupt status
// register, therefore call all registered
// handlers for current level
let configured_interrupts =
get_configured_interrupts(core, chip_specific::INTERRUPT_EDGE, level);
for interrupt_nr in configured_interrupts.iterator() {
// Don't use `Interrupt::try_from`. It's slower and placed in flash
let interrupt: Interrupt = unsafe { core::mem::transmute(interrupt_nr as u16) };
handle_interrupt(level, interrupt, save_frame);
}
} else {
// finally check peripheral sources and fire of handlers from pac
// peripheral mapped interrupts are cleared by the peripheral
let status = get_status(core);
let configured_interrupts = get_configured_interrupts(core, status, level);
let status = if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 {
// Next, handle edge triggered peripheral interrupts.
// If the interrupt is edge triggered, we need to clear the
// request on the CPU's side
interrupt::clear(cpu_interrupt_mask & CPU_INTERRUPT_EDGE);
// For edge interrupts we cannot rely on the peripherals' interrupt status
// registers, therefore call all registered handlers for current level.
chip_specific::INTERRUPT_EDGE
} else {
// Finally, check level-triggered peripheral sources.
// These interrupts are cleared by the peripheral.
get_status(core)
};
let configured_interrupts = get_configured_interrupts(core, status, level);
for interrupt_nr in configured_interrupts.iterator() {
// Don't use `Interrupt::try_from`. It's slower and placed in flash
let interrupt: Interrupt = unsafe { core::mem::transmute(interrupt_nr as u16) };