Skip to content

Commit f5d8dc3

Browse files
committed
Support extra parameter on `attachInterrupt()
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. This is a port of arduino/Arduino#4519, but for Arduino Due.
1 parent 2a17b0d commit f5d8dc3

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

cores/arduino/WInterrupts.c

+29-10
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,18 @@
1818

1919
#include "WInterrupts.h"
2020

21-
typedef void (*interruptCB)(void);
21+
typedef void (*interruptCB)(void*);
2222

2323
static interruptCB callbacksPioA[32];
2424
static interruptCB callbacksPioB[32];
2525
static interruptCB callbacksPioC[32];
2626
static interruptCB callbacksPioD[32];
2727

28+
static void* callbackParamsPioA[32];
29+
static void* callbackParamsPioB[32];
30+
static void* callbackParamsPioC[32];
31+
static void* callbackParamsPioD[32];
32+
2833
/* Configure PIO interrupt sources */
2934
static void __initialize() {
3035
int i;
@@ -60,8 +65,17 @@ static void __initialize() {
6065
NVIC_EnableIRQ(PIOD_IRQn);
6166
}
6267

68+
void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode) {
69+
// THIS IMPLEMENTATION IS NOT PORTABLE!
70+
//
71+
// On ARM's calling convention, calling a function with more arguments than it declares
72+
// is OK - The extra parameter is ignored and causes no harm
73+
//
74+
// This implementation takes advantage of it to support callbacks with and without parameters with minimum overhead.
75+
attachInterruptParam(pin, (void (*)(void*))callback, mode, NULL);
76+
}
6377

64-
void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode)
78+
void attachInterruptParam(uint32_t pin, void (*callback)(void*), uint32_t mode, void* param)
6579
{
6680
static int enabled = 0;
6781
if (!enabled) {
@@ -79,14 +93,19 @@ void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode)
7993
;
8094

8195
// Set callback function
82-
if (pio == PIOA)
96+
if (pio == PIOA) {
8397
callbacksPioA[pos] = callback;
84-
if (pio == PIOB)
98+
callbackParamsPioA[pos] = param;
99+
} else if (pio == PIOB) {
85100
callbacksPioB[pos] = callback;
86-
if (pio == PIOC)
101+
callbackParamsPioB[pos] = param;
102+
} else if (pio == PIOC) {
87103
callbacksPioC[pos] = callback;
88-
if (pio == PIOD)
104+
callbackParamsPioC[pos] = param;
105+
} else if (pio == PIOD) {
89106
callbacksPioD[pos] = callback;
107+
callbackParamsPioD[pos] = param;
108+
}
90109

91110
// Configure the interrupt mode
92111
if (mode == CHANGE) {
@@ -139,7 +158,7 @@ void PIOA_Handler(void) {
139158
while((leading_zeros=__CLZ(isr))<32)
140159
{
141160
uint8_t pin=32-leading_zeros-1;
142-
if(callbacksPioA[pin]) callbacksPioA[pin]();
161+
if(callbacksPioA[pin]) callbacksPioA[pin](callbackParamsPioA[pin]);
143162
isr=isr&(~(1<<pin));
144163
}
145164
}
@@ -150,7 +169,7 @@ void PIOB_Handler(void) {
150169
while((leading_zeros=__CLZ(isr))<32)
151170
{
152171
uint8_t pin=32-leading_zeros-1;
153-
if(callbacksPioB[pin]) callbacksPioB[pin]();
172+
if(callbacksPioB[pin]) callbacksPioB[pin](callbackParamsPioB[pin]);
154173
isr=isr&(~(1<<pin));
155174
}
156175
}
@@ -161,7 +180,7 @@ void PIOC_Handler(void) {
161180
while((leading_zeros=__CLZ(isr))<32)
162181
{
163182
uint8_t pin=32-leading_zeros-1;
164-
if(callbacksPioC[pin]) callbacksPioC[pin]();
183+
if(callbacksPioC[pin]) callbacksPioC[pin](callbackParamsPioC[pin]);
165184
isr=isr&(~(1<<pin));
166185
}
167186
}
@@ -172,7 +191,7 @@ void PIOD_Handler(void) {
172191
while((leading_zeros=__CLZ(isr))<32)
173192
{
174193
uint8_t pin=32-leading_zeros-1;
175-
if(callbacksPioD[pin]) callbacksPioD[pin]();
194+
if(callbacksPioD[pin]) callbacksPioD[pin](callbackParamsPioD[pin]);
176195
isr=isr&(~(1<<pin));
177196
}
178197
}

cores/arduino/WInterrupts.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extern "C" {
2626
#endif
2727

2828
void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode);
29-
29+
void attachInterruptParam(uint32_t pin, void (*callback)(void*), uint32_t mode, void* param);
3030
void detachInterrupt(uint32_t pin);
3131

3232
#ifdef __cplusplus

0 commit comments

Comments
 (0)