Skip to content

Commit 6d06982

Browse files
PaintYourDragonladyada
authored andcommitted
Allow attachInterrupt() on NMI pin (PA08 on ATSAMD21E)
1 parent 24a653d commit 6d06982

File tree

1 file changed

+82
-41
lines changed

1 file changed

+82
-41
lines changed

cores/arduino/WInterrupts.c

Lines changed: 82 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -62,57 +62,86 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
6262
#else
6363
EExt_Interrupts in = digitalPinToInterrupt(pin);
6464
#endif
65-
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI)
66-
return;
65+
if (in == NOT_AN_INTERRUPT) return;
6766

6867
if (!enabled) {
6968
__initialize();
7069
enabled = 1;
7170
}
7271

73-
// Enable wakeup capability on pin in case being used during sleep
74-
EIC->WAKEUP.reg |= (1 << in);
72+
if (in == EXTERNAL_INT_NMI) {
73+
EIC->NMIFLAG.bit.NMI = 1; // Clear flag
74+
switch (mode) {
75+
case LOW:
76+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_LOW;
77+
break;
7578

76-
// Assign pin to EIC
77-
pinPeripheral(pin, PIO_EXTINT);
79+
case HIGH:
80+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_HIGH;
81+
break;
7882

79-
// Assign callback to interrupt
80-
callbacksInt[in] = callback;
83+
case CHANGE:
84+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_BOTH;
85+
break;
8186

82-
// Look for right CONFIG register to be addressed
83-
if (in > EXTERNAL_INT_7) {
84-
config = 1;
85-
} else {
86-
config = 0;
87-
}
87+
case FALLING:
88+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_FALL;
89+
break;
8890

89-
// Configure the interrupt mode
90-
pos = (in - (8 * config)) << 2;
91-
switch (mode)
92-
{
93-
case LOW:
94-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos;
95-
break;
91+
case RISING:
92+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_RISE;
93+
break;
94+
}
9695

97-
case HIGH:
98-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos;
99-
break;
96+
// Assign callback to interrupt
97+
callbacksInt[EXTERNAL_INT_NMI] = callback;
10098

101-
case CHANGE:
102-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos;
103-
break;
99+
} else { // Not NMI, is external interrupt
104100

105-
case FALLING:
106-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos;
107-
break;
101+
// Enable wakeup capability on pin in case being used during sleep
102+
EIC->WAKEUP.reg |= (1 << in);
108103

109-
case RISING:
110-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos;
111-
break;
112-
}
104+
// Assign pin to EIC
105+
pinPeripheral(pin, PIO_EXTINT);
106+
107+
// Look for right CONFIG register to be addressed
108+
if (in > EXTERNAL_INT_7) {
109+
config = 1;
110+
} else {
111+
config = 0;
112+
}
113+
114+
// Configure the interrupt mode
115+
pos = (in - (8 * config)) << 2;
116+
switch (mode)
117+
{
118+
case LOW:
119+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos;
120+
break;
121+
122+
case HIGH:
123+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos;
124+
break;
125+
126+
case CHANGE:
127+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos;
128+
break;
129+
130+
case FALLING:
131+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos;
132+
break;
113133

114-
// Enable the interrupt
115-
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << in);
134+
case RISING:
135+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos;
136+
break;
137+
}
138+
139+
// Enable the interrupt
140+
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << in);
141+
142+
// Assign callback to interrupt
143+
callbacksInt[in] = callback;
144+
}
116145
}
117146

118147
/*
@@ -125,13 +154,16 @@ void detachInterrupt(uint32_t pin)
125154
#else
126155
EExt_Interrupts in = digitalPinToInterrupt(pin);
127156
#endif
128-
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI)
129-
return;
157+
if (in == NOT_AN_INTERRUPT) return;
130158

131-
EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(1 << in);
159+
if(in == EXTERNAL_INT_NMI) {
160+
EIC->NMICTRL.bit.NMISENSE = 0; // Turn off detection
161+
} else {
162+
EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(1 << in);
132163

133-
// Disable wakeup capability on pin during sleep
134-
EIC->WAKEUP.reg &= ~(1 << in);
164+
// Disable wakeup capability on pin during sleep
165+
EIC->WAKEUP.reg &= ~(1 << in);
166+
}
135167
}
136168

137169
/*
@@ -154,3 +186,12 @@ void EIC_Handler(void)
154186
}
155187
}
156188
}
189+
190+
/*
191+
* NMI Interrupt Handler
192+
*/
193+
void NMI_Handler(void)
194+
{
195+
if (callbacksInt[EXTERNAL_INT_NMI]) callbacksInt[EXTERNAL_INT_NMI]();
196+
EIC->NMIFLAG.bit.NMI = 1; // Clear interrupt
197+
}

0 commit comments

Comments
 (0)