]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/drivers/Atmel/at91lib/peripherals/pio/pio_it.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / Common / drivers / Atmel / at91lib / peripherals / pio / pio_it.c
1 /* ----------------------------------------------------------------------------\r
2  *         ATMEL Microcontroller Software Support \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2008, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /// Disable traces for this file\r
31 #ifndef NOTRACE\r
32     #define NOTRACE\r
33 #endif\r
34 \r
35 //------------------------------------------------------------------------------\r
36 //         Headers\r
37 //------------------------------------------------------------------------------\r
38 \r
39 #include "pio_it.h"\r
40 #include "pio.h"\r
41 #include <aic/aic.h>\r
42 #include <board.h>\r
43 #include <utility/assert.h>\r
44 #include <utility/trace.h>\r
45 \r
46 //------------------------------------------------------------------------------\r
47 //         Local definitions\r
48 //------------------------------------------------------------------------------\r
49 \r
50 /// Returns the current value of a register.\r
51 #define READ(peripheral, register)          (peripheral->register)\r
52 /// Modifies the current value of a register.\r
53 #define WRITE(peripheral, register, value)  (peripheral->register = value)\r
54 \r
55 /// Maximum number of interrupt sources that can be defined.\r
56 #define MAX_INTERRUPT_SOURCES       7\r
57 \r
58 //------------------------------------------------------------------------------\r
59 //         Local types\r
60 //------------------------------------------------------------------------------\r
61 \r
62 /// Describes a PIO interrupt source, including the PIO instance triggering the\r
63 /// interrupt and the associated interrupt handler.\r
64 typedef struct _InterruptSource {\r
65 \r
66     /// Interrupt source pin.\r
67     const Pin *pPin;\r
68 \r
69     /// Interrupt handler.\r
70     void (*handler)(const Pin *);\r
71 \r
72 } InterruptSource;\r
73 \r
74 //------------------------------------------------------------------------------\r
75 //         Local variables\r
76 //------------------------------------------------------------------------------\r
77 \r
78 /// List of interrupt sources.\r
79 static InterruptSource pSources[MAX_INTERRUPT_SOURCES];\r
80 \r
81 /// Number of currently defined interrupt sources.\r
82 static unsigned int numSources;\r
83 \r
84 //------------------------------------------------------------------------------\r
85 //         Local functions\r
86 //------------------------------------------------------------------------------\r
87 \r
88 //------------------------------------------------------------------------------\r
89 /// Handles all interrupts on the given PIO controller.\r
90 /// \param id  PIO controller ID.\r
91 /// \param pBase  PIO controller base address.\r
92 //------------------------------------------------------------------------------\r
93 void PioInterruptHandler(unsigned int id, AT91S_PIO *pBase)\r
94 {\r
95     unsigned int status;\r
96     unsigned int i;\r
97 \r
98     // Check PIO controller status\r
99     status = pBase->PIO_ISR;\r
100     status &= pBase->PIO_IMR;\r
101     if (status != 0) {\r
102 \r
103         trace_LOG(trace_DEBUG, "-D- PIO interrupt on PIO controller #%d\n\r", id);\r
104 \r
105         // Check all sources\r
106         i = 0;\r
107         while (status != 0) {\r
108 \r
109             // There cannot be an unconfigured source enabled.\r
110             SANITY_CHECK(i < numSources);\r
111 \r
112             // Source if configured on PIOA\r
113             if (pSources[i].pPin->id == id) {\r
114 \r
115                 // Source has PIOs which have changed\r
116                 if ((status & pSources[i].pPin->mask) != 0) {\r
117 \r
118                     trace_LOG(trace_DEBUG, "-D- Interrupt source #%d triggered\n\r", i);\r
119 \r
120                     pSources[i].handler(pSources[i].pPin);\r
121                     status &= ~(pSources[i].pPin->mask);\r
122                 }\r
123             }\r
124             i++;\r
125         }\r
126     }\r
127 }\r
128 \r
129 //------------------------------------------------------------------------------\r
130 /// Generic PIO interrupt handler. Single entry point for interrupts coming\r
131 /// from any PIO controller (PIO A, B, C ...). Dispatches the interrupt to\r
132 /// the user-configured handlers.\r
133 //------------------------------------------------------------------------------\r
134 void InterruptHandler()\r
135 {\r
136 #if defined(AT91C_ID_PIOA)\r
137     // Treat PIOA interrupts\r
138     PioInterruptHandler(AT91C_ID_PIOA, AT91C_BASE_PIOA);\r
139 #endif\r
140 \r
141 #if defined(AT91C_ID_PIOB)\r
142     // Treat PIOB interrupts\r
143     PioInterruptHandler(AT91C_ID_PIOB, AT91C_BASE_PIOB);\r
144 #endif\r
145 \r
146 #if defined(AT91C_ID_PIOC)\r
147     // Treat PIOC interrupts\r
148     PioInterruptHandler(AT91C_ID_PIOC, AT91C_BASE_PIOC);\r
149 #endif\r
150 \r
151 #if defined(AT91C_ID_PIOD)\r
152     // Treat PIOD interrupts\r
153     PioInterruptHandler(AT91C_ID_PIOD, AT91C_BASE_PIOD);\r
154 #endif\r
155 \r
156 #if defined(AT91C_ID_PIOE)\r
157     // Treat PIOE interrupts\r
158     PioInterruptHandler(AT91C_ID_PIOE, AT91C_BASE_PIOE);\r
159 #endif\r
160 \r
161 #if defined(AT91C_ID_PIOABCD)\r
162     // Treat PIOABCD interrupts\r
163     #if !defined(AT91C_ID_PIOA)\r
164         PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOA);\r
165     #endif\r
166     #if !defined(AT91C_ID_PIOB)\r
167         PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOB);\r
168     #endif\r
169     #if !defined(AT91C_ID_PIOC)\r
170         PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOC);\r
171     #endif\r
172     #if !defined(AT91C_ID_PIOD)\r
173         PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOD);\r
174     #endif\r
175 #endif\r
176 \r
177 #if defined(AT91C_ID_PIOABCDE)\r
178     // Treat PIOABCDE interrupts\r
179     #if !defined(AT91C_ID_PIOA)\r
180         PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOA);\r
181     #endif\r
182     #if !defined(AT91C_ID_PIOB)\r
183         PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOB);\r
184     #endif\r
185     #if !defined(AT91C_ID_PIOC)\r
186         PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOC);\r
187     #endif\r
188     #if !defined(AT91C_ID_PIOD)\r
189         PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOD);\r
190     #endif\r
191     #if !defined(AT91C_ID_PIOE)\r
192         PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOE);\r
193     #endif\r
194 #endif\r
195 \r
196 #if defined(AT91C_ID_PIOCDE)\r
197     // Treat PIOCDE interrupts\r
198     #if !defined(AT91C_ID_PIOC)\r
199         PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOC);\r
200     #endif\r
201     #if !defined(AT91C_ID_PIOD)\r
202         PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOD);\r
203     #endif\r
204     #if !defined(AT91C_ID_PIOE)\r
205         PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOE);\r
206     #endif\r
207 #endif\r
208 \r
209 }\r
210 \r
211 //------------------------------------------------------------------------------\r
212 //         Global functions\r
213 //------------------------------------------------------------------------------\r
214 \r
215 //------------------------------------------------------------------------------\r
216 /// Initializes the PIO interrupt management logic.\r
217 /// \param priority  PIO controller interrupts priority.\r
218 //------------------------------------------------------------------------------\r
219 void PIO_InitializeInterrupts(unsigned int priority)\r
220 {\r
221     trace_LOG(trace_DEBUG, "-D- PIO_Initialize()\n\r");\r
222 \r
223     SANITY_CHECK((priority & ~AT91C_AIC_PRIOR) == 0);\r
224 \r
225     // Reset sources\r
226     numSources = 0;\r
227 \r
228 #ifdef AT91C_ID_PIOA\r
229     // Configure PIO interrupt sources\r
230     trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOA\n\r");\r
231     AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA;\r
232     AT91C_BASE_PIOA->PIO_ISR;\r
233     AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;\r
234     AIC_ConfigureIT(AT91C_ID_PIOA, priority, InterruptHandler);\r
235     AIC_EnableIT(AT91C_ID_PIOA);\r
236 #endif\r
237 \r
238 #ifdef AT91C_ID_PIOB\r
239     trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOB\n\r");\r
240     AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB;\r
241     AT91C_BASE_PIOB->PIO_ISR;\r
242     AT91C_BASE_PIOB->PIO_IDR = 0xFFFFFFFF;\r
243     AIC_ConfigureIT(AT91C_ID_PIOB, priority, InterruptHandler);\r
244     AIC_EnableIT(AT91C_ID_PIOB);\r
245 #endif\r
246 \r
247 #ifdef AT91C_ID_PIOC\r
248     trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOC\n\r");\r
249     AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOC;\r
250     AT91C_BASE_PIOC->PIO_ISR;\r
251     AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;\r
252     AIC_ConfigureIT(AT91C_ID_PIOC, priority, InterruptHandler);\r
253     AIC_EnableIT(AT91C_ID_PIOC);\r
254 #endif\r
255 \r
256 #ifdef AT91C_ID_PIOD\r
257     trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOD\n\r");\r
258     AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOD;\r
259     AT91C_BASE_PIOC->PIO_ISR;\r
260     AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;\r
261     AIC_ConfigureIT(AT91C_ID_PIOD, priority, InterruptHandler);\r
262     AIC_EnableIT(AT91C_ID_PIOD);\r
263 #endif\r
264 \r
265 #ifdef AT91C_ID_PIOE\r
266     trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOE\n\r");\r
267     AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOE;\r
268     AT91C_BASE_PIOC->PIO_ISR;\r
269     AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;\r
270     AIC_ConfigureIT(AT91C_ID_PIOE, priority, InterruptHandler);\r
271     AIC_EnableIT(AT91C_ID_PIOE);\r
272 #endif\r
273 \r
274 #if defined(AT91C_ID_PIOABCD)\r
275     // Treat PIOABCD interrupts\r
276     #if !defined(AT91C_ID_PIOA) \\r
277      && !defined(AT91C_ID_PIOB) \\r
278      && !defined(AT91C_ID_PIOC) \\r
279      && !defined(AT91C_ID_PIOD)\r
280 \r
281         trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOABCD\n\r");\r
282         AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOABCD;\r
283         AT91C_BASE_PIOA->PIO_ISR;\r
284         AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;\r
285         AIC_ConfigureIT(AT91C_ID_PIOABCD, priority, InterruptHandler);\r
286         AIC_EnableIT(AT91C_ID_PIOABCD);\r
287     #endif\r
288 #endif\r
289 \r
290 #if defined(AT91C_ID_PIOABCDE)\r
291     // Treat PIOABCDE interrupts\r
292     #if !defined(AT91C_ID_PIOA) \\r
293      && !defined(AT91C_ID_PIOB) \\r
294      && !defined(AT91C_ID_PIOC) \\r
295      && !defined(AT91C_ID_PIOD) \\r
296      && !defined(AT91C_ID_PIOE)\r
297 \r
298         trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOABCDE\n\r");\r
299         AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOABCDE;\r
300         AT91C_BASE_PIOA->PIO_ISR;\r
301         AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;\r
302         AIC_ConfigureIT(AT91C_ID_PIOABCDE, priority, InterruptHandler);\r
303         AIC_EnableIT(AT91C_ID_PIOABCDE);\r
304     #endif\r
305 #endif\r
306 \r
307 #if defined(AT91C_ID_PIOCDE)\r
308     // Treat PIOCDE interrupts\r
309     #if !defined(AT91C_ID_PIOC) \\r
310      && !defined(AT91C_ID_PIOD) \\r
311      && !defined(AT91C_ID_PIOE)\r
312 \r
313         trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOC\n\r");\r
314         AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOCDE;\r
315         AT91C_BASE_PIOC->PIO_ISR;\r
316         AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;\r
317         AIC_ConfigureIT(AT91C_ID_PIOCDE, priority, InterruptHandler);\r
318         AIC_EnableIT(AT91C_ID_PIOCDE);\r
319     #endif\r
320 #endif\r
321 }\r
322 \r
323 //------------------------------------------------------------------------------\r
324 /// Configures an interrupt source.\r
325 /// \param pPin  Interrupt source.\r
326 /// \param handler  Desired interrupt handler for the source.\r
327 //------------------------------------------------------------------------------\r
328 void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *))\r
329 {\r
330     InterruptSource *pSource;\r
331 \r
332     trace_LOG(trace_DEBUG, "-D- PIO_ConfigureIt()\n\r");\r
333 \r
334     SANITY_CHECK(pPin);\r
335     ASSERT(numSources < MAX_INTERRUPT_SOURCES,\r
336            "-F- PIO_ConfigureIt: Increase MAX_INTERRUPT_SOURCES\n\r");\r
337 \r
338     // Define new source\r
339     trace_LOG(trace_DEBUG, "-D- PIO_ConfigureIt: Defining new source #%d.\n\r", numSources);\r
340 \r
341     pSource = &(pSources[numSources]);\r
342     pSource->pPin = pPin;\r
343     pSource->handler = handler;\r
344     numSources++;\r
345 }\r
346 \r
347 //------------------------------------------------------------------------------\r
348 /// Enables the given interrupt source if it has been configured.\r
349 /// \param pPin  Interrupt source to enable.\r
350 //------------------------------------------------------------------------------\r
351 void PIO_EnableIt(const Pin *pPin)\r
352 {\r
353     trace_LOG(trace_DEBUG, "-D- PIO_EnableIt()\n\r");\r
354 \r
355     SANITY_CHECK(pPin);\r
356 \r
357 #ifndef NOASSERT\r
358     unsigned int i = 0;\r
359     unsigned char found = 0;\r
360     while ((i < numSources) && !found) {\r
361 \r
362         if (pSources[i].pPin == pPin) {\r
363 \r
364             found = 1;\r
365         }\r
366         i++;\r
367     }\r
368     ASSERT(found, "-F- PIO_EnableIt: Interrupt source has not been configured\n\r");\r
369 #endif\r
370 \r
371     pPin->pio->PIO_ISR;\r
372     pPin->pio->PIO_IER = pPin->mask;\r
373 }\r
374 \r
375 //------------------------------------------------------------------------------\r
376 /// Disables a given interrupt source.\r
377 /// \param pPin  Interrupt source to disable.\r
378 //------------------------------------------------------------------------------\r
379 void PIO_DisableIt(const Pin *pPin)\r
380 {\r
381     SANITY_CHECK(pPin);\r
382 \r
383     trace_LOG(trace_DEBUG, "-D- PIO_DisableIt()\n\r");\r
384 \r
385     pPin->pio->PIO_IDR = pPin->mask;\r
386 }\r
387 \r