diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h
index 09c144895..6a42e4195 100644
--- a/cores/arduino/Arduino.h
+++ b/cores/arduino/Arduino.h
@@ -148,6 +148,7 @@ 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, void (*)(void), int mode);
+void attachInterruptParam(uint8_t, void (*)(void*), int mode, void* param);
 void detachInterrupt(uint8_t);
 
 void setup(void);
diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c
index ac72dda44..c6119075a 100644
--- a/cores/arduino/WInterrupts.c
+++ b/cores/arduino/WInterrupts.c
@@ -32,10 +32,12 @@
 
 #include "wiring_private.h"
 
-static void nothing(void) {
+typedef void (*voidFuncPtrParam)(void*);
+
+static void nothing(void* arg) {
 }
 
-static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
+static volatile voidFuncPtrParam intFunc[EXTERNAL_NUM_INTERRUPTS] = {
 #if EXTERNAL_NUM_INTERRUPTS > 8
     #warning There are more than 8 external interrupts. Some callbacks may not be initialized.
     nothing,
@@ -65,10 +67,20 @@ static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = {
     nothing,
 #endif
 };
+static volatile void* intFuncParam[EXTERNAL_NUM_INTERRUPTS];
 
 void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
+  // To support callbacks with and without parameters with minimum overhead,
+  // this relies on that fact that in C calling conventions extra argument on a
+  // function call are safely ignored without side-effects.
+
+  attachInterruptParam(interruptNum, (voidFuncPtrParam)userFunc, mode, NULL);
+}
+
+ void attachInterruptParam(uint8_t interruptNum, voidFuncPtrParam userFunc, int mode, void* param) {
   if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
     intFunc[interruptNum] = userFunc;
+    intFuncParam[interruptNum] = param;
     
     // Configure the interrupt mode (trigger on low input, any change, rising
     // edge, or falling edge).  The mode constants were chosen to correspond
@@ -270,13 +282,14 @@ void detachInterrupt(uint8_t interruptNum) {
     }
       
     intFunc[interruptNum] = nothing;
+    intFuncParam[interruptNum] = NULL;
   }
 }
 
 
 #define IMPLEMENT_ISR(vect, interrupt) \
   ISR(vect) { \
-    intFunc[interrupt](); \
+    intFunc[interrupt]((void*)intFuncParam[interrupt]); \
   }
 
 #if defined(__AVR_ATmega32U4__)
diff --git a/cores/arduino/wiring_private.h b/cores/arduino/wiring_private.h
index a277b1484..b49c6f203 100644
--- a/cores/arduino/wiring_private.h
+++ b/cores/arduino/wiring_private.h
@@ -63,8 +63,6 @@ uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, u
 #define EXTERNAL_NUM_INTERRUPTS 2
 #endif
 
-typedef void (*voidFuncPtr)(void);
-
 #ifdef __cplusplus
 } // extern "C"
 #endif