blob: 48403c0f332302a1de2559de898ca4fe490a93d4 [file] [log] [blame]
Christina Quast8be71e42014-12-02 13:06:01 +01001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2008, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30/*
31 * \file
32 */
33
34/*----------------------------------------------------------------------------
35 * Headers
36 *----------------------------------------------------------------------------*/
37
38#include "chip.h"
39
40#include <assert.h>
41
42/*----------------------------------------------------------------------------
43 * Local definitions
44 *----------------------------------------------------------------------------*/
45
46/* Maximum number of interrupt sources that can be defined. This
47 * constant can be increased, but the current value is the smallest possible
48 * that will be compatible with all existing projects. */
49#define MAX_INTERRUPT_SOURCES 7
50
51/*----------------------------------------------------------------------------
52 * Local types
53 *----------------------------------------------------------------------------*/
54
55/**
56 * Describes a PIO interrupt source, including the PIO instance triggering the
57 * interrupt and the associated interrupt handler.
58 */
59typedef struct _InterruptSource
60{
61 /* Pointer to the source pin instance. */
62 const Pin *pPin;
63
64 /* Interrupt handler. */
65 void (*handler)( const Pin* ) ;
66} InterruptSource ;
67
68/*----------------------------------------------------------------------------
69 * Local variables
70 *----------------------------------------------------------------------------*/
71
72/* List of interrupt sources. */
73static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ;
74
75/* Number of currently defined interrupt sources. */
76static uint32_t _dwNumSources = 0;
77
78/*----------------------------------------------------------------------------
79 * Local Functions
80 *----------------------------------------------------------------------------*/
81/*----------------------------------------------------------------------------*/
82/**
83 * \brief Stub, to handling all PIO Capture interrupts, if not defined.
84 */
85/*----------------------------------------------------------------------------*/
86//extern WEAK void PIO_CaptureHandler( void )
87//{
88//}
89
90/**
91 * \brief Handles all interrupts on the given PIO controller.
92 * \param id PIO controller ID.
93 * \param pPio PIO controller base address.
94 */
95extern void PioInterruptHandler( uint32_t id, Pio *pPio )
96{
97 uint32_t status;
98 uint32_t i;
99
100 /* Read PIO controller status */
101 status = pPio->PIO_ISR;
102 status &= pPio->PIO_IMR;
103
104 /* Check pending events */
105 if ( status != 0 )
106 {
Christina Quast061fa6e2015-01-27 15:31:02 +0100107 TRACE_DEBUG( "PIO interrupt on PIO controller #%" PRIu32 "\n\r", id ) ;
Christina Quast8be71e42014-12-02 13:06:01 +0100108
109 /* Find triggering source */
110 i = 0;
111 while ( status != 0 )
112 {
113 /* There cannot be an unconfigured source enabled. */
114 assert(i < _dwNumSources);
115
116 /* Source is configured on the same controller */
117 if (_aIntSources[i].pPin->id == id)
118 {
119 /* Source has PIOs whose statuses have changed */
120 if ( (status & _aIntSources[i].pPin->mask) != 0 )
121 {
Christina Quast061fa6e2015-01-27 15:31:02 +0100122 TRACE_DEBUG( "Interrupt source #%" PRIu32 " triggered\n\r", i ) ;
Christina Quast8be71e42014-12-02 13:06:01 +0100123
124 _aIntSources[i].handler(_aIntSources[i].pPin);
125 status &= ~(_aIntSources[i].pPin->mask);
126 }
127 }
128 i++;
129 }
130 }
131}
132
133/*----------------------------------------------------------------------------
134 * Global Functions
135 *----------------------------------------------------------------------------*/
136
137/**
138 * \brief Parallel IO Controller A interrupt handler
139 * \Redefined PIOA interrupt handler for NVIC interrupt table.
140 */
141extern void PIOA_IrqHandler( void )
142{
143 if ( PIOA->PIO_PCISR != 0 )
144 {
145 PIO_CaptureHandler() ;
146 }
147
148 PioInterruptHandler( ID_PIOA, PIOA ) ;
149}
150
151/**
152 * \brief Parallel IO Controller B interrupt handler
153 * \Redefined PIOB interrupt handler for NVIC interrupt table.
154 */
155extern void PIOB_IrqHandler( void )
156{
157 PioInterruptHandler( ID_PIOB, PIOB ) ;
158}
159
160/**
161 * \brief Parallel IO Controller C interrupt handler
162 * \Redefined PIOC interrupt handler for NVIC interrupt table.
163 */
164extern void PIOC_IrqHandler( void )
165{
166 PioInterruptHandler( ID_PIOC, PIOC ) ;
167}
168
169/**
170 * \brief Initializes the PIO interrupt management logic
171 *
172 * The desired priority of PIO interrupts must be provided.
173 * Calling this function multiple times result in the reset of currently
174 * configured interrupts.
175 *
176 * \param priority PIO controller interrupts priority.
177 */
178extern void PIO_InitializeInterrupts( uint32_t dwPriority )
179{
180 TRACE_DEBUG( "PIO_Initialize()\n\r" ) ;
181
182 /* Reset sources */
183 _dwNumSources = 0 ;
184
185 /* Configure PIO interrupt sources */
186 TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ;
187 PMC_EnablePeripheral( ID_PIOA ) ;
188 PIOA->PIO_ISR ;
189 PIOA->PIO_IDR = 0xFFFFFFFF ;
190 NVIC_DisableIRQ( PIOA_IRQn ) ;
191 NVIC_ClearPendingIRQ( PIOA_IRQn ) ;
192 NVIC_SetPriority( PIOA_IRQn, dwPriority ) ;
193 NVIC_EnableIRQ( PIOA_IRQn ) ;
194
195 TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ;
196 PMC_EnablePeripheral( ID_PIOB ) ;
197 PIOB->PIO_ISR ;
198 PIOB->PIO_IDR = 0xFFFFFFFF ;
199 NVIC_DisableIRQ( PIOB_IRQn ) ;
200 NVIC_ClearPendingIRQ( PIOB_IRQn ) ;
201 NVIC_SetPriority( PIOB_IRQn, dwPriority ) ;
202 NVIC_EnableIRQ( PIOB_IRQn ) ;
203
204 TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ;
205 PMC_EnablePeripheral( ID_PIOC ) ;
206 PIOC->PIO_ISR ;
207 PIOC->PIO_IDR = 0xFFFFFFFF ;
208 NVIC_DisableIRQ( PIOC_IRQn ) ;
209 NVIC_ClearPendingIRQ( PIOC_IRQn ) ;
210 NVIC_SetPriority( PIOC_IRQn, dwPriority ) ;
211 NVIC_EnableIRQ( PIOC_IRQn ) ;
212}
213
214/**
215 * Configures a PIO or a group of PIO to generate an interrupt on status
216 * change. The provided interrupt handler will be called with the triggering
217 * pin as its parameter (enabling different pin instances to share the same
218 * handler).
219 * \param pPin Pointer to a Pin instance.
220 * \param handler Interrupt handler function pointer.
221 */
222extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) )
223{
224 Pio* pio ;
225 InterruptSource* pSource ;
226
227 TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ;
228
229 assert( pPin ) ;
230 pio = pPin->pio ;
231 assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;
232
233 /* Define new source */
Christina Quast061fa6e2015-01-27 15:31:02 +0100234 TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%" PRIu32 ".\n\r", _dwNumSources ) ;
Christina Quast8be71e42014-12-02 13:06:01 +0100235
236 pSource = &(_aIntSources[_dwNumSources]) ;
237 pSource->pPin = pPin ;
238 pSource->handler = handler ;
239 _dwNumSources++ ;
240
241 /* PIO3 with additional interrupt support
242 * Configure additional interrupt mode registers */
243 if ( pPin->attribute & PIO_IT_AIME )
244 {
245 // enable additional interrupt mode
246 pio->PIO_AIMER = pPin->mask ;
247
248 // if bit field of selected pin is 1, set as Rising Edge/High level detection event
249 if ( pPin->attribute & PIO_IT_RE_OR_HL )
250 {
251 pio->PIO_REHLSR = pPin->mask ;
252 }
253 else
254 {
255 pio->PIO_FELLSR = pPin->mask;
256 }
257
258 /* if bit field of selected pin is 1, set as edge detection source */
259 if (pPin->attribute & PIO_IT_EDGE)
260 pio->PIO_ESR = pPin->mask;
261 else
262 pio->PIO_LSR = pPin->mask;
263 }
264 else
265 {
266 /* disable additional interrupt mode */
267 pio->PIO_AIMDR = pPin->mask;
268 }
269}
270
271/**
272 * Enables the given interrupt source if it has been configured. The status
273 * register of the corresponding PIO controller is cleared prior to enabling
274 * the interrupt.
275 * \param pPin Interrupt source to enable.
276 */
277extern void PIO_EnableIt( const Pin *pPin )
278{
279 TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ;
280
281 assert( pPin != NULL ) ;
282
283#ifndef NOASSERT
284 uint32_t i = 0;
285 uint32_t dwFound = 0;
286
287 while ( (i < _dwNumSources) && !dwFound )
288 {
289 if ( _aIntSources[i].pPin == pPin )
290 {
291 dwFound = 1 ;
292 }
293 i++ ;
294 }
295 assert( dwFound != 0 ) ;
296#endif
297
298 pPin->pio->PIO_ISR;
299 pPin->pio->PIO_IER = pPin->mask ;
300}
301
302/**
303 * Disables a given interrupt source, with no added side effects.
304 *
305 * \param pPin Interrupt source to disable.
306 */
307extern void PIO_DisableIt( const Pin *pPin )
308{
309 assert( pPin != NULL ) ;
310
311 TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ;
312
313 pPin->pio->PIO_IDR = pPin->mask;
314}
315