ESP32 crashes when running uPy from ISR
When MICROPY_PY_THREAD is enabled, ISR cannot be used for anything except mp_sched_schedule.
That's because a call to MP_STATE_THREAD (by nlr_push for example) calls pvTaskGetThreadLocalStoragePointer which is invalid in ISR context.
Perhaps Micropython should allocate state for ISR context as well?
ports/esp32: Fix crash and improve timer interrupt allocation
Summary
esp_intr_free is not safe to call from the timer ISR because it requires the current task (the one the ISR interrupted) to be pinned to the same core as the interrupt was allocated on. The ISR is of course guaranteed to interrupt a task on the same core, but it's not guaranteed that that task is also pinned to that core.
This was causing a lockup followed by ISR watchdog timeout in the machine_uart RXIDLE timer (which disables the timer from its own callback) when the ISR happened to interrupt a task that was not pinned to a specific core (for example for me if often hit the lwIP TCP/IP thread task).
The first commit in this PR fixes that by merely disabling the interrupt, which is safe to do from the ISR since that only requires that we're currently running on the same core (which the ISR always is), regardless of the current task.
Additionally, the second commit makes repeated disabling and enabling of the interrupt (such as the UART RXIDLE does) a bit more efficient by re-enabling instead of reallocating it. That also allowed to removing some code duplication and simplify how machine_uart uses the timer.
Testing
I've been using these fixes in combination with https://github.com/micropython/micropython/pull/17138 (which changed the PPP implementation to use that RXIDLE IRQ). Like that PR, I've been running this on three custom boards (1x original ESP32, 2x ESP32S3) for a few weeks at the moment of writing.