Skip to content

Commit 56b23d9

Browse files
committed
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>
1 parent 6127259 commit 56b23d9

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

ports/nrf/modules/machine/pin.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "py/nlr.h"
3434
#include "py/runtime.h"
3535
#include "py/mphal.h"
36+
#include "py/gc.h"
3637
#include "pin.h"
3738
#include "nrf_gpio.h"
3839
#include "nrfx_gpiote.h"
@@ -498,7 +499,29 @@ static void pin_common_irq_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t
498499
mp_obj_t pin_number = MP_OBJ_NEW_SMALL_INT(pin);
499500
const pin_obj_t *pin_obj = pin_find(pin_number);
500501

501-
mp_call_function_1(pin_handler, (mp_obj_t)pin_obj);
502+
if (pin_handler != mp_const_none) {
503+
#if MICROPY_ENABLE_SCHEDULER
504+
mp_sched_lock();
505+
#endif
506+
// When executing code within a handler we must lock the GC to prevent
507+
// any memory allocations. We must also catch any exceptions.
508+
gc_lock();
509+
nlr_buf_t nlr;
510+
if (nlr_push(&nlr) == 0) {
511+
mp_call_function_1(pin_handler, (mp_obj_t)pin_obj);
512+
nlr_pop();
513+
} else {
514+
// Uncaught exception; disable the callback so it doesn't run again.
515+
MP_STATE_PORT(pin_irq_handlers)[pin] = mp_const_none;
516+
nrfx_gpiote_in_uninit(pin);
517+
mp_printf(MICROPY_ERROR_PRINTER, "uncaught exception in interrupt handler for Pin('%q')\n", pin_obj->name);
518+
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
519+
}
520+
gc_unlock();
521+
#if MICROPY_ENABLE_SCHEDULER
522+
mp_sched_unlock();
523+
#endif
524+
}
502525
}
503526

504527
static mp_obj_t pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {

ports/nrf/modules/machine/uart.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,9 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
214214

215215
config.hal_cfg.parity = NRF_UART_PARITY_EXCLUDED;
216216

217-
#if (BLUETOOTH_SD == 100)
218-
config.interrupt_priority = 3;
219-
#else
220-
config.interrupt_priority = 6;
221-
#endif
217+
// Higher priority than pin interrupts, otherwise printing exceptions from
218+
// interrupt handlers gets stuck.
219+
config.interrupt_priority = NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY - 1;
222220

223221
// These baudrates are not supported, it seems.
224222
if (args[ARG_baudrate].u_int < 1200 || args[ARG_baudrate].u_int > 1000000) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy