aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAditya Gaddam <adityagaddam@gmail.com>2012-08-31 14:19:57 -0400
committerAditya Gaddam <adityagaddam@gmail.com>2012-08-31 14:19:57 -0400
commitf6f2601213625f0a12a3a93c5a64918619d8adc3 (patch)
tree5693873124e4ac1f4a9c311f859fe6bce0f64d24
parent151ad0d4600875cb4fa20cecda68e26949d67596 (diff)
"Added ability to set callbacks for interrupts that get an argument. This argument can be the instance that needs to handle the interrupt, or just a random argument you might find useful later. Suggestions from mbolivar and iperry from pull53 on libmaple were taken into account.
Signed-off-by: Aditya Gaddam <adityagaddam@gmail.com>"
-rw-r--r--libmaple/exti.c110
-rw-r--r--libmaple/include/libmaple/exti.h5
-rw-r--r--libmaple/include/libmaple/libmaple_types.h1
-rw-r--r--wirish/ext_interrupts.cpp28
-rw-r--r--wirish/include/wirish/ext_interrupts.h21
5 files changed, 141 insertions, 24 deletions
diff --git a/libmaple/exti.c b/libmaple/exti.c
index 9023782..b620c77 100644
--- a/libmaple/exti.c
+++ b/libmaple/exti.c
@@ -43,27 +43,27 @@ static inline void dispatch_extis(uint32 start, uint32 stop);
*/
typedef struct exti_channel {
- void (*handler)(void);
- uint32 irq_line;
+ void (*handler)(void *);
+ void *arg;
} exti_channel;
static exti_channel exti_channels[] = {
- { .handler = NULL, .irq_line = NVIC_EXTI0 }, // EXTI0
- { .handler = NULL, .irq_line = NVIC_EXTI1 }, // EXTI1
- { .handler = NULL, .irq_line = NVIC_EXTI2 }, // EXTI2
- { .handler = NULL, .irq_line = NVIC_EXTI3 }, // EXTI3
- { .handler = NULL, .irq_line = NVIC_EXTI4 }, // EXTI4
- { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI5
- { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI6
- { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI7
- { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI8
- { .handler = NULL, .irq_line = NVIC_EXTI_9_5 }, // EXTI9
- { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI10
- { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI11
- { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI12
- { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI13
- { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI14
- { .handler = NULL, .irq_line = NVIC_EXTI_15_10 }, // EXTI15
+ { .handler = NULL, .arg = NULL }, // EXTI0
+ { .handler = NULL, .arg = NULL }, // EXTI1
+ { .handler = NULL, .arg = NULL }, // EXTI2
+ { .handler = NULL, .arg = NULL }, // EXTI3
+ { .handler = NULL, .arg = NULL }, // EXTI4
+ { .handler = NULL, .arg = NULL }, // EXTI5
+ { .handler = NULL, .arg = NULL }, // EXTI6
+ { .handler = NULL, .arg = NULL }, // EXTI7
+ { .handler = NULL, .arg = NULL }, // EXTI8
+ { .handler = NULL, .arg = NULL }, // EXTI9
+ { .handler = NULL, .arg = NULL }, // EXTI10
+ { .handler = NULL, .arg = NULL }, // EXTI11
+ { .handler = NULL, .arg = NULL }, // EXTI12
+ { .handler = NULL, .arg = NULL }, // EXTI13
+ { .handler = NULL, .arg = NULL }, // EXTI14
+ { .handler = NULL, .arg = NULL }, // EXTI15
};
/*
@@ -90,10 +90,39 @@ void exti_attach_interrupt(exti_num num,
exti_cfg port,
voidFuncPtr handler,
exti_trigger_mode mode) {
+
+ // Call callback version with arg being null
+ exti_attach_callback(num, port, handler, NULL, mode);
+}
+
+/**
+ * @brief Register a handler with an argument to run upon external interrupt.
+ *
+ * This function assumes that the interrupt request corresponding to
+ * the given external interrupt is masked.
+ *
+ * @param num External interrupt line number.
+ * @param port Port to use as source input for external interrupt.
+ * @param handler Function handler to execute when interrupt is triggered.
+ * @param arg Argument to pass to the interrupt handler.
+ * @param mode Type of transition to trigger on, one of:
+ * EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING.
+ * @see exti_num
+ * @see exti_cfg
+ * @see voidFuncPtr
+ * @see exti_trigger_mode
+ */
+void exti_attach_callback(exti_num num,
+ exti_cfg port,
+ voidFuncPtr handler,
+ void *arg,
+ exti_trigger_mode mode) {
+
ASSERT(handler);
/* Register the handler */
- exti_channels[num].handler = handler;
+ exti_channels[num].handler = (voidArgumentFuncPtr)handler;
+ exti_channels[num].arg = arg;
/* Set trigger mode */
switch (mode) {
@@ -116,7 +145,39 @@ void exti_attach_interrupt(exti_num num,
bb_peri_set_bit(&EXTI_BASE->IMR, num, 1);
/* Enable the interrupt line */
- nvic_irq_enable(exti_channels[num].irq_line);
+ switch(num)
+ {
+ case 0:
+ nvic_irq_enable(NVIC_EXTI0);
+ break;
+ case 1:
+ nvic_irq_enable(NVIC_EXTI1);
+ break;
+ case 2:
+ nvic_irq_enable(NVIC_EXTI2);
+ break;
+ case 3:
+ nvic_irq_enable(NVIC_EXTI3);
+ break;
+ case 4:
+ nvic_irq_enable(NVIC_EXTI4);
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ nvic_irq_enable(NVIC_EXTI_9_5);
+ break;
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ nvic_irq_enable(NVIC_EXTI_15_10);
+ break;
+ }
}
/**
@@ -134,6 +195,7 @@ void exti_detach_interrupt(exti_num num) {
/* Finally, unregister the user's handler */
exti_channels[num].handler = NULL;
+ exti_channels[num].arg = NULL;
}
/*
@@ -199,13 +261,13 @@ static __always_inline void clear_pending_msk(uint32 exti_msk) {
/* This dispatch routine is for non-multiplexed EXTI lines only; i.e.,
* it doesn't check EXTI_PR. */
static __always_inline void dispatch_single_exti(uint32 exti) {
- voidFuncPtr handler = exti_channels[exti].handler;
+ voidArgumentFuncPtr handler = exti_channels[exti].handler;
if (!handler) {
return;
}
- handler();
+ handler(exti_channels[exti].arg);
clear_pending_msk(1U << exti);
}
@@ -219,9 +281,9 @@ static __always_inline void dispatch_extis(uint32 start, uint32 stop) {
for (exti = start; exti <= stop; exti++) {
uint32 eb = (1U << exti);
if (pr & eb) {
- voidFuncPtr handler = exti_channels[exti].handler;
+ voidArgumentFuncPtr handler = exti_channels[exti].handler;
if (handler) {
- handler();
+ handler(exti_channels[exti].arg);
handled_msk |= eb;
}
}
diff --git a/libmaple/include/libmaple/exti.h b/libmaple/include/libmaple/exti.h
index 3800b4a..530b442 100644
--- a/libmaple/include/libmaple/exti.h
+++ b/libmaple/include/libmaple/exti.h
@@ -115,6 +115,11 @@ void exti_attach_interrupt(exti_num num,
exti_cfg port,
voidFuncPtr handler,
exti_trigger_mode mode);
+void exti_attach_callback(exti_num num,
+ exti_cfg port,
+ voidFuncPtr handler,
+ void *arg,
+ exti_trigger_mode mode);
void exti_detach_interrupt(exti_num num);
/**
diff --git a/libmaple/include/libmaple/libmaple_types.h b/libmaple/include/libmaple/libmaple_types.h
index 9e1fbb3..60dd2ff 100644
--- a/libmaple/include/libmaple/libmaple_types.h
+++ b/libmaple/include/libmaple/libmaple_types.h
@@ -48,6 +48,7 @@ typedef int int32;
typedef long long int64;
typedef void (*voidFuncPtr)(void);
+typedef void (*voidArgumentFuncPtr)(void *);
#define __io volatile
#define __attr_flash __attribute__((section (".USER_FLASH")))
diff --git a/wirish/ext_interrupts.cpp b/wirish/ext_interrupts.cpp
index a3e61fd..f72efbf 100644
--- a/wirish/ext_interrupts.cpp
+++ b/wirish/ext_interrupts.cpp
@@ -60,6 +60,34 @@ void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) {
}
/**
+ * @brief Registers an interrupt handler on a pin.
+ *
+ * @param pin Pin number
+ * @param handler Static class member function to run upon external interrupt
+ * trigger. The handler should take 1 argument and return void
+ * @param arg Argument that the handler will be passed when it's called. One
+ * use of this is to pass the specific instance of the class that
+ * will handle the interrupt.
+ * @param mode Type of transition to trigger on, e.g. falling, rising, etc.
+ *
+ * @sideeffect Registers a handler
+ * @see detachInterrupt()
+ */
+void attachInterrupt(uint8 pin, voidFuncPtr handler, void *arg, ExtIntTriggerMode mode) {
+ if (pin >= BOARD_NR_GPIO_PINS || !handler) {
+ return;
+ }
+
+ exti_trigger_mode outMode = exti_out_mode(mode);
+
+ exti_attach_callback((exti_num)(PIN_MAP[pin].gpio_bit),
+ gpio_exti_port(PIN_MAP[pin].gpio_device),
+ handler,
+ arg,
+ outMode);
+}
+
+/**
* @brief Disable any external interrupt attached to a pin.
* @param pin Pin number to detach any interrupt from.
*/
diff --git a/wirish/include/wirish/ext_interrupts.h b/wirish/include/wirish/ext_interrupts.h
index 933be04..1bd7956 100644
--- a/wirish/include/wirish/ext_interrupts.h
+++ b/wirish/include/wirish/ext_interrupts.h
@@ -69,6 +69,27 @@ typedef enum ExtIntTriggerMode {
void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode);
/**
+ * @brief Registers an interrupt handler on a pin.
+ *
+ * The interrupt will be triggered on a given transition on the pin,
+ * as specified by the mode parameter. The handler runs in interrupt
+ * context. The new handler will replace whatever handler is
+ * currently registered for the pin, if any.
+ *
+ * @param pin Pin number
+ * @param handler Static class member function to run upon external interrupt
+ * trigger. The handler should take 1 argument and return void
+ * @param arg Argument that the handler will be passed when it's called. One
+ * use of this is to pass the specific instance of the class that
+ * will handle the interrupt.
+ * @param mode Type of transition to trigger on, e.g. falling, rising, etc.
+ *
+ * @sideeffect Registers a handler
+ * @see detachInterrupt()
+ */
+void attachInterrupt(uint8 pin, voidFuncPtr handler, void *arg, ExtIntTriggerMode mode);
+
+/**
* @brief Disable any registered external interrupt.
* @param pin Maple pin number
* @sideeffect unregisters external interrupt handler