21
21
22
22
#include <string.h>
23
23
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
+
25
28
26
29
/* Configure I/O interrupt sources */
27
30
static void __initialize ()
28
31
{
29
- memset (callbacksInt , 0 , sizeof (callbacksInt ));
32
+ memset (ISRlist , 0 , sizeof (ISRlist ));
33
+ memset (ISRcallback , 0 , sizeof (ISRcallback ));
34
+ nints = 0 ;
30
35
31
36
NVIC_DisableIRQ (EIC_IRQn );
32
37
NVIC_ClearPendingIRQ (EIC_IRQn );
@@ -76,42 +81,65 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
76
81
// Assign pin to EIC
77
82
pinPeripheral (pin , PIO_EXTINT );
78
83
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
+ }
81
98
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
+ }
88
116
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 ;
97
125
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 ;
101
129
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 ;
105
133
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 ;
109
137
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
+ }
113
142
}
114
-
115
143
// Enable the interrupt
116
144
EIC -> INTENSET .reg = EIC_INTENSET_EXTINT (1 << in );
117
145
}
@@ -133,25 +161,42 @@ void detachInterrupt(uint32_t pin)
133
161
134
162
// Disable wakeup capability on pin during sleep
135
163
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 -- ;
136
181
}
137
182
138
183
/*
139
184
* External Interrupt Controller NVIC Interrupt Handler
140
185
*/
141
186
void EIC_Handler (void )
142
187
{
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 ++ )
145
193
{
146
- if ((EIC -> INTFLAG .reg & ( 1 << i ) ) != 0 )
194
+ if ((EIC -> INTFLAG .reg & 1 << ISRlist [ i ] ) != 0 )
147
195
{
148
- // Call the callback function if assigned
149
- if (callbacksInt [i ]) {
150
- callbacksInt [i ]();
151
- }
152
-
196
+ // Call the callback function
197
+ ISRcallback [i ]();
153
198
// Clear the interrupt
154
- EIC -> INTFLAG .reg = 1 << i ;
199
+ EIC -> INTFLAG .reg = 1 << ISRlist [ i ] ;
155
200
}
156
201
}
157
202
}
0 commit comments