Skip to content

Commit 3c6d386

Browse files
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 5755dde commit 3c6d386

File tree

3 files changed

+17
-5
lines changed

3 files changed

+17
-5
lines changed

Diff for: cores/arduino/Arduino.h

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
148148
uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
149149

150150
void attachInterrupt(uint8_t, void (*)(void), int mode);
151+
void attachInterruptParam(uint8_t, void (*)(void*), int mode, void* param);
151152
void detachInterrupt(uint8_t);
152153

153154
void setup(void);

Diff for: cores/arduino/WInterrupts.c

+16-3
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@
3232

3333
#include "wiring_private.h"
3434

35-
static void nothing(void) {
35+
typedef void (*voidFuncPtrParam)(void*);
36+
37+
static void nothing(void* arg) {
3638
}
3739

38-
static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
40+
static volatile voidFuncPtrParam intFunc[EXTERNAL_NUM_INTERRUPTS] = {
3941
#if EXTERNAL_NUM_INTERRUPTS > 8
4042
#warning There are more than 8 external interrupts. Some callbacks may not be initialized.
4143
nothing,
@@ -65,10 +67,20 @@ static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
6567
nothing,
6668
#endif
6769
};
70+
static volatile void* intFuncParam[EXTERNAL_NUM_INTERRUPTS];
6871

6972
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
73+
// To support callbacks with and without parameters with minimum overhead,
74+
// this relies on that fact that in C calling conventions extra argument on a
75+
// function call are safely ignored without side-effects.
76+
77+
attachInterruptParam(interruptNum, (voidFuncPtrParam)userFunc, mode, NULL);
78+
}
79+
80+
void attachInterruptParam(uint8_t interruptNum, voidFuncPtrParam userFunc, int mode, void* param) {
7081
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
7182
intFunc[interruptNum] = userFunc;
83+
intFuncParam[interruptNum] = param;
7284

7385
// Configure the interrupt mode (trigger on low input, any change, rising
7486
// edge, or falling edge). The mode constants were chosen to correspond
@@ -270,13 +282,14 @@ void detachInterrupt(uint8_t interruptNum) {
270282
}
271283

272284
intFunc[interruptNum] = nothing;
285+
intFuncParam[interruptNum] = NULL;
273286
}
274287
}
275288

276289

277290
#define IMPLEMENT_ISR(vect, interrupt) \
278291
ISR(vect) { \
279-
intFunc[interrupt](); \
292+
intFunc[interrupt]((void*)intFuncParam[interrupt]); \
280293
}
281294

282295
#if defined(__AVR_ATmega32U4__)

Diff for: cores/arduino/wiring_private.h

-2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, u
6363
#define EXTERNAL_NUM_INTERRUPTS 2
6464
#endif
6565

66-
typedef void (*voidFuncPtr)(void);
67-
6866
#ifdef __cplusplus
6967
} // extern "C"
7068
#endif

0 commit comments

Comments
 (0)