GPIO: prevent woken task interrupting GPIO handler (#2838)
* Clear interrupt bit before allowing waker to wake a task * Add test
This commit is contained in:
parent
b8f15f0a8b
commit
97598968eb
@ -930,8 +930,11 @@ fn handle_pin_interrupts(user_handler: fn()) {
|
||||
intr_bits -= 1 << pin_pos;
|
||||
|
||||
let pin_nr = pin_pos as u8 + bank.offset();
|
||||
asynch::PIN_WAKERS[pin_nr as usize].wake();
|
||||
set_int_enable(pin_nr, Some(0), 0, false);
|
||||
|
||||
crate::interrupt::free(|| {
|
||||
asynch::PIN_WAKERS[pin_nr as usize].wake();
|
||||
set_int_enable(pin_nr, Some(0), 0, false);
|
||||
});
|
||||
}
|
||||
|
||||
bank.write_interrupt_status_clear(intrs);
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
//! interrupt15() => Priority::Priority15
|
||||
//! ```
|
||||
|
||||
pub(crate) use esp_riscv_rt::riscv::interrupt::free;
|
||||
pub use esp_riscv_rt::TrapFrame;
|
||||
use riscv::register::{mcause, mtvec};
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Interrupt handling
|
||||
|
||||
use xtensa_lx::interrupt;
|
||||
pub(crate) use xtensa_lx::interrupt::free;
|
||||
use xtensa_lx_rt::exception::Context;
|
||||
|
||||
pub use self::vectored::*;
|
||||
|
||||
@ -904,7 +904,7 @@ where
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(esp32)] {
|
||||
// https://docs.espressif.com/projects/esp-chip-errata/en/latest/esp32/03-errata-description/esp32/cpu-subsequent-access-halted-when-get-interrupted.html
|
||||
xtensa_lx::interrupt::free(|| {
|
||||
crate::interrupt::free(|| {
|
||||
*byte = fifo.read().rxfifo_rd_byte().bits();
|
||||
});
|
||||
} else {
|
||||
|
||||
@ -399,4 +399,33 @@ mod tests {
|
||||
|
||||
_ = Input::new(pin, Pull::Down);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interrupt_executor_is_not_frozen(ctx: Context) {
|
||||
use esp_hal::interrupt::{software::SoftwareInterrupt, Priority};
|
||||
use esp_hal_embassy::InterruptExecutor;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
static INTERRUPT_EXECUTOR: StaticCell<InterruptExecutor<1>> = StaticCell::new();
|
||||
let interrupt_executor = INTERRUPT_EXECUTOR.init(InterruptExecutor::new(unsafe {
|
||||
SoftwareInterrupt::<1>::steal()
|
||||
}));
|
||||
|
||||
let spawner = interrupt_executor.start(Priority::max());
|
||||
|
||||
spawner.must_spawn(test_task(ctx.test_gpio1.degrade()));
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn test_task(pin: AnyPin) {
|
||||
let mut pin = Input::new(pin, Pull::Down);
|
||||
|
||||
// This line must return, even if the executor
|
||||
// is running at a higher priority than the GPIO handler.
|
||||
pin.wait_for_low().await;
|
||||
|
||||
embedded_test::export::check_outcome(());
|
||||
}
|
||||
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user