Skip to content

Commit 0654cd0

Browse files
committed
DM: fix interrupt handling
1 parent 6631c1b commit 0654cd0

File tree

1 file changed

+136
-136
lines changed

1 file changed

+136
-136
lines changed

cores/arduino/WInterrupts.c

Lines changed: 136 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -78,133 +78,129 @@ static void __initialize()
7878
*/
7979
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
8080
{
81-
static int enabled = 0;
82-
uint32_t config;
83-
uint32_t pos;
84-
85-
#if ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10606
86-
EExt_Interrupts in = g_APinDescription[pin].ulExtInt;
87-
#else
88-
EExt_Interrupts in = digitalPinToInterrupt(pin);
89-
#endif
90-
if (in == NOT_AN_INTERRUPT) return;
91-
92-
if (!enabled) {
93-
__initialize();
94-
enabled = 1;
95-
}
96-
97-
// Only store when there is really an ISR to call.
98-
// This allow for calling attachInterrupt(pin, NULL, mode), we set up all needed register
99-
// but won't service the interrupt, this way we also don't need to check it inside the ISR.
100-
if (callback)
101-
{
102-
// Store interrupts to service in order of when they were attached
103-
// to allow for first come first serve handler
104-
uint32_t current = 0;
105-
uint32_t inMask = (1UL << in);
106-
107-
// Check if we already have this interrupt
108-
for (current=0; current<nints; current++) {
109-
if (ISRlist[current] == inMask) {
110-
break;
111-
}
112-
}
113-
if (current == nints) {
114-
// Need to make a new entry
115-
nints++;
116-
}
117-
ISRlist[current] = inMask; // List of interrupt in order of when they were attached
118-
ISRcallback[current] = callback; // List of callback adresses
119-
}
120-
121-
if (in == EXTERNAL_INT_NMI) {
122-
EIC->NMIFLAG.bit.NMI = 1; // Clear flag
123-
switch (mode) {
124-
case LOW:
125-
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_LOW;
126-
break;
127-
128-
case HIGH:
129-
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_HIGH;
130-
break;
131-
132-
case CHANGE:
133-
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_BOTH;
134-
break;
135-
136-
case FALLING:
137-
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_FALL;
138-
break;
139-
140-
case RISING:
141-
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_RISE;
142-
break;
143-
}
144-
145-
// Assign callback to interrupt
146-
ISRcallback[EXTERNAL_INT_NMI] = callback;
147-
148-
} else { // Not NMI, is external interrupt
149-
150-
// Enable wakeup capability on pin in case being used during sleep
151-
#if defined(__SAMD51__)
152-
//I believe this is done automatically
153-
#else
154-
EIC->WAKEUP.reg |= (1 << in);
155-
#endif
156-
157-
// Assign pin to EIC
158-
pinPeripheral(pin, PIO_EXTINT);
159-
160-
// Assign callback to interrupt
161-
ISRcallback[in] = callback;
162-
163-
// Look for right CONFIG register to be addressed
164-
if (in > EXTERNAL_INT_7) {
165-
config = 1;
166-
} else {
167-
config = 0;
168-
}
169-
170-
// Configure the interrupt mode
171-
pos = (in - (8 * config)) << 2;
172-
173-
#if defined (__SAMD51__)
174-
EIC->CTRLA.bit.ENABLE = 0;
175-
while (EIC->SYNCBUSY.bit.ENABLE == 1) { }
176-
#endif
177-
178-
switch (mode)
179-
{
180-
case LOW:
181-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos;
182-
break;
183-
184-
case HIGH:
185-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos;
186-
break;
187-
188-
case CHANGE:
189-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos;
190-
break;
191-
192-
case FALLING:
193-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos;
194-
break;
195-
196-
case RISING:
197-
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos;
198-
break;
199-
}
200-
}
201-
// Enable the interrupt
202-
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << in);
203-
204-
#if defined (__SAMD51__)
205-
EIC->CTRLA.bit.ENABLE = 1;
206-
while (EIC->SYNCBUSY.bit.ENABLE == 1) { }
207-
#endif
81+
static int enabled = 0;
82+
uint32_t config;
83+
uint32_t pos;
84+
85+
#if ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10606
86+
EExt_Interrupts in = g_APinDescription[pin].ulExtInt;
87+
#else
88+
EExt_Interrupts in = digitalPinToInterrupt(pin);
89+
#endif
90+
if (in == NOT_AN_INTERRUPT) return;
91+
92+
if (!enabled) {
93+
__initialize();
94+
enabled = 1;
95+
}
96+
uint32_t inMask = (1UL << in);
97+
// Enable wakeup capability on pin in case being used during sleep
98+
#if defined(__SAMD51__)
99+
//I believe this is done automatically
100+
#else
101+
EIC->WAKEUP.reg |= (1 << in);
102+
#endif
103+
104+
// Only store when there is really an ISR to call.
105+
// This allow for calling attachInterrupt(pin, NULL, mode), we set up all needed register
106+
// but won't service the interrupt, this way we also don't need to check it inside the ISR.
107+
if (callback)
108+
{
109+
if (in == EXTERNAL_INT_NMI) {
110+
EIC->NMIFLAG.bit.NMI = 1; // Clear flag
111+
switch (mode) {
112+
case LOW:
113+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_LOW;
114+
break;
115+
116+
case HIGH:
117+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_HIGH;
118+
break;
119+
120+
case CHANGE:
121+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_BOTH;
122+
break;
123+
124+
case FALLING:
125+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_FALL;
126+
break;
127+
128+
case RISING:
129+
EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_RISE;
130+
break;
131+
}
132+
133+
// Assign callback to interrupt
134+
ISRcallback[EXTERNAL_INT_NMI] = callback;
135+
136+
} else { // Not NMI, is external interrupt
137+
138+
// Assign pin to EIC
139+
pinPeripheral(pin, PIO_EXTINT);
140+
141+
// Store interrupts to service in order of when they were attached
142+
// to allow for first come first serve handler
143+
uint32_t current = 0;
144+
145+
// Check if we already have this interrupt
146+
for (current=0; current<nints; current++) {
147+
if (ISRlist[current] == inMask) {
148+
break;
149+
}
150+
}
151+
if (current == nints) {
152+
// Need to make a new entry
153+
nints++;
154+
}
155+
ISRlist[current] = inMask; // List of interrupt in order of when they were attached
156+
ISRcallback[current] = callback; // List of callback adresses
157+
158+
// Look for right CONFIG register to be addressed
159+
if (in > EXTERNAL_INT_7) {
160+
config = 1;
161+
pos = (in - 8) << 2;
162+
} else {
163+
config = 0;
164+
pos = in << 2;
165+
}
166+
167+
#if defined (__SAMD51__)
168+
EIC->CTRLA.bit.ENABLE = 0;
169+
while (EIC->SYNCBUSY.bit.ENABLE == 1) { }
170+
#endif
171+
172+
EIC->CONFIG[config].reg &=~ (EIC_CONFIG_SENSE0_Msk << pos); // Reset sense mode, important when changing trigger mode during runtime
173+
switch (mode)
174+
{
175+
case LOW:
176+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos;
177+
break;
178+
179+
case HIGH:
180+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos;
181+
break;
182+
183+
case CHANGE:
184+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos;
185+
break;
186+
187+
case FALLING:
188+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos;
189+
break;
190+
191+
case RISING:
192+
EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos;
193+
break;
194+
}
195+
}
196+
// Enable the interrupt
197+
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << in);
198+
}
199+
200+
#if defined (__SAMD51__)
201+
EIC->CTRLA.bit.ENABLE = 1;
202+
while (EIC->SYNCBUSY.bit.ENABLE == 1) { }
203+
#endif
208204
}
209205

