Skip to content

Commit fd44c17

Browse files
authored
Fix riscv interrupt handling (#4315)
1 parent 981379e commit fd44c17

File tree

1 file changed

+26
-12
lines changed

1 file changed

+26
-12
lines changed

esp-hal/src/interrupt/riscv.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -841,25 +841,39 @@ mod rt {
841841
let prio = INTERRUPT_TO_PRIORITY[cpu_intr as usize];
842842
let configured_interrupts = vectored::configured_interrupts(core, status, prio);
843843

844+
// Change the current runlevel so that interrupt handlers can access the correct runlevel.
845+
let level = unsafe { change_current_runlevel(prio) };
846+
847+
// When nesting is possible, we run the nestable interrupts first. This ensures that we
848+
// don't violate assumptions made by non-nestable handlers.
849+
850+
if prio != Priority::max() {
851+
for interrupt_nr in configured_interrupts.iterator() {
852+
let handler =
853+
unsafe { pac::__EXTERNAL_INTERRUPTS[interrupt_nr as usize]._handler } as usize;
854+
let nested = (handler & 1) == 0;
855+
if nested {
856+
let handler: fn() =
857+
unsafe { core::mem::transmute::<usize, fn()>(handler & !1) };
858+
859+
unsafe { riscv::interrupt::nested(handler) };
860+
}
861+
}
862+
}
863+
864+
// Now we can run the non-nestable interrupt handlers.
865+
844866
for interrupt_nr in configured_interrupts.iterator() {
845867
let handler =
846868
unsafe { pac::__EXTERNAL_INTERRUPTS[interrupt_nr as usize]._handler } as usize;
847869
let not_nested = (handler & 1) == 1;
848-
let handler = handler & !1;
870+
if not_nested || prio == Priority::max() {
871+
let handler: fn() = unsafe { core::mem::transmute::<usize, fn()>(handler & !1) };
849872

850-
let handler: fn() = unsafe { core::mem::transmute::<usize, fn()>(handler) };
851-
852-
if not_nested || prio == Priority::Priority15 {
853873
handler();
854-
} else {
855-
let elevated = prio as u8;
856-
unsafe {
857-
let level =
858-
change_current_runlevel(unwrap!(Priority::try_from(elevated as u32)));
859-
riscv::interrupt::nested(handler);
860-
change_current_runlevel(level);
861-
}
862874
}
863875
}
876+
877+
unsafe { change_current_runlevel(level) };
864878
}
865879
}

0 commit comments

Comments
 (0)