From 654efb7d0d9a79f8af3b234c119335dcd432c674 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Sun, 16 May 2021 21:37:41 +0300 Subject: [PATCH 1/9] ref. esp8266/Arduino#6047 --- cores/esp8266/Arduino.h | 8 +- cores/esp8266/FunctionalInterrupt.cpp | 65 ------ cores/esp8266/FunctionalInterrupt.h | 35 --- cores/esp8266/core_esp8266_wiring_digital.cpp | 211 +++++++++--------- 4 files changed, 115 insertions(+), 204 deletions(-) delete mode 100644 cores/esp8266/FunctionalInterrupt.cpp delete mode 100644 cores/esp8266/FunctionalInterrupt.h diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 2aab5770c9..696631f523 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -182,9 +182,9 @@ unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout); void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); -void attachInterrupt(uint8_t pin, void (*)(void), int mode); +void attachInterrupt(uint8_t pin, void (*)(), int mode); +void attachInterruptParam(uint8_t pin, void (*)(void*), int mode, void* param); void detachInterrupt(uint8_t pin); -void attachInterruptArg(uint8_t pin, void (*)(void*), void* arg, int mode); void preinit(void); void setup(void); @@ -223,6 +223,7 @@ void optimistic_yield(uint32_t interval_us); #ifdef __cplusplus #include +#include #include #include @@ -264,6 +265,9 @@ long secureRandom(long); long secureRandom(long, long); long map(long, long, long, long, long); +// Functional interrupt handler +void attachInterrupt(uint8_t pin, std::function, int mode); + void setTZ(const char* tz); void configTime(int timezone, int daylightOffset_sec, const char* server1, diff --git a/cores/esp8266/FunctionalInterrupt.cpp b/cores/esp8266/FunctionalInterrupt.cpp deleted file mode 100644 index f468595787..0000000000 --- a/cores/esp8266/FunctionalInterrupt.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include "Arduino.h" - -// Duplicate typedefs from core_esp8266_wiring_digital_c -typedef void (*voidFuncPtr)(void); -typedef void (*voidFuncPtrArg)(void*); - -// Helper functions for Functional interrupt routines -extern "C" void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtr userFunc, void*fp, int mode, bool functional); - - -void IRAM_ATTR interruptFunctional(void* arg) -{ - ArgStructure* localArg = (ArgStructure*)arg; - if (localArg->functionInfo->reqScheduledFunction) - { - schedule_function(std::bind(localArg->functionInfo->reqScheduledFunction,InterruptInfo(*(localArg->interruptInfo)))); - } - if (localArg->functionInfo->reqFunction) - { - localArg->functionInfo->reqFunction(); - } -} - -extern "C" -{ - void cleanupFunctional(void* arg) - { - ArgStructure* localArg = (ArgStructure*)arg; - delete (FunctionInfo*)localArg->functionInfo; - delete (InterruptInfo*)localArg->interruptInfo; - delete localArg; - } -} - -void attachInterrupt(uint8_t pin, std::function intRoutine, int mode) -{ - // use the local interrupt routine which takes the ArgStructure as argument - - InterruptInfo* ii = nullptr; - - FunctionInfo* fi = new FunctionInfo; - fi->reqFunction = intRoutine; - - ArgStructure* as = new ArgStructure; - as->interruptInfo = ii; - as->functionInfo = fi; - - __attachInterruptFunctionalArg(pin, (voidFuncPtr)interruptFunctional, as, mode, true); -} - -void attachScheduledInterrupt(uint8_t pin, std::function scheduledIntRoutine, int mode) -{ - InterruptInfo* ii = new InterruptInfo; - - FunctionInfo* fi = new FunctionInfo; - fi->reqScheduledFunction = scheduledIntRoutine; - - ArgStructure* as = new ArgStructure; - as->interruptInfo = ii; - as->functionInfo = fi; - - __attachInterruptFunctionalArg(pin, (voidFuncPtr)interruptFunctional, as, mode, true); -} diff --git a/cores/esp8266/FunctionalInterrupt.h b/cores/esp8266/FunctionalInterrupt.h deleted file mode 100644 index 968793e499..0000000000 --- a/cores/esp8266/FunctionalInterrupt.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef FUNCTIONALINTERRUPT_H -#define FUNCTIONALINTERRUPT_H - -#include -#include -#include - -extern "C" { -#include "c_types.h" -#include "ets_sys.h" -} - -// Structures for communication - -struct InterruptInfo { - uint8_t pin = 0; - uint8_t value = 0; - uint32_t micro = 0; -}; - -struct FunctionInfo { - std::function reqFunction = nullptr; - std::function reqScheduledFunction = nullptr; -}; - -struct ArgStructure { - InterruptInfo* interruptInfo = nullptr; - FunctionInfo* functionInfo = nullptr; -}; - -void attachInterrupt(uint8_t pin, std::function intRoutine, int mode); -void attachScheduledInterrupt(uint8_t pin, std::function scheduledIntRoutine, int mode); - - -#endif //INTERRUPTS_H diff --git a/cores/esp8266/core_esp8266_wiring_digital.cpp b/cores/esp8266/core_esp8266_wiring_digital.cpp index 6b42c3ee36..383012b89c 100644 --- a/cores/esp8266/core_esp8266_wiring_digital.cpp +++ b/cores/esp8266/core_esp8266_wiring_digital.cpp @@ -102,108 +102,70 @@ extern int IRAM_ATTR __digitalRead(uint8_t pin) { return 0; } +} // extern "C" + /* GPIO INTERRUPTS */ -typedef void (*voidFuncPtr)(void); -typedef void (*voidFuncPtrArg)(void*); +typedef void (*voidFuncPtr)(); +typedef void (*voidFuncParamPtr)(void*); +typedef std::function voidFuncObj; -typedef struct { - uint8_t mode; - voidFuncPtr fn; - void * arg; - bool functional; -} interrupt_handler_t; - -//duplicate from functionalInterrupt.h keep in sync -typedef struct InterruptInfo { - uint8_t pin; - uint8_t value; - uint32_t micro; -} InterruptInfo; - -typedef struct { - InterruptInfo* interruptInfo; - void* functionInfo; -} ArgStructure; - -static interrupt_handler_t interrupt_handlers[16] = { {0, 0, 0, 0}, }; -static uint32_t interrupt_reg = 0; +struct interrupt_handler_t { + interrupt_handler_t(const interrupt_handler_t&) = delete; + interrupt_handler_t(interrupt_handler_t&&) = delete; -void IRAM_ATTR interrupt_handler(void *arg, void *frame) -{ - (void) arg; - (void) frame; - uint32_t status = GPIE; - GPIEC = status;//clear them interrupts - uint32_t levels = GPI; - if(status == 0 || interrupt_reg == 0) return; - ETS_GPIO_INTR_DISABLE(); - int i = 0; - uint32_t changedbits = status & interrupt_reg; - while(changedbits){ - while(!(changedbits & (1 << i))) i++; - changedbits &= ~(1 << i); - interrupt_handler_t *handler = &interrupt_handlers[i]; - if (handler->fn && - (handler->mode == CHANGE || - (handler->mode & 1) == !!(levels & (1 << i)))) { - // to make ISR compatible to Arduino AVR model where interrupts are disabled - // we disable them before we call the client ISR - esp8266::InterruptLock irqLock; // stop other interrupts - if (handler->functional) - { - ArgStructure* localArg = (ArgStructure*)handler->arg; - if (localArg && localArg->interruptInfo) - { - localArg->interruptInfo->pin = i; - localArg->interruptInfo->value = __digitalRead(i); - localArg->interruptInfo->micro = micros(); - } - } - if (handler->arg) - { - ((voidFuncPtrArg)handler->fn)(handler->arg); - } - else - { - handler->fn(); - } - } + interrupt_handler_t() { + reset(); } - ETS_GPIO_INTR_ENABLE(); -} -extern void cleanupFunctional(void* arg); + ~interrupt_handler_t() { + reset(); + } -static void set_interrupt_handlers(uint8_t pin, voidFuncPtr userFunc, void* arg, uint8_t mode, bool functional) + void reset() { + if (obj) { + delete obj; + obj = nullptr; + } + fn = nullptr; + mode = 0; + } + + voidFuncPtr fn; + voidFuncObj* obj; + uint8_t mode; +}; + +static interrupt_handler_t interrupt_handlers[16]; +static uint32_t interrupt_reg = 0; + +void IRAM_ATTR interrupt_handler(void * /*arg*/, void * /*frame*/); + +static void set_interrupt_handlers(uint8_t pin, voidFuncPtr userFunc, uint8_t mode) { interrupt_handler_t* handler = &interrupt_handlers[pin]; + handler->reset(); + handler->mode = mode; handler->fn = userFunc; - if (handler->functional && handler->arg) // Clean when new attach without detach - { - cleanupFunctional(handler->arg); - } - handler->arg = arg; - handler->functional = functional; } -extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void* arg, int mode, bool functional) +static void set_interrupt_handlers(uint8_t pin, voidFuncObj&& userFunc, uint8_t mode) { - // #5780 - // https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map - if ((uint32_t)userFunc >= 0x40200000) - { - // ISR not in IRAM - ::printf((PGM_P)F("ISR not in IRAM!\r\n")); - abort(); - } + interrupt_handler_t* handler = &interrupt_handlers[pin]; + handler->reset(); + + handler->mode = mode; + handler->obj = new voidFuncObj(std::move(userFunc)); +} +template +void __attachInterrupt(uint8_t pin, T&& userFunc, int mode) { if(pin < 16) { ETS_GPIO_INTR_DISABLE(); - set_interrupt_handlers(pin, (voidFuncPtr)userFunc, arg, mode, functional); + set_interrupt_handlers(pin, std::forward(userFunc), mode); interrupt_reg |= (1 << pin); GPC(pin) &= ~(0xF << GPCI);//INT mode disabled GPIEC = (1 << pin); //Clear Interrupt for this pin @@ -213,19 +175,40 @@ extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, } } -extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void* arg, int mode) +extern "C" void __attachInterruptFunctional(uint8_t pin, voidFuncObj userFunc, int mode) +{ + // Assuming that .ld script magic had worked, and void() std::function operator()() is placed into IRAM + ets_printf("functional\n"); + __attachInterrupt(pin, std::move(userFunc), mode); +} + +extern "C" void __attachInterruptBasic(uint8_t pin, voidFuncPtr userFunc, int mode) { - __attachInterruptFunctionalArg(pin, userFunc, arg, mode, false); + // #5780 + // https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map + if ((uint32_t)userFunc >= 0x40200000) + { + // ISR not in IRAM + ::printf((PGM_P)F("ISR not in IRAM!\r\n")); + abort(); + } + + ets_printf("pointer\n"); + __attachInterrupt(pin, userFunc, mode); } -extern void IRAM_ATTR __detachInterrupt(uint8_t pin) { +extern "C" void __attachInterruptBasicParam(uint8_t pin, voidFuncParamPtr userFunc, int mode, void* param) { + __attachInterruptFunctional(pin, [param, userFunc]() { userFunc(param); }, mode); +} + +extern "C" void IRAM_ATTR __detachInterrupt(uint8_t pin) { if (pin < 16) { ETS_GPIO_INTR_DISABLE(); GPC(pin) &= ~(0xF << GPCI);//INT mode disabled GPIEC = (1 << pin); //Clear Interrupt for this pin interrupt_reg &= ~(1 << pin); - set_interrupt_handlers(pin, nullptr, nullptr, 0, false); + interrupt_handlers[pin].reset(); if (interrupt_reg) { ETS_GPIO_INTR_ENABLE(); @@ -233,19 +216,14 @@ extern void IRAM_ATTR __detachInterrupt(uint8_t pin) { } } -extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int mode) -{ - __attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, 0, mode, false); -} - -extern void __resetPins() { +extern "C" void __resetPins() { for (int i = 0; i <= 16; ++i) { if (!isFlashInterfacePin(i)) pinMode(i, INPUT); } } -extern void initPins() { +extern "C" void initPins() { //Disable UART interrupts system_set_os_print(0); U0IE = 0; @@ -254,12 +232,41 @@ extern void initPins() { resetPins(); } -extern void resetPins() __attribute__ ((weak, alias("__resetPins"))); -extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pinMode"))); -extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite"))); -extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead"), nothrow)); -extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt"))); -extern void attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void* arg, int mode) __attribute__((weak, alias("__attachInterruptArg"))); -extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); +void resetPins() __attribute__ ((weak, alias("__resetPins"))); +void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pinMode"))); +void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite"))); +int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead"), nothrow)); +void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterruptBasic"))); +void attachInterruptParam(uint8_t pin, voidFuncParamPtr handler, int mode, void* param) __attribute__((weak, alias("__attachInterruptBasicParam"))); +void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); -}; + +#pragma GCC optimize ("O2") + +void interrupt_handler(void * /*arg*/, void * /*frame*/) +{ + uint32_t status = GPIE; + GPIEC = status;//clear them interrupts + uint32_t levels = GPI; + if(status == 0 || interrupt_reg == 0) return; + ETS_GPIO_INTR_DISABLE(); + int i = 0; + uint32_t changedbits = status & interrupt_reg; + while (changedbits >= (1UL << i)) { + while (!(changedbits & (1UL << i))) { + ++i; + } + const interrupt_handler_t& handler = interrupt_handlers[i]; + if (handler.mode == CHANGE || (handler.mode & 1) == static_cast(levels & (1UL << i))) { + esp8266::InterruptLock irqLock; + if (__builtin_expect(handler.fn != nullptr, 1)) + { + handler.fn(); + } else { + (*handler.obj)(); + } + } + ++i; + } + ETS_GPIO_INTR_ENABLE(); +} From 9334ff019af6656c1a2ac1557ff635d65f0005ec Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Sun, 16 May 2021 21:41:27 +0300 Subject: [PATCH 2/9] oops --- cores/esp8266/core_esp8266_wiring_digital.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cores/esp8266/core_esp8266_wiring_digital.cpp b/cores/esp8266/core_esp8266_wiring_digital.cpp index 383012b89c..71243d2ad1 100644 --- a/cores/esp8266/core_esp8266_wiring_digital.cpp +++ b/cores/esp8266/core_esp8266_wiring_digital.cpp @@ -237,6 +237,7 @@ void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pinMode") void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite"))); int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead"), nothrow)); void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterruptBasic"))); +void attachInterrupt(uint8_t pin, voidFuncObj handler, int mode) __attribute__ ((weak, alias("__attachInterruptFunctional"))); void attachInterruptParam(uint8_t pin, voidFuncParamPtr handler, int mode, void* param) __attribute__((weak, alias("__attachInterruptBasicParam"))); void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); From 86fbf2d77f692aa29d572a5ef1a255aa5d1e6039 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Mon, 17 May 2021 02:14:44 +0300 Subject: [PATCH 3/9] make it apparent we are iterating bits --- cores/esp8266/core_esp8266_wiring_digital.cpp | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/cores/esp8266/core_esp8266_wiring_digital.cpp b/cores/esp8266/core_esp8266_wiring_digital.cpp index 71243d2ad1..df60b5acee 100644 --- a/cores/esp8266/core_esp8266_wiring_digital.cpp +++ b/cores/esp8266/core_esp8266_wiring_digital.cpp @@ -251,22 +251,29 @@ void interrupt_handler(void * /*arg*/, void * /*frame*/) uint32_t levels = GPI; if(status == 0 || interrupt_reg == 0) return; ETS_GPIO_INTR_DISABLE(); - int i = 0; + uint32_t i = 0; uint32_t changedbits = status & interrupt_reg; - while (changedbits >= (1UL << i)) { - while (!(changedbits & (1UL << i))) { - ++i; - } - const interrupt_handler_t& handler = interrupt_handlers[i]; - if (handler.mode == CHANGE || (handler.mode & 1) == static_cast(levels & (1UL << i))) { - esp8266::InterruptLock irqLock; - if (__builtin_expect(handler.fn != nullptr, 1)) + while (changedbits) { + if (changedbits & 1ul) { + const interrupt_handler_t& handler = interrupt_handlers[i]; + + auto level = levels & (1UL << i); + if ((handler.mode == CHANGE) + || ((handler.mode == HIGH) && level) + || ((handler.mode == LOW) && !level)) { + // to make ISR compatible to Arduino AVR model where interrupts are disabled + // we disable them before we call the user ISR function + esp8266::InterruptLock irqLock; + if (__builtin_expect(handler.fn != nullptr, 1)) + { handler.fn(); - } else { + } else { (*handler.obj)(); + } } } + changedbits = changedbits >> 1ul; ++i; } ETS_GPIO_INTR_ENABLE(); From 188f20162d0c7b62603586f30ac7494f5e178d80 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Mon, 17 May 2021 02:15:23 +0300 Subject: [PATCH 4/9] recover functionalinterrupt (?) --- cores/esp8266/FunctionalInterrupt.cpp | 26 ++++++++++++++++++++++++++ cores/esp8266/FunctionalInterrupt.h | 13 +++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 cores/esp8266/FunctionalInterrupt.cpp create mode 100644 cores/esp8266/FunctionalInterrupt.h diff --git a/cores/esp8266/FunctionalInterrupt.cpp b/cores/esp8266/FunctionalInterrupt.cpp new file mode 100644 index 0000000000..5b0d929684 --- /dev/null +++ b/cores/esp8266/FunctionalInterrupt.cpp @@ -0,0 +1,26 @@ +// Helpers to manage interrupts via schedule_function queue + +// TODO: isr may not be able to call code in flash when it is not present in ICACHE (functions, methods, ctors, etc. not marked IRAM_ATTR) +// TODO: does this std function copy really work? (same as old bind)... or is this just a happy accident? + +#include +#include +#include "Arduino.h" + +using ScheduledInterruptFunc = std::function; + +void attachScheduledInterrupt(uint8_t pin, ScheduledInterruptFunc func, int mode) +{ + if (pin < 16) { + detachInterrupt(pin); + attachInterrupt(pin, [pin, func = std::move(func)]() { + InterruptInfo info; + info.pin = pin; + info.value = digitalRead(pin); + info.micro = micros(); + schedule_function([func, info]() { + func(info); + }); + }, mode); + } +} diff --git a/cores/esp8266/FunctionalInterrupt.h b/cores/esp8266/FunctionalInterrupt.h new file mode 100644 index 0000000000..a24db29bf0 --- /dev/null +++ b/cores/esp8266/FunctionalInterrupt.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include + +struct InterruptInfo { + uint8_t pin = 0; + int8_t value = 0; + uint32_t micro = 0; +}; + +void attachScheduledInterrupt(uint8_t pin, std::function scheduledIntRoutine, int mode); From 2f0ab73055419518e9622942e0b21267bc2c8cb0 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Mon, 17 May 2021 02:15:58 +0300 Subject: [PATCH 5/9] add aforementioned magic --- tools/sdk/ld/eagle.app.v6.common.ld.h | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/sdk/ld/eagle.app.v6.common.ld.h b/tools/sdk/ld/eagle.app.v6.common.ld.h index 77c834ae19..b326f98aee 100644 --- a/tools/sdk/ld/eagle.app.v6.common.ld.h +++ b/tools/sdk/ld/eagle.app.v6.common.ld.h @@ -142,6 +142,7 @@ SECTIONS /* all functional callers are placed in IRAM (including SPI/IRQ callbacks/etc) here */ *(.text._ZNKSt8functionIF*EE*) /* std::function::operator()() const */ + *(.text._ZNSt17_Function_handlerIFvv*9_M_invoke*9_Any_data) /* std::function::_M_invoke */ } >iram1_0_seg :iram1_0_phdr .irom0.text : ALIGN(4) From 4b7262f8a5053471e7c53adf7bfd5bee94ff6352 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Tue, 18 May 2021 13:40:21 +0300 Subject: [PATCH 6/9] add back the attachInterruptArg --- cores/esp8266/Arduino.h | 1 + cores/esp8266/core_esp8266_wiring_digital.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 696631f523..fd2da4662b 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -184,6 +184,7 @@ uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); void attachInterrupt(uint8_t pin, void (*)(), int mode); void attachInterruptParam(uint8_t pin, void (*)(void*), int mode, void* param); +void attachInterruptArg(uint8_t pin, void (*)(void*), int mode, void* param); void detachInterrupt(uint8_t pin); void preinit(void); diff --git a/cores/esp8266/core_esp8266_wiring_digital.cpp b/cores/esp8266/core_esp8266_wiring_digital.cpp index df60b5acee..5319cb4b4b 100644 --- a/cores/esp8266/core_esp8266_wiring_digital.cpp +++ b/cores/esp8266/core_esp8266_wiring_digital.cpp @@ -239,6 +239,7 @@ int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead"), nothr void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterruptBasic"))); void attachInterrupt(uint8_t pin, voidFuncObj handler, int mode) __attribute__ ((weak, alias("__attachInterruptFunctional"))); void attachInterruptParam(uint8_t pin, voidFuncParamPtr handler, int mode, void* param) __attribute__((weak, alias("__attachInterruptBasicParam"))); +void attachInterruptArg(uint8_t pin, voidFuncParamPtr handler, int mode, void* param) __attribute__((weak, alias("__attachInterruptBasicParam"))); void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); From 112181b8df2176c411001f15d4f9bc6ee02fef05 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Tue, 18 May 2021 14:46:03 +0300 Subject: [PATCH 7/9] oops --- cores/esp8266/core_esp8266_wiring_digital.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cores/esp8266/core_esp8266_wiring_digital.cpp b/cores/esp8266/core_esp8266_wiring_digital.cpp index 5319cb4b4b..b7252959b4 100644 --- a/cores/esp8266/core_esp8266_wiring_digital.cpp +++ b/cores/esp8266/core_esp8266_wiring_digital.cpp @@ -260,8 +260,7 @@ void interrupt_handler(void * /*arg*/, void * /*frame*/) auto level = levels & (1UL << i); if ((handler.mode == CHANGE) - || ((handler.mode == HIGH) && level) - || ((handler.mode == LOW) && !level)) + || ((handler->mode & 1) == !!(levels & (1 << i)))) { // to make ISR compatible to Arduino AVR model where interrupts are disabled // we disable them before we call the user ISR function From b953834f7155385ae79bbe6f764a484143cf37b4 Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Tue, 18 May 2021 16:15:03 +0300 Subject: [PATCH 8/9] fixup! oops --- cores/esp8266/core_esp8266_wiring_digital.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/core_esp8266_wiring_digital.cpp b/cores/esp8266/core_esp8266_wiring_digital.cpp index b7252959b4..21950878d6 100644 --- a/cores/esp8266/core_esp8266_wiring_digital.cpp +++ b/cores/esp8266/core_esp8266_wiring_digital.cpp @@ -260,7 +260,7 @@ void interrupt_handler(void * /*arg*/, void * /*frame*/) auto level = levels & (1UL << i); if ((handler.mode == CHANGE) - || ((handler->mode & 1) == !!(levels & (1 << i)))) + || ((handler.mode & 1ul) == !!(level))) { // to make ISR compatible to Arduino AVR model where interrupts are disabled // we disable them before we call the user ISR function From 097cd94b0f2570e49530795a07689362d01b35bd Mon Sep 17 00:00:00 2001 From: Maxim Prokhorov Date: Tue, 18 May 2021 16:20:25 +0300 Subject: [PATCH 9/9] other way around --- cores/esp8266/Arduino.h | 2 +- cores/esp8266/core_esp8266_wiring_digital.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index fd2da4662b..f9abf75dc4 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -184,7 +184,7 @@ uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); void attachInterrupt(uint8_t pin, void (*)(), int mode); void attachInterruptParam(uint8_t pin, void (*)(void*), int mode, void* param); -void attachInterruptArg(uint8_t pin, void (*)(void*), int mode, void* param); +void attachInterruptArg(uint8_t pin, void (*)(void*), void* param, int mode); void detachInterrupt(uint8_t pin); void preinit(void); diff --git a/cores/esp8266/core_esp8266_wiring_digital.cpp b/cores/esp8266/core_esp8266_wiring_digital.cpp index 21950878d6..6db4630145 100644 --- a/cores/esp8266/core_esp8266_wiring_digital.cpp +++ b/cores/esp8266/core_esp8266_wiring_digital.cpp @@ -239,9 +239,11 @@ int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead"), nothr void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterruptBasic"))); void attachInterrupt(uint8_t pin, voidFuncObj handler, int mode) __attribute__ ((weak, alias("__attachInterruptFunctional"))); void attachInterruptParam(uint8_t pin, voidFuncParamPtr handler, int mode, void* param) __attribute__((weak, alias("__attachInterruptBasicParam"))); -void attachInterruptArg(uint8_t pin, voidFuncParamPtr handler, int mode, void* param) __attribute__((weak, alias("__attachInterruptBasicParam"))); void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); +void attachInterruptArg(uint8_t pin, voidFuncParamPtr handler, void* param, int mode) { + attachInterruptParam(pin, handler, mode, param); +} #pragma GCC optimize ("O2")