@@ -78,133 +78,129 @@ static void __initialize()
78
78
*/
79
79
void attachInterrupt (uint32_t pin , voidFuncPtr callback , uint32_t mode )
80
80
{
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
208
204
}
209
205
210
206
/*
@@ -256,15 +252,19 @@ void detachInterrupt(uint32_t pin)
256
252
#if defined(__SAMD51__ )
257
253
void InterruptHandler (uint32_t i )
258
254
{
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
265
257
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
+ }
268
268
}
269
269
}
270
270
@@ -375,4 +375,4 @@ void NMI_Handler(void)
375
375
if (ISRcallback [EXTERNAL_INT_NMI ]) ISRcallback [EXTERNAL_INT_NMI ]();
376
376
EIC -> NMIFLAG .bit .NMI = 1 ; // Clear interrupt
377
377
}
378
- #endif
378
+ #endif
0 commit comments