Tweak xtensa interrupt handling (#2148)
* Tweak xtensa interrupt handling * Deduplicate peripheral interrupt handling
This commit is contained in:
parent
45806dfba0
commit
cc4c6e1a8e
@ -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) };
|
||||
|
||||
Loading…
Reference in New Issue
Block a user