@@ -78,133 +78,129 @@ static void __initialize()
7878 */
7979void 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__ )
257253void 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