diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst index 5254e163c02a3..3055491ebbba8 100644 --- a/docs/library/machine.Pin.rst +++ b/docs/library/machine.Pin.rst @@ -216,6 +216,7 @@ Methods - ``hard`` if true a hardware interrupt is used. This reduces the delay between the pin change and the handler being called. Hard interrupt handlers may not allocate memory; see :ref:`isr_rules`. + Not all ports support this argument. This method returns a callback object. diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c index f33f977874a9c..4e74ad652dc4e 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 71c49cd246a8c..5344a98d6a548 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -114,6 +114,10 @@ #define MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_POLL #define MICROPY_VM_HOOK_RETURN MICROPY_VM_HOOK_POLL +#include "xtirq.h" +#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() +#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) + // type definitions for the specific machine #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p))) @@ -192,5 +196,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)) diff --git a/py/mpconfig.h b/py/mpconfig.h index 1327d8b02753f..f2b3af1f2a314 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -1449,6 +1449,10 @@ typedef double mp_float_t; #define MICROPY_WRAP_MP_KEYBOARD_INTERRUPT(f) f #endif +#ifndef MICROPY_WRAP_MP_SCHED_SCHEDULE +#define MICROPY_WRAP_MP_SCHED_SCHEDULE(f) f +#endif + /*****************************************************************************/ /* Miscellaneous settings */ diff --git a/py/scheduler.c b/py/scheduler.c index b559091b83a4a..06d7b36c2cdc4 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -120,7 +120,7 @@ void mp_sched_unlock(void) { MICROPY_END_ATOMIC_SECTION(atomic_state); } -bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) { +bool MICROPY_WRAP_MP_SCHED_SCHEDULE(mp_sched_schedule)(mp_obj_t function, mp_obj_t arg) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); bool ret; if (!mp_sched_full()) {