2121
2222#include <string.h>
2323
24- static voidFuncPtr callbacksInt [EXTERNAL_NUM_INTERRUPTS ];
24+ static voidFuncPtr ISRcallback [EXTERNAL_NUM_INTERRUPTS ];
25+ static EExt_Interrupts ISRlist [EXTERNAL_NUM_INTERRUPTS ];
26+ static uint32_t nints ; // Stores total number of attached interrupts
27+
2528
2629/* Configure I/O interrupt sources */
2730static void __initialize ()
2831{
29- memset (callbacksInt , 0 , sizeof (callbacksInt ));
32+ memset (ISRlist , 0 , sizeof (ISRlist ));
33+ memset (ISRcallback , 0 , sizeof (ISRcallback ));
34+ nints = 0 ;
3035
3136 NVIC_DisableIRQ (EIC_IRQn );
3237 NVIC_ClearPendingIRQ (EIC_IRQn );
@@ -76,42 +81,65 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
7681 // Assign pin to EIC
7782 pinPeripheral (pin , PIO_EXTINT );
7883
79- // Assign callback to interrupt
80- callbacksInt [in ] = callback ;
84+ // Only store when there is really an ISR to call.
85+ // This allow for calling attachInterrupt(pin, NULL, mode), we set up all needed register
86+ // but won't service the interrupt, this way we also don't need to check it inside the ISR.
87+ if (callback )
88+ {
89+ // Store interrupts to service in order of when they were attached
90+ // to allow for first come first serve handler
91+ uint32_t current = 0 ;
92+
93+ // Check if we already have this interrupt
94+ int id = -1 ;
95+ for (uint32_t i = 0 ; i < nints ; i ++ ) {
96+ if (ISRlist [i ] == in ) id = in ;
97+ }
8198
82- // Look for right CONFIG register to be addressed
83- if (in > EXTERNAL_INT_7 ) {
84- config = 1 ;
85- } else {
86- config = 0 ;
87- }
99+ if (id == -1 ) {
100+ // Need to make a new entry
101+ current = nints ;
102+ nints ++ ;
103+ } else {
104+ // We already have an entry for this pin
105+ current = id ;
106+ }
107+ ISRlist [current ] = in ; // List with nr of interrupt in order of when they were attached
108+ ISRcallback [current ] = callback ; // List of callback adresses
109+
110+ // Look for right CONFIG register to be addressed
111+ if (in > EXTERNAL_INT_7 ) {
112+ config = 1 ;
113+ } else {
114+ config = 0 ;
115+ }
88116
89- // Configure the interrupt mode
90- pos = (in - (8 * config )) << 2 ;
91- EIC -> CONFIG [config ].reg &=~ (EIC_CONFIG_SENSE0_Msk << pos );//reset sense mode, important when changing trigger mode during runtime
92- switch (mode )
93- {
94- case LOW :
95- EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos ;
96- break ;
117+ // Configure the interrupt mode
118+ pos = (in - (8 * config )) << 2 ;
119+ EIC -> CONFIG [config ].reg &=~ (EIC_CONFIG_SENSE0_Msk << pos ); // Reset sense mode, important when changing trigger mode during runtime
120+ switch (mode )
121+ {
122+ case LOW :
123+ EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos ;
124+ break ;
97125
98- case HIGH :
99- EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos ;
100- break ;
126+ case HIGH :
127+ EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos ;
128+ break ;
101129
102- case CHANGE :
103- EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos ;
104- break ;
130+ case CHANGE :
131+ EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos ;
132+ break ;
105133
106- case FALLING :
107- EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos ;
108- break ;
134+ case FALLING :
135+ EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos ;
136+ break ;
109137
110- case RISING :
111- EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos ;
112- break ;
138+ case RISING :
139+ EIC -> CONFIG [config ].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos ;
140+ break ;
141+ }
113142 }
114-
115143 // Enable the interrupt
116144 EIC -> INTENSET .reg = EIC_INTENSET_EXTINT (1 << in );
117145}
@@ -133,25 +161,42 @@ void detachInterrupt(uint32_t pin)
133161
134162 // Disable wakeup capability on pin during sleep
135163 EIC -> WAKEUP .reg &= ~(1 << in );
164+
165+ // Remove callback from the ISR list
166+ int id = -1 ;
167+ for (uint32_t i = 0 ; i < nints ; i ++ ) {
168+ if (ISRlist [i ] == in ) id = in ;
169+ }
170+ if (id == -1 ) return ; // We didn't have it
171+
172+ // Shift the reminder down
173+ for (uint32_t i = id ; i < nints - 1 ; i ++ ) {
174+ ISRlist [i ] = ISRlist [i + 1 ];
175+ ISRcallback [i ] = ISRcallback [i + 1 ];
176+ }
177+ // And remove the top item
178+ ISRlist [nints ]= 0 ;
179+ ISRcallback [nints ]= NULL ;
180+ nints -- ;
136181}
137182
138183/*
139184 * External Interrupt Controller NVIC Interrupt Handler
140185 */
141186void EIC_Handler (void )
142187{
143- // Test the 16 normal interrupts
144- for (uint32_t i = EXTERNAL_INT_0 ; i <=EXTERNAL_INT_15 ; i ++ )
188+ // Calling the routine directly from -here- takes about 1us
189+ // Depending on where you are in the list it will take longer
190+
191+ // Loop over all enabled interrupts in the list
192+ for (uint32_t i = 0 ; i < nints ; i ++ )
145193 {
146- if ((EIC -> INTFLAG .reg & ( 1 << i ) ) != 0 )
194+ if ((EIC -> INTFLAG .reg & 1 << ISRlist [ i ] ) != 0 )
147195 {
148- // Call the callback function if assigned
149- if (callbacksInt [i ]) {
150- callbacksInt [i ]();
151- }
152-
196+ // Call the callback function
197+ ISRcallback [i ]();
153198 // Clear the interrupt
154- EIC -> INTFLAG .reg = 1 << i ;
199+ EIC -> INTFLAG .reg = 1 << ISRlist [ i ] ;
155200 }
156201 }
157202}
0 commit comments