From 0bd58a56137bd9124756ed0f57b4213daccfc7d5 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 23 Apr 2020 16:19:15 +1000 Subject: [PATCH] esp8266/machine_pin: Move pin_intr_handler to iRAM, de-support hard IRQ. GPIO interrupts can occur when the flash ROM cache is in use and so the GPIO interrupt handler must be in iRAM. This commit moves the handler to iRAM, and also moves mp_sched_schedule to iRAM which is called by pin_intr_handler. As part of this fix the Pin class can no longer support hard=True in the Pin.irq() method, because the VM and runtime are too big to put in iRAM. Fixes #5714. --- ports/esp8266/machine_pin.c | 24 +++++------------------- ports/esp8266/mpconfigport.h | 1 + 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c index f33f977874..4e74ad652d 100644 --- a/ports/esp8266/machine_pin.c +++ b/ports/esp8266/machine_pin.c @@ -37,7 +37,6 @@ #include "py/gc.h" #include "py/mphal.h" #include "extmod/virtpin.h" -#include "ets_alt_task.h" #include "modmachine.h" #define GET_TRIGGER(phys_port) \ @@ -87,15 +86,11 @@ STATIC uint8_t pin_mode[16 + 1]; // forward declaration STATIC const pin_irq_obj_t pin_irq_obj[16]; -// whether the irq is hard or soft -STATIC bool pin_irq_is_hard[16]; - void pin_init0(void) { ETS_GPIO_INTR_DISABLE(); ETS_GPIO_INTR_ATTACH(pin_intr_handler_iram, NULL); // disable all interrupts memset(&MP_STATE_PORT(pin_irq_handler)[0], 0, 16 * sizeof(mp_obj_t)); - memset(pin_irq_is_hard, 0, sizeof(pin_irq_is_hard)); for (int p = 0; p < 16; ++p) { GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << p); SET_TRIGGER(p, 0); @@ -103,24 +98,13 @@ void pin_init0(void) { ETS_GPIO_INTR_ENABLE(); } -void pin_intr_handler(uint32_t status) { +void MP_FASTCODE(pin_intr_handler)(uint32_t status) { status &= 0xffff; for (int p = 0; status; ++p, status >>= 1) { if (status & 1) { mp_obj_t handler = MP_STATE_PORT(pin_irq_handler)[p]; if (handler != MP_OBJ_NULL) { - if (pin_irq_is_hard[p]) { - int orig_ets_loop_iter_disable = ets_loop_iter_disable; - ets_loop_iter_disable = 1; - mp_sched_lock(); - gc_lock(); - mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p])); - gc_unlock(); - mp_sched_unlock(); - ets_loop_iter_disable = orig_ets_loop_iter_disable; - } else { - mp_sched_schedule(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p])); - } + mp_sched_schedule(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p])); } } } @@ -390,6 +374,9 @@ STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k if (self->phys_port >= 16) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("pin does not have IRQ capabilities")); } + if (args[ARG_hard].u_bool) { + mp_raise_ValueError(MP_ERROR_TEXT("hard IRQ not supported")); + } if (n_args > 1 || kw_args->used != 0) { // configure irq @@ -401,7 +388,6 @@ STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k } ETS_GPIO_INTR_DISABLE(); MP_STATE_PORT(pin_irq_handler)[self->phys_port] = handler; - pin_irq_is_hard[self->phys_port] = args[ARG_hard].u_bool; SET_TRIGGER(self->phys_port, trigger); GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << self->phys_port); ETS_GPIO_INTR_ENABLE(); diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index 71c49cd246..e27ae1792c 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -192,5 +192,6 @@ extern const struct _mp_obj_module_t mp_module_onewire; #define MP_FASTCODE(n) __attribute__((section(".iram0.text." #n))) n #define MICROPY_WRAP_MP_KEYBOARD_INTERRUPT(f) MP_FASTCODE(f) +#define MICROPY_WRAP_MP_SCHED_SCHEDULE(f) MP_FASTCODE(f) #define _assert(expr) ((expr) ? (void)0 : __assert_func(__FILE__, __LINE__, __func__, #expr))