210206
/*
@@ -256,15 +252,19 @@ void detachInterrupt(uint32_t pin)
256252
#if defined(__SAMD51__)
257253
void InterruptHandler(uint32_t i)
258254
{
259-
if ((EIC->INTFLAG.reg & (1 << i)) != 0)
260-
{
261-
// Call the callback function if assigned
262-
if (ISRcallback[i]) {
263-
ISRcallback[i]();
264-
}
255+
// Calling the routine directly from -here- takes about 1us
256+
// Depending on where you are in the list it will take longer
265257

266-
// Clear the interrupt
267-
EIC->INTFLAG.reg = 1 << i;
258+
// Loop over all enabled interrupts in the list
259+
for (uint32_t i=0; i<nints; i++)
260+
{
261+
if ((EIC->INTFLAG.reg & ISRlist[i]) != 0)
262+
{
263+
// Call the callback function
264+
ISRcallback[i]();
265+
// Clear the interrupt
266+
EIC->INTFLAG.reg = ISRlist[i];
267+
}
268268
}
269269
}
270270

@@ -375,4 +375,4 @@ void NMI_Handler(void)
375375
if (ISRcallback[EXTERNAL_INT_NMI]) ISRcallback[EXTERNAL_INT_NMI]();
376376
EIC->NMIFLAG.bit.NMI = 1; // Clear interrupt
377377
}
378-
#endif
378+
#endif

0 commit comments

Comments
 (0)