From 6538f8950bd787e6c8d78df966d295cff1dd49dd Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 4 Sep 2015 15:20:26 +0200 Subject: [PATCH 1/2] NMI interrupts are now correctly ignored by attach/detachInterrupt Fixes #30 --- cores/arduino/WInterrupts.c | 121 +++++++++++------------------------- 1 file changed, 35 insertions(+), 86 deletions(-) diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c index 93d888200..be6db38b9 100644 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.c @@ -76,6 +76,8 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) if (digitalPinToInterrupt(pin) == NOT_AN_INTERRUPT) return; + if (digitalPinToInterrupt(pin) == EXTERNAL_INT_NMI) + return; if (!enabled) { __initialize(); @@ -89,91 +91,53 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) callbacksInt[digitalPinToInterrupt(pin)]._ulPin = pin; callbacksInt[digitalPinToInterrupt(pin)]._callback = callback; - // Check if normal interrupt or NMI - if (pin != 2) - { - // Look for right CONFIG register to be addressed - if (digitalPinToInterrupt(pin) > EXTERNAL_INT_7) { - config = 1; - } else { - config = 0; - } - - // Configure the interrupt mode - pos = ((digitalPinToInterrupt(pin) - (8 * config)) << 2); - switch (mode) - { - case LOW: - EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos; - break; - - case HIGH: - EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos; - break; - - case CHANGE: - EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos; - break; - - case FALLING: - EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos; - break; - - case RISING: - EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos; - break; - } - - // Enable the interrupt - EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << digitalPinToInterrupt(pin)); + // Look for right CONFIG register to be addressed + if (digitalPinToInterrupt(pin) > EXTERNAL_INT_7) { + config = 1; + } else { + config = 0; } - else // Handles NMI on pin 2 + + // Configure the interrupt mode + pos = ((digitalPinToInterrupt(pin) - (8 * config)) << 2); + switch (mode) { - // Configure the interrupt mode - switch (mode) - { - case LOW: - EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_LOW; - break; + case LOW: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos; + break; - case HIGH: - EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_HIGH; - break; + case HIGH: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos; + break; - case CHANGE: - EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_BOTH; - break; + case CHANGE: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos; + break; - case FALLING: - EIC->NMICTRL.reg = EIC_NMICTRL_NMISENSE_FALL; - break; + case FALLING: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos; + break; - case RISING: - EIC->NMICTRL.reg= EIC_NMICTRL_NMISENSE_RISE; - break; - } + case RISING: + EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos; + break; } + + // Enable the interrupt + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << digitalPinToInterrupt(pin)); } /* * \brief Turns off the given interrupt. */ -void detachInterrupt( uint32_t ulPin ) +void detachInterrupt(uint32_t pin) { -/* - // Retrieve pin information - Pio *pio = g_APinDescription[pin].pPort; - uint32_t mask = g_APinDescription[pin].ulPin; - - // Disable interrupt - pio->PIO_IDR = mask; -*/ - if ( digitalPinToInterrupt( ulPin ) == NOT_AN_INTERRUPT ) - { - return ; - } + if (digitalPinToInterrupt(pin) == NOT_AN_INTERRUPT) + return; + if (digitalPinToInterrupt(pin) == EXTERNAL_INT_NMI) + return; - EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT( 1 << digitalPinToInterrupt( ulPin ) ) ; + EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(1 << digitalPinToInterrupt(pin)); } /* @@ -200,21 +164,6 @@ void EIC_Handler( void ) } } -/* - * External Non-Maskable Interrupt Controller NVIC Interrupt Handler - */ -void NMI_Handler( void ) -{ - // Call the callback function if assigned - if ( callbacksInt[EXTERNAL_INT_NMI]._callback != NULL ) - { - callbacksInt[EXTERNAL_INT_NMI]._callback() ; - } - - // Clear the interrupt - EIC->NMIFLAG.reg = EIC_NMIFLAG_NMI ; -} - #ifdef __cplusplus } #endif From e258489713a5bf9e628e9174b13166243bd3e4d7 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 4 Sep 2015 15:35:38 +0200 Subject: [PATCH 2/2] Simplified "callbacksInt" structure in WInterrupts.c --- cores/arduino/WInterrupts.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c index be6db38b9..2c6ed74e1 100644 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.c @@ -25,16 +25,12 @@ extern "C" { #endif -static struct -{ - uint32_t _ulPin ; - voidFuncPtr _callback ; -} callbacksInt[EXTERNAL_NUM_INTERRUPTS] ; +static voidFuncPtr callbacksInt[EXTERNAL_NUM_INTERRUPTS]; /* Configure I/O interrupt sources */ static void __initialize() { - memset( callbacksInt, 0, sizeof( callbacksInt ) ) ; + memset(callbacksInt, 0, sizeof(callbacksInt)); NVIC_DisableIRQ( EIC_IRQn ) ; NVIC_ClearPendingIRQ( EIC_IRQn ) ; @@ -88,8 +84,7 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) pinPeripheral(pin, PIO_EXTINT); // Assign callback to interrupt - callbacksInt[digitalPinToInterrupt(pin)]._ulPin = pin; - callbacksInt[digitalPinToInterrupt(pin)]._callback = callback; + callbacksInt[digitalPinToInterrupt(pin)] = callback; // Look for right CONFIG register to be addressed if (digitalPinToInterrupt(pin) > EXTERNAL_INT_7) { @@ -153,9 +148,8 @@ void EIC_Handler( void ) if ( (EIC->INTFLAG.reg & ( 1 << ul ) ) != 0 ) { // Call the callback function if assigned - if ( callbacksInt[ul]._callback != NULL ) - { - callbacksInt[ul]._callback() ; + if (callbacksInt[ul]) { + callbacksInt[ul](); } // Clear the interrupt