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>
pull/13497/head
Christian Walther 2024-01-05 16:17:55 +01:00 zatwierdzone przez Damien George
rodzic b10182bbcc
commit 5e926b2222
2 zmienionych plików z 27 dodań i 6 usunięć

Wyświetl plik

@ -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);
mp_call_function_1(pin_handler, (mp_obj_t)pin_obj);
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) {

Wyświetl plik

@ -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) {