1 /* ----------------------------------------------------------------------------
\r
2 * ATMEL Microcontroller Software Support
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2008, Atmel Corporation
\r
6 * All rights reserved.
\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
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\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
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
30 /// Disable traces for this file
\r
35 //------------------------------------------------------------------------------
\r
37 //------------------------------------------------------------------------------
\r
41 #include <aic/aic.h>
\r
43 #include <utility/assert.h>
\r
44 #include <utility/trace.h>
\r
46 //------------------------------------------------------------------------------
\r
47 // Local definitions
\r
48 //------------------------------------------------------------------------------
\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
55 /// Maximum number of interrupt sources that can be defined.
\r
56 #define MAX_INTERRUPT_SOURCES 7
\r
58 //------------------------------------------------------------------------------
\r
60 //------------------------------------------------------------------------------
\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
66 /// Interrupt source pin.
\r
69 /// Interrupt handler.
\r
70 void (*handler)(const Pin *);
\r
74 //------------------------------------------------------------------------------
\r
76 //------------------------------------------------------------------------------
\r
78 /// List of interrupt sources.
\r
79 static InterruptSource pSources[MAX_INTERRUPT_SOURCES];
\r
81 /// Number of currently defined interrupt sources.
\r
82 static unsigned int numSources;
\r
84 //------------------------------------------------------------------------------
\r
86 //------------------------------------------------------------------------------
\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
95 unsigned int status;
\r
98 // Check PIO controller status
\r
99 status = pBase->PIO_ISR;
\r
100 status &= pBase->PIO_IMR;
\r
103 trace_LOG(trace_DEBUG, "-D- PIO interrupt on PIO controller #%d\n\r", id);
\r
105 // Check all sources
\r
107 while (status != 0) {
\r
109 // There cannot be an unconfigured source enabled.
\r
110 SANITY_CHECK(i < numSources);
\r
112 // Source if configured on PIOA
\r
113 if (pSources[i].pPin->id == id) {
\r
115 // Source has PIOs which have changed
\r
116 if ((status & pSources[i].pPin->mask) != 0) {
\r
118 trace_LOG(trace_DEBUG, "-D- Interrupt source #%d triggered\n\r", i);
\r
120 pSources[i].handler(pSources[i].pPin);
\r
121 status &= ~(pSources[i].pPin->mask);
\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
136 #if defined(AT91C_ID_PIOA)
\r
137 // Treat PIOA interrupts
\r
138 PioInterruptHandler(AT91C_ID_PIOA, AT91C_BASE_PIOA);
\r
141 #if defined(AT91C_ID_PIOB)
\r
142 // Treat PIOB interrupts
\r
143 PioInterruptHandler(AT91C_ID_PIOB, AT91C_BASE_PIOB);
\r
146 #if defined(AT91C_ID_PIOC)
\r
147 // Treat PIOC interrupts
\r
148 PioInterruptHandler(AT91C_ID_PIOC, AT91C_BASE_PIOC);
\r
151 #if defined(AT91C_ID_PIOD)
\r
152 // Treat PIOD interrupts
\r
153 PioInterruptHandler(AT91C_ID_PIOD, AT91C_BASE_PIOD);
\r
156 #if defined(AT91C_ID_PIOE)
\r
157 // Treat PIOE interrupts
\r
158 PioInterruptHandler(AT91C_ID_PIOE, AT91C_BASE_PIOE);
\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
166 #if !defined(AT91C_ID_PIOB)
\r
167 PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOB);
\r
169 #if !defined(AT91C_ID_PIOC)
\r
170 PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOC);
\r
172 #if !defined(AT91C_ID_PIOD)
\r
173 PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOD);
\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
182 #if !defined(AT91C_ID_PIOB)
\r
183 PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOB);
\r
185 #if !defined(AT91C_ID_PIOC)
\r
186 PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOC);
\r
188 #if !defined(AT91C_ID_PIOD)
\r
189 PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOD);
\r
191 #if !defined(AT91C_ID_PIOE)
\r
192 PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOE);
\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
201 #if !defined(AT91C_ID_PIOD)
\r
202 PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOD);
\r
204 #if !defined(AT91C_ID_PIOE)
\r
205 PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOE);
\r
211 //------------------------------------------------------------------------------
\r
212 // Global functions
\r
213 //------------------------------------------------------------------------------
\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
221 trace_LOG(trace_DEBUG, "-D- PIO_Initialize()\n\r");
\r
223 SANITY_CHECK((priority & ~AT91C_AIC_PRIOR) == 0);
\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
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
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
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
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
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
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
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
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
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
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
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
330 InterruptSource *pSource;
\r
332 trace_LOG(trace_DEBUG, "-D- PIO_ConfigureIt()\n\r");
\r
334 SANITY_CHECK(pPin);
\r
335 ASSERT(numSources < MAX_INTERRUPT_SOURCES,
\r
336 "-F- PIO_ConfigureIt: Increase MAX_INTERRUPT_SOURCES\n\r");
\r
338 // Define new source
\r
339 trace_LOG(trace_DEBUG, "-D- PIO_ConfigureIt: Defining new source #%d.\n\r", numSources);
\r
341 pSource = &(pSources[numSources]);
\r
342 pSource->pPin = pPin;
\r
343 pSource->handler = handler;
\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
353 trace_LOG(trace_DEBUG, "-D- PIO_EnableIt()\n\r");
\r
355 SANITY_CHECK(pPin);
\r
358 unsigned int i = 0;
\r
359 unsigned char found = 0;
\r
360 while ((i < numSources) && !found) {
\r
362 if (pSources[i].pPin == pPin) {
\r
368 ASSERT(found, "-F- PIO_EnableIt: Interrupt source has not been configured\n\r");
\r
371 pPin->pio->PIO_ISR;
\r
372 pPin->pio->PIO_IER = pPin->mask;
\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
381 SANITY_CHECK(pPin);
\r
383 trace_LOG(trace_DEBUG, "-D- PIO_DisableIt()\n\r");
\r
385 pPin->pio->PIO_IDR = pPin->mask;
\r