Skip to content

Commit 91a68d9

Browse files
author
Paulo Costa
committed
Support extra parameter on attachInterrupt()
When writing an arduino library, it is difficult to connect interrupt handlers with the component instance that should be notified. In C, the common pattern to fix this is to specifying a `void*` parameter with the callback, where the listener can store any context necessary. This patch adds the new function `attachInterruptParam()` to implement this pattern.
1 parent 36c9419 commit 91a68d9

File tree

3 files changed

+36
-59
lines changed

3 files changed

+36
-59
lines changed

hardware/arduino/avr/cores/arduino/Arduino.h

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
140140
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
141141

142142
void attachInterrupt(uint8_t, void (*)(void), int mode);
143+
void attachInterruptParam(uint8_t, void (*)(void*), int mode, void* param);
143144
void detachInterrupt(uint8_t);
144145

145146
void setup(void);

hardware/arduino/avr/cores/arduino/WInterrupts.c

+34-59
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@
3535
static void nothing(void) {
3636
}
3737

38-
static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
38+
static void compatFunc(void* realCallback) {
39+
voidFuncPtr f = realCallback;
40+
f();
41+
}
42+
43+
static volatile voidFuncPtrParam intFunc[EXTERNAL_NUM_INTERRUPTS] = {
3944
#if EXTERNAL_NUM_INTERRUPTS > 8
4045
#warning There are more than 8 external interrupts. Some callbacks may not be initialized.
4146
nothing,
@@ -65,11 +70,17 @@ static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
6570
nothing,
6671
#endif
6772
};
73+
static volatile void* intFuncParam[EXTERNAL_NUM_INTERRUPTS];
6874
// volatile static voidFuncPtr twiIntFunc;
6975

7076
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
77+
attachInterruptParam(interruptNum, compatFunc, mode, userFunc);
78+
}
79+
80+
void attachInterruptParam(uint8_t interruptNum, void (*userFunc)(void*), int mode, void* param) {
7181
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
7282
intFunc[interruptNum] = userFunc;
83+
intFuncParam[interruptNum] = param;
7384

7485
// Configure the interrupt mode (trigger on low input, any change, rising
7586
// edge, or falling edge). The mode constants were chosen to correspond
@@ -271,6 +282,7 @@ void detachInterrupt(uint8_t interruptNum) {
271282
}
272283

273284
intFunc[interruptNum] = nothing;
285+
intFuncParam[interruptNum] = 0;
274286
}
275287
}
276288

@@ -280,75 +292,38 @@ void attachInterruptTwi(void (*userFunc)(void) ) {
280292
}
281293
*/
282294

283-
#if defined(__AVR_ATmega32U4__)
284-
ISR(INT0_vect) {
285-
intFunc[EXTERNAL_INT_0]();
286-
}
287-
288-
ISR(INT1_vect) {
289-
intFunc[EXTERNAL_INT_1]();
290-
}
291-
292-
ISR(INT2_vect) {
293-
intFunc[EXTERNAL_INT_2]();
294-
}
295+
#define IMPLEMENT_ISR(vect, interrupt) \
296+
ISR(vect) { \
297+
intFunc[interrupt](intFuncParam [interrupt]); \
298+
}
295299

296-
ISR(INT3_vect) {
297-
intFunc[EXTERNAL_INT_3]();
298-
}
300+
#if defined(__AVR_ATmega32U4__)
299301

300-
ISR(INT6_vect) {
301-
intFunc[EXTERNAL_INT_4]();
302-
}
302+
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
303+
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
304+
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
305+
IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_3)
306+
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_4)
303307

304308
#elif defined(EICRA) && defined(EICRB)
305309

306-
ISR(INT0_vect) {
307-
intFunc[EXTERNAL_INT_2]();
308-
}
309310

310-
ISR(INT1_vect) {
311-
intFunc[EXTERNAL_INT_3]();
312-
}
313-
314-
ISR(INT2_vect) {
315-
intFunc[EXTERNAL_INT_4]();
316-
}
317-
318-
ISR(INT3_vect) {
319-
intFunc[EXTERNAL_INT_5]();
320-
}
321-
322-
ISR(INT4_vect) {
323-
intFunc[EXTERNAL_INT_0]();
324-
}
325-
326-
ISR(INT5_vect) {
327-
intFunc[EXTERNAL_INT_1]();
328-
}
329-
330-
ISR(INT6_vect) {
331-
intFunc[EXTERNAL_INT_6]();
332-
}
333-
334-
ISR(INT7_vect) {
335-
intFunc[EXTERNAL_INT_7]();
336-
}
311+
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_2)
312+
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_3)
313+
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_4)
314+
IMPLEMENT_ISR(INT3_vect, EXTERNAL_INT_5)
315+
IMPLEMENT_ISR(INT4_vect, EXTERNAL_INT_0)
316+
IMPLEMENT_ISR(INT5_vect, EXTERNAL_INT_1)
317+
IMPLEMENT_ISR(INT6_vect, EXTERNAL_INT_6)
318+
IMPLEMENT_ISR(INT7_vect, EXTERNAL_INT_7)
337319

338320
#else
339321

340-
ISR(INT0_vect) {
341-
intFunc[EXTERNAL_INT_0]();
342-
}
343-
344-
ISR(INT1_vect) {
345-
intFunc[EXTERNAL_INT_1]();
346-
}
322+
IMPLEMENT_ISR(INT0_vect, EXTERNAL_INT_0)
323+
IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
347324

348325
#if defined(EICRA) && defined(ISC20)
349-
ISR(INT2_vect) {
350-
intFunc[EXTERNAL_INT_2]();
351-
}
326+
IMPLEMENT_ISR(INT2_vect, EXTERNAL_INT_2)
352327
#endif
353328

354329
#endif

hardware/arduino/avr/cores/arduino/wiring_private.h

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, u
6464
#endif
6565

6666
typedef void (*voidFuncPtr)(void);
67+
typedef void (*voidFuncPtrParam)(void*);
6768

6869
#ifdef __cplusplus
6970
} // extern "C"

0 commit comments

Comments
 (0)