Skip to content

Commit 2c6ca16

Browse files
committed
Properly check for "functional" ISRs and expose C-style attachInterruptArg
1 parent 7c184f4 commit 2c6ca16

File tree

3 files changed

+70
-53
lines changed

3 files changed

+70
-53
lines changed

cores/esp8266/Arduino.h

+1
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
218218

219219
void attachInterrupt(uint8_t pin, void (*)(void), int mode);
220220
void detachInterrupt(uint8_t pin);
221+
void attachInterruptArg(uint8_t pin, void (*)(void*), void* arg, int mode);
221222

222223
void preinit(void);
223224
void setup(void);

cores/esp8266/FunctionalInterrupt.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ typedef void (*voidFuncPtr)(void);
77
typedef void (*voidFuncPtrArg)(void*);
88

99
// Helper functions for Functional interrupt routines
10-
extern "C" void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFunc, void*fp , int mode);
10+
extern "C" void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtr userFunc, void*fp, int mode, bool functional);
1111

1212

1313
void ICACHE_RAM_ATTR interruptFunctional(void* arg)
@@ -47,7 +47,7 @@ void attachInterrupt(uint8_t pin, std::function<void(void)> intRoutine, int mode
4747
as->interruptInfo = ii;
4848
as->functionInfo = fi;
4949

50-
__attachInterruptArg (pin, (voidFuncPtr)interruptFunctional, as, mode);
50+
__attachInterruptFunctionalArg(pin, (voidFuncPtr)interruptFunctional, as, mode, true);
5151
}
5252

5353
void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> scheduledIntRoutine, int mode)
@@ -61,5 +61,5 @@ void attachScheduledInterrupt(uint8_t pin, std::function<void(InterruptInfo)> sc
6161
as->interruptInfo = ii;
6262
as->functionInfo = fi;
6363

64-
__attachInterruptArg (pin, (voidFuncPtr)interruptFunctional, as, mode);
64+
__attachInterruptFunctionalArg(pin, (voidFuncPtr)interruptFunctional, as, mode, true);
6565
}

cores/esp8266/core_esp8266_wiring_digital.cpp

+66-50
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,9 @@ typedef void (*voidFuncPtrArg)(void*);
109109

110110
typedef struct {
111111
uint8_t mode;
112-
void (*fn)(void);
112+
voidFuncPtr fn;
113113
void * arg;
114+
bool functional;
114115
} interrupt_handler_t;
115116

116117
//duplicate from functionalInterrupt.h keep in sync
@@ -125,11 +126,11 @@ typedef struct {
125126
void* functionInfo;
126127
} ArgStructure;
127128

128-
static interrupt_handler_t interrupt_handlers[16];
129+
static interrupt_handler_t interrupt_handlers[16] = { {0, 0, 0, 0}, };
129130
static uint32_t interrupt_reg = 0;
130131

131-
void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
132-
(void) arg;
132+
void ICACHE_RAM_ATTR interrupt_handler(void*)
133+
{
133134
uint32_t status = GPIE;
134135
GPIEC = status;//clear them interrupts
135136
uint32_t levels = GPI;
@@ -144,34 +145,37 @@ void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
144145
if (handler->fn &&
145146
(handler->mode == CHANGE ||
146147
(handler->mode & 1) == !!(levels & (1 << i)))) {
147-
// to make ISR compatible to Arduino AVR model where interrupts are disabled
148-
// we disable them before we call the client ISR
149-
uint32_t savedPS = xt_rsil(15); // stop other interrupts
150-
ArgStructure* localArg = (ArgStructure*)handler->arg;
151-
if (localArg && localArg->interruptInfo)
152-
{
153-
localArg->interruptInfo->pin = i;
154-
localArg->interruptInfo->value = __digitalRead(i);
155-
localArg->interruptInfo->micro = micros();
156-
}
157-
if (handler->arg)
158-
{
159-
((voidFuncPtrArg)handler->fn)(handler->arg);
160-
}
161-
else
162-
{
163-
handler->fn();
148+
// to make ISR compatible to Arduino AVR model where interrupts are disabled
149+
// we disable them before we call the client ISR
150+
uint32_t savedPS = xt_rsil(15); // stop other interrupts
151+
if (handler->functional)
152+
{
153+
ArgStructure* localArg = (ArgStructure*)handler->arg;
154+
if (localArg && localArg->interruptInfo)
155+
{
156+
localArg->interruptInfo->pin = i;
157+
localArg->interruptInfo->value = __digitalRead(i);
158+
localArg->interruptInfo->micro = micros();
159+
}
160+
}
161+
if (handler->arg)
162+
{
163+
((voidFuncPtrArg)handler->fn)(handler->arg);
164+
}
165+
else
166+
{
167+
handler->fn();
168+
}
169+
xt_wsr_ps(savedPS);
164170
}
165-
xt_wsr_ps(savedPS);
166-
}
167171
}
168172
ETS_GPIO_INTR_ENABLE();
169173
}
170174

171175
extern void cleanupFunctional(void* arg);
172176

173-
extern void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFunc, void *arg, int mode) {
174-
177+
extern void __attachInterruptFunctionalArg(uint8_t pin, voidFuncPtrArg userFunc, void* arg, int mode, bool functional)
178+
{
175179
// #5780
176180
// https://github.com/esp8266/esp8266-wiki/wiki/Memory-Map
177181
if ((uint32_t)userFunc >= 0x40200000)
@@ -183,14 +187,15 @@ extern void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFu
183187

184188
if(pin < 16) {
185189
ETS_GPIO_INTR_DISABLE();
186-
interrupt_handler_t *handler = &interrupt_handlers[pin];
190+
interrupt_handler_t* handler = &interrupt_handlers[pin];
187191
handler->mode = mode;
188-
handler->fn = userFunc;
189-
if (handler->arg) // Clean when new attach without detach
190-
{
191-
cleanupFunctional(handler->arg);
192-
}
192+
handler->fn = (voidFuncPtr)userFunc;
193+
if (handler->functional && handler->arg) // Clean when new attach without detach
194+
{
195+
cleanupFunctional(handler->arg);
196+
}
193197
handler->arg = arg;
198+
handler->functional = functional;
194199
interrupt_reg |= (1 << pin);
195200
GPC(pin) &= ~(0xF << GPCI);//INT mode disabled
196201
GPIEC = (1 << pin); //Clear Interrupt for this pin
@@ -200,28 +205,38 @@ extern void ICACHE_RAM_ATTR __attachInterruptArg(uint8_t pin, voidFuncPtr userFu
200205
}
201206
}
202207

203-
extern void ICACHE_RAM_ATTR __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int mode )
208+
extern void __attachInterruptArg(uint8_t pin, voidFuncPtrArg userFunc, void* arg, int mode)
204209
{
205-
__attachInterruptArg (pin, userFunc, 0, mode);
210+
__attachInterruptFunctionalArg(pin, userFunc, arg, mode, false);
206211
}
207212

208-
extern void ICACHE_RAM_ATTR __detachInterrupt(uint8_t pin) {
209-
if(pin < 16) {
210-
ETS_GPIO_INTR_DISABLE();
211-
GPC(pin) &= ~(0xF << GPCI);//INT mode disabled
212-
GPIEC = (1 << pin); //Clear Interrupt for this pin
213-
interrupt_reg &= ~(1 << pin);
214-
interrupt_handler_t *handler = &interrupt_handlers[pin];
215-
handler->mode = 0;
216-
handler->fn = 0;
217-
if (handler->arg)
218-
{
219-
cleanupFunctional(handler->arg);
220-
}
221-
handler->arg = 0;
222-
if (interrupt_reg)
223-
ETS_GPIO_INTR_ENABLE();
224-
}
213+
extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int mode)
214+
{
215+
__attachInterruptFunctionalArg(pin, (voidFuncPtrArg)userFunc, 0, mode, false);
216+
}
217+
218+
extern void ICACHE_RAM_ATTR __detachInterrupt(uint8_t pin)
219+
{
220+
if (pin < 16)
221+
{
222+
ETS_GPIO_INTR_DISABLE();
223+
GPC(pin) &= ~(0xF << GPCI);//INT mode disabled
224+
GPIEC = (1 << pin); //Clear Interrupt for this pin
225+
interrupt_reg &= ~(1 << pin);
226+
interrupt_handler_t* handler = &interrupt_handlers[pin];
227+
handler->mode = 0;
228+
handler->fn = 0;
229+
if (handler->functional && handler->arg)
230+
{
231+
cleanupFunctional(handler->arg);
232+
}
233+
handler->arg = 0;
234+
handler->functional = false;
235+
if (interrupt_reg)
236+
{
237+
ETS_GPIO_INTR_ENABLE();
238+
}
239+
}
225240
}
226241

227242
void initPins() {
@@ -243,6 +258,7 @@ extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pi
243258
extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite")));
244259
extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead")));
245260
extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt")));
261+
extern void attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void* arg, int mode) __attribute__((weak, alias("__attachInterruptArg")));
246262
extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt")));
247263

248264
};

0 commit comments

Comments
 (0)