nrf/modules/machine: Catch exceptions from pin interrupts.

Exceptions in pin interrupt handlers would end up crashing MicroPython with
a "FATAL: uncaught exception".

In addition, MicroPython would get stuck trying to output this error
message, or generally any print output from inside a pin interrupt handler,
through the UART after the first character, so that only "F" was visible.
The reason was a matching interrupt priority between the running pin
interrupt and the UARTE interrupt signaling completion of the output
operation.  Fix that by increasing the UARTE interrupt priority.

Code taken from the stm32 port and adapted.

Signed-off-by: Christian Walther <cwalther@gmx.ch>
This commit is contained in:
Christian Walther 2024-01-05 16:17:55 +01:00 committed by Damien George
parent b10182bbcc
commit 5e926b2222
2 changed files with 27 additions and 6 deletions

View file

@ -33,6 +33,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/gc.h"
#include "pin.h"
#include "nrf_gpio.h"
#include "nrfx_gpiote.h"
@ -498,7 +499,29 @@ static void pin_common_irq_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t
mp_obj_t pin_number = MP_OBJ_NEW_SMALL_INT(pin);
const pin_obj_t *pin_obj = pin_find(pin_number);
if (pin_handler != mp_const_none) {
#if MICROPY_ENABLE_SCHEDULER
mp_sched_lock();
#endif
// When executing code within a handler we must lock the GC to prevent
// any memory allocations. We must also catch any exceptions.
gc_lock();
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_call_function_1(pin_handler, (mp_obj_t)pin_obj);
nlr_pop();
} else {
// Uncaught exception; disable the callback so it doesn't run again.
MP_STATE_PORT(pin_irq_handlers)[pin] = mp_const_none;
nrfx_gpiote_in_uninit(pin);
mp_printf(MICROPY_ERROR_PRINTER, "uncaught exception in interrupt handler for Pin('%q')\n", pin_obj->name);
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
}
gc_unlock();
#if MICROPY_ENABLE_SCHEDULER
mp_sched_unlock();
#endif
}
}
static mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {

View file

@ -214,11 +214,9 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
config.hal_cfg.parity = NRF_UART_PARITY_EXCLUDED;
#if (BLUETOOTH_SD == 100)
config.interrupt_priority = 3;
#else
config.interrupt_priority = 6;
#endif
// Higher priority than pin interrupts, otherwise printing exceptions from
// interrupt handlers gets stuck.
config.interrupt_priority = NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY - 1;
// These baudrates are not supported, it seems.
if (args[ARG_baudrate].u_int < 1200 || args[ARG_baudrate].u_int > 1000000) {