Skip to content

Allow enabling/disabling external interrupts and clear pending interrupts on attach #2159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: ide-1.5.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hardware/arduino/avr/cores/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);

void attachInterrupt(uint8_t, void (*)(void), int mode);
void detachInterrupt(uint8_t);
void enableInterrupt(uint8_t interruptNum);
void disableInterrupt(uint8_t interruptNum);

void setup(void);
void loop(void);
Expand Down
209 changes: 147 additions & 62 deletions hardware/arduino/avr/cores/arduino/WInterrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA

Modified 24 November 2006 by David A. Mellis
Modified 1 August 2010 by Mark Sproul
*/
Expand All @@ -38,112 +38,192 @@ static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
intFunc[interruptNum] = userFunc;

// Configure the interrupt mode (trigger on low input, any change, rising
// edge, or falling edge). The mode constants were chosen to correspond
// to the configuration bits in the hardware register, so we simply shift
// the mode into place.

// Enable the interrupt.


switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
// I hate doing this, but the register assignment differs between the 1280/2560
// and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
// and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
// even present on the 32U4 this is the only way to distinguish between them.
case 0:
EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
EIMSK |= (1<<INT0);
break;
EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
EIFR |= (1 << INTF0);
break;
case 1:
EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
EIMSK |= (1<<INT1);
break;
EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
EIFR |= (1 << INTF1);
break;
case 2:
EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
EIMSK |= (1<<INT2);
break;
EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20);
EIFR |= (1 << INTF2);
break;
case 3:
EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
EIMSK |= (1<<INT3);
break;
EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30);
EIFR |= (1 << INTF3);
break;
case 4:
EICRB = (EICRB & ~((1<<ISC60) | (1<<ISC61))) | (mode << ISC60);
EIMSK |= (1<<INT6);
break;
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
EICRB = (EICRB & ~((1<<ISC60) | (1<<ISC61))) | (mode << ISC60);
EIFR |= (1 << INTF6);
break;
#elif defined(EICRA) && defined(EICRB)
case 2:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
EIFR |= (1 << INTF0);
break;
case 3:
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
EIFR |= (1 << INTF1);
break;
case 4:
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIMSK |= (1 << INT2);
EIFR |= (1 << INTF2);
break;
case 5:
EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
EIMSK |= (1 << INT3);
EIFR |= (1 << INTF4);
break;
case 0:
EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
EIMSK |= (1 << INT4);
EIFR |= (1 << INTF4);
break;
case 1:
EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
EIMSK |= (1 << INT5);
EIFR |= (1 << INTF5);
break;
case 6:
EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
EIMSK |= (1 << INT6);
EIFR |= (1 << INTF6);
break;
case 7:
EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
EIMSK |= (1 << INT7);
EIFR |= (1 << INTF7);
break;
#else
#else
case 0:
#if defined(EICRA) && defined(ISC00) && defined(EIMSK)
#if defined(EICRA) && defined(ISC00) && defined(EIFR)
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
#elif defined(MCUCR) && defined(ISC00) && defined(GICR)
EIFR |= (1 << INTF0);
#elif defined(MCUCR) && defined(ISC00) && defined(GIFR)
MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
GIFR |= (1 << INTF0);
#else
#error attachInterrupt not finished for this CPU (case 0)
#endif
break;

case 1:
#if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIFR)
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIFR |= (1 << INTF1);
#elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GIFR)
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
GIFR |= (1 << INTF1);
#else
#warning attachInterrupt may need some more work for this cpu (case 1)
#endif
break;

case 2:
#if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIFR)
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIFR |= (1 << INTF2);
#elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GIFR)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
GIFR |= (1 << INTF2);
#endif
break;
#endif
}

// Enable the interrupt.
enableInterrupt(interruptNum);
}
}

void enableInterrupt(uint8_t interruptNum) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {

// Enable the interrupt.
switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
// I hate doing this, but the register assignment differs between the 1280/2560
// and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
// even present on the 32U4 this is the only way to distinguish between them.
case 0:
EIMSK |= (1<<INT0);
break;
case 1:
EIMSK |= (1<<INT1);
break;
case 2:
EIMSK |= (1<<INT2);
break;
case 3:
EIMSK |= (1<<INT3);
break;
case 4:
EIMSK |= (1<<INT6);
break;
#elif defined(EIFR) && defined(EICRB) && defined(EIMSK)
case 2:
EIMSK |= (1 << INT0);
break;
case 3:
EIMSK |= (1 << INT1);
break;
case 4:
EIMSK |= (1 << INT2);
break;
case 5:
EIMSK |= (1 << INT3);
break;
case 0:
EIMSK |= (1 << INT4);
break;
case 1:
EIMSK |= (1 << INT5);
break;
case 6:
EIMSK |= (1 << INT6);
break;
case 7:
EIMSK |= (1 << INT7);
break;
#else
case 0:
#if defined(ISC00) && defined(EIMSK)
EIMSK |= (1 << INT0);
#elif defined(ISC00) && defined(GICR)
GICR |= (1 << INT0);
#elif defined(MCUCR) && defined(ISC00) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
#elif defined(ISC00) && defined(GIMSK)
GIMSK |= (1 << INT0);
#else
#error attachInterrupt not finished for this CPU (case 0)
#endif
break;

case 1:
#if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
#if defined(ISC10) && defined(ISC11) && defined(EIMSK)
EIMSK |= (1 << INT1);
#elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR)
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
#elif defined(ISC10) && defined(ISC11) && defined(GICR)
GICR |= (1 << INT1);
#elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
#elif defined(ISC10) && defined(GIMSK) && defined(GIMSK)
GIMSK |= (1 << INT1);
#else
#warning attachInterrupt may need some more work for this cpu (case 1)
#endif
break;

case 2:
#if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIMSK)
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
#if defined(ISC20) && defined(ISC21) && defined(EIMSK)
EIMSK |= (1 << INT2);
#elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GICR)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
#elif defined(ISC20) && defined(ISC21) && defined(GICR)
GICR |= (1 << INT2);
#elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
#elif defined(ISC20) && defined(GIMSK) && defined(GIMSK)
GIMSK |= (1 << INT2);
#endif
break;
Expand All @@ -153,27 +233,34 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
}

void detachInterrupt(uint8_t interruptNum) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
disableInterrupt(interruptNum);
intFunc[interruptNum] = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be nothing now
https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/WInterrupts.c#L273

And the PR needs to be built against the master, otherwise its useless. May you update the PR or better create a new against the master?

}
}

void disableInterrupt(uint8_t interruptNum) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
// Disable the interrupt. (We can't assume that interruptNum is equal
// to the number of the EIMSK bit to clear, as this isn't true on the
// to the number of the EIMSK bit to clear, as this isn't true on the
// ATmega8. There, INT0 is 6 and INT1 is 7.)
switch (interruptNum) {
#if defined(__AVR_ATmega32U4__)
case 0:
EIMSK &= ~(1<<INT0);
break;
EIMSK &= ~(1<<INT0);
break;
case 1:
EIMSK &= ~(1<<INT1);
break;
EIMSK &= ~(1<<INT1);
break;
case 2:
EIMSK &= ~(1<<INT2);
break;
EIMSK &= ~(1<<INT2);
break;
case 3:
EIMSK &= ~(1<<INT3);
break;
EIMSK &= ~(1<<INT3);
break;
case 4:
EIMSK &= ~(1<<INT6);
break;
EIMSK &= ~(1<<INT6);
break;
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EIMSK &= ~(1 << INT0);
Expand Down Expand Up @@ -225,8 +312,6 @@ void detachInterrupt(uint8_t interruptNum) {
break;
#endif
}

intFunc[interruptNum] = 0;
}
}

Expand Down
Loading