Skip to content

Commit

Permalink
Invented void* detachInterruptArg() that returns the argument given i…
Browse files Browse the repository at this point in the history
…n attachInterruptArg().

This is sufficient for resource management - the function has static duration anyway.
  • Loading branch information
dok-net committed May 3, 2019
1 parent e7013ba commit 9e239ec
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 68 deletions.
3 changes: 2 additions & 1 deletion cores/esp8266/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,9 @@ 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 attachInterruptArg(uint8_t pin, void (*)(void*), void * arg, int mode);
void detachInterrupt(uint8_t pin);
void attachInterruptArg(uint8_t pin, void (*)(void*), void* arg, int mode);
void* detachInterruptArg(uint8_t pin);

void preinit(void);
void setup(void);
Expand Down
11 changes: 7 additions & 4 deletions cores/esp8266/core_esp8266_wiring_digital.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,10 @@ extern void __detachInterrupt(uint8_t pin) {
}
}

extern interrupt_handler_t* __getInterruptHandler(uint8_t pin) {
return (pin < 16) ? &interrupt_handlers[pin] : nullptr;
extern void* __detachInterruptArg(uint8_t pin) {
void* arg = (pin < 16) ? interrupt_handlers[pin].arg : nullptr;
__detachInterrupt(pin);
return arg;
}

void initPins() {
Expand All @@ -215,7 +217,8 @@ extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pi
extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite")));
extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead")));
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")));
extern void detachInterrupt(uint8_t pin) __attribute__((weak, alias("__detachInterrupt")));
extern void attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void* arg, int mode) __attribute__((weak, alias("__attachInterruptArg")));
extern void* detachInterruptArg(uint8_t pin) __attribute__((weak, alias("__detachInterruptArg")));

};
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,6 @@
#include <Schedule.h>
#include "Arduino.h"

#if defined(ESP8266)

// Duplicate typedefs from core_esp8266_wiring_digital.cpp
// Keep in sync
typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrArg)(void*);

typedef struct {
uint8_t mode;
voidFuncPtr fn;
void* arg;
} interrupt_handler_t;

// Helper functions for Functional interrupt routines
extern "C" interrupt_handler_t* __getInterruptHandler(uint8_t pin);

#elif defined(ESP32)

// Duplicate typedefs from esp32-hal-gpio.c
// Keep in sync
typedef void (*voidFuncPtr)(void);
typedef void (*voidFuncPtrArg)(void*);
typedef struct {
voidFuncPtr fn;
void* arg;
} InterruptHandle_t;

// Helper functions for Functional interrupt routines
extern "C" InterruptHandle_t* __getInterruptHandler(uint8_t pin);

#endif

void ICACHE_RAM_ATTR interruptFunctional(void* arg)
{
ArgStructure* localArg = static_cast<ArgStructure*>(arg);
Expand All @@ -44,32 +12,30 @@ void ICACHE_RAM_ATTR interruptFunctional(void* arg)
}
if (localArg->functionInfo->reqScheduledFunction)
{
schedule_function(std::bind(localArg->functionInfo->reqScheduledFunction,InterruptInfo(*(localArg->interruptInfo))));
schedule_function(
[reqScheduledFunction = localArg->functionInfo->reqScheduledFunction,
interruptInfo = *localArg->interruptInfo]() { reqScheduledFunction(interruptInfo); });
}
if (localArg->functionInfo->reqFunction)
{
localArg->functionInfo->reqFunction();
}
}

void cleanupFunctional(void* arg)
{
ArgStructure* localArg = static_cast<ArgStructure*>(arg);
delete localArg;
}
void cleanupFunctional(void* arg)
{
ArgStructure* localArg = static_cast<ArgStructure*>(arg);
delete localArg;
}

void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode)
{
// use the local interrupt routine which takes the ArgStructure as argument

#if defined(ESP8266)
interrupt_handler_t* handler = __getInterruptHandler(pin);
#elif defined(ESP32)
InterruptHandle_t* handler = __getInterruptHandler(pin);
#endif
if (handler->arg)
void* localArg = detachInterruptArg(pin);
if (localArg)
{
cleanupFunctional(handler->arg);
cleanupFunctional(localArg);
}

FunctionInfo* fi = new FunctionInfo;
Expand All @@ -78,19 +44,15 @@ void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode
ArgStructure* as = new ArgStructure;
as->functionInfo = fi;

::attachInterruptArg (pin, static_cast<voidFuncPtrArg>(interruptFunctional), as, mode);
attachInterruptArg (pin, interruptFunctional, as, mode);
}

void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
{
#if defined(ESP8266)
interrupt_handler_t* handler = __getInterruptHandler(pin);
#elif defined(ESP32)
InterruptHandle_t* handler = __getInterruptHandler(pin);
#endif
if (handler->arg)
void* localArg = detachInterruptArg(pin);
if (localArg)
{
cleanupFunctional(handler->arg);
cleanupFunctional(localArg);
}

InterruptInfo* ii = new InterruptInfo(pin);
Expand All @@ -102,20 +64,14 @@ void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> sc
as->interruptInfo = ii;
as->functionInfo = fi;

::attachInterruptArg (pin, static_cast<voidFuncPtrArg>(interruptFunctional), as, mode);
attachInterruptArg(pin, interruptFunctional, as, mode);
}

void detachFunctionalInterrupt(uint8_t pin)
{
#if defined(ESP8266)
interrupt_handler_t* handler = __getInterruptHandler(pin);
#elif defined(ESP32)
InterruptHandle_t* handler = __getInterruptHandler(pin);
#endif
if (handler->arg)
void* localArg = detachInterruptArg(pin);
if (localArg)
{
cleanupFunctional(handler->arg);
cleanupFunctional(localArg);
}
::detachInterrupt (pin);
}

0 comments on commit 9e239ec

Please sign in to comment.