1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2014, 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
34 /*----------------------------------------------------------------------------
\r
36 *----------------------------------------------------------------------------*/
\r
42 /*----------------------------------------------------------------------------
\r
44 *----------------------------------------------------------------------------*/
\r
46 /* Maximum number of interrupt sources that can be defined. This
\r
47 * constant can be increased, but the current value is the smallest possible
\r
48 * that will be compatible with all existing projects. */
\r
49 #define MAX_INTERRUPT_SOURCES 7
\r
51 /*----------------------------------------------------------------------------
\r
53 *----------------------------------------------------------------------------*/
\r
56 * Describes a PIO interrupt source, including the PIO instance triggering the
\r
57 * interrupt and the associated interrupt handler.
\r
59 typedef struct _InterruptSource
\r
61 /* Pointer to the source pin instance. */
\r
64 /* Interrupt handler. */
\r
65 void (*handler)( const Pin* ) ;
\r
68 /*----------------------------------------------------------------------------
\r
70 *----------------------------------------------------------------------------*/
\r
72 /* List of interrupt sources. */
\r
73 static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ;
\r
75 /* Number of currently defined interrupt sources. */
\r
76 static uint32_t _dwNumSources = 0;
\r
78 /*----------------------------------------------------------------------------
\r
80 *----------------------------------------------------------------------------*/
\r
83 * \brief Handles all interrupts on the given PIO controller.
\r
84 * \param id PIO controller ID.
\r
85 * \param pPio PIO controller base address.
\r
87 extern void PioInterruptHandler( uint32_t id, Pio *pPio )
\r
92 /* Read PIO controller status */
\r
93 status = pPio->PIO_ISR;
\r
94 status &= pPio->PIO_IMR;
\r
96 /* Check pending events */
\r
99 TRACE_DEBUG( "PIO interrupt on PIO controller #%d\n\r", id ) ;
\r
101 /* Find triggering source */
\r
103 while ( status != 0 )
\r
105 /* There cannot be an unconfigured source enabled. */
\r
106 assert(i < _dwNumSources);
\r
108 /* Source is configured on the same controller */
\r
109 if (_aIntSources[i].pPin->id == id)
\r
111 /* Source has PIOs whose statuses have changed */
\r
112 if ( (status & _aIntSources[i].pPin->mask) != 0 )
\r
114 TRACE_DEBUG( "Interrupt source #%d triggered\n\r", i ) ;
\r
116 _aIntSources[i].handler(_aIntSources[i].pPin);
\r
117 status &= ~(_aIntSources[i].pPin->mask);
\r
125 /*----------------------------------------------------------------------------
\r
127 *----------------------------------------------------------------------------*/
\r
130 * \brief Parallel IO Controller A interrupt handler
\r
131 * \Redefined PIOA interrupt handler for NVIC interrupt table.
\r
133 extern void PIOA_Handler( void )
\r
135 PioInterruptHandler( ID_PIOA, PIOA ) ;
\r
139 * \brief Parallel IO Controller B interrupt handler
\r
140 * \Redefined PIOB interrupt handler for NVIC interrupt table.
\r
142 extern void PIOB_Handler( void )
\r
144 PioInterruptHandler( ID_PIOB, PIOB ) ;
\r
148 * \brief Parallel IO Controller C interrupt handler
\r
149 * \Redefined PIOC interrupt handler for NVIC interrupt table.
\r
151 extern void PIOC_Handler( void )
\r
153 PioInterruptHandler( ID_PIOC, PIOC ) ;
\r
158 * \brief Parallel IO Controller D interrupt handler
\r
159 * \Redefined PIOD interrupt handler for NVIC interrupt table.
\r
161 extern void PIOD_Handler( void )
\r
163 PioInterruptHandler( ID_PIOD, PIOD ) ;
\r
168 * \brief Parallel IO Controller E interrupt handler
\r
169 * \Redefined PIOE interrupt handler for NVIC interrupt table.
\r
171 extern void PIOE_Handler( void )
\r
173 PioInterruptHandler( ID_PIOE, PIOE ) ;
\r
177 * \brief Initializes the PIO interrupt management logic
\r
179 * The desired priority of PIO interrupts must be provided.
\r
180 * Calling this function multiple times result in the reset of currently
\r
181 * configured interrupts.
\r
183 * \param priority PIO controller interrupts priority.
\r
185 extern void PIO_InitializeInterrupts( uint32_t dwPriority )
\r
187 TRACE_DEBUG( "PIO_Initialize()\n\r" ) ;
\r
189 /* Reset sources */
\r
190 _dwNumSources = 0 ;
\r
192 /* Configure PIO interrupt sources */
\r
193 TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ;
\r
194 PMC_EnablePeripheral( ID_PIOA ) ;
\r
196 PIOA->PIO_IDR = 0xFFFFFFFF ;
\r
197 NVIC_DisableIRQ( PIOA_IRQn ) ;
\r
198 NVIC_ClearPendingIRQ( PIOA_IRQn ) ;
\r
199 NVIC_SetPriority( PIOA_IRQn, dwPriority ) ;
\r
200 NVIC_EnableIRQ( PIOA_IRQn ) ;
\r
202 TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ;
\r
203 PMC_EnablePeripheral( ID_PIOB ) ;
\r
205 PIOB->PIO_IDR = 0xFFFFFFFF ;
\r
206 NVIC_DisableIRQ( PIOB_IRQn ) ;
\r
207 NVIC_ClearPendingIRQ( PIOB_IRQn ) ;
\r
208 NVIC_SetPriority( PIOB_IRQn, dwPriority ) ;
\r
209 NVIC_EnableIRQ( PIOB_IRQn ) ;
\r
211 TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ;
\r
212 PMC_EnablePeripheral( ID_PIOC ) ;
\r
214 PIOC->PIO_IDR = 0xFFFFFFFF ;
\r
215 NVIC_DisableIRQ( PIOC_IRQn ) ;
\r
216 NVIC_ClearPendingIRQ( PIOC_IRQn ) ;
\r
217 NVIC_SetPriority( PIOC_IRQn, dwPriority ) ;
\r
218 NVIC_EnableIRQ( PIOC_IRQn ) ;
\r
220 TRACE_DEBUG( "PIO_Initialize: Configuring PIOD\n\r" ) ;
\r
221 PMC_EnablePeripheral( ID_PIOD ) ;
\r
223 PIOD->PIO_IDR = 0xFFFFFFFF ;
\r
224 NVIC_DisableIRQ( PIOD_IRQn ) ;
\r
225 NVIC_ClearPendingIRQ( PIOD_IRQn ) ;
\r
226 NVIC_SetPriority( PIOD_IRQn, dwPriority ) ;
\r
227 NVIC_EnableIRQ( PIOD_IRQn ) ;
\r
229 TRACE_DEBUG( "PIO_Initialize: Configuring PIOE\n\r" ) ;
\r
230 PMC_EnablePeripheral( ID_PIOE ) ;
\r
232 PIOE->PIO_IDR = 0xFFFFFFFF ;
\r
233 NVIC_DisableIRQ( PIOE_IRQn ) ;
\r
234 NVIC_ClearPendingIRQ( PIOE_IRQn ) ;
\r
235 NVIC_SetPriority( PIOE_IRQn, dwPriority ) ;
\r
236 NVIC_EnableIRQ( PIOE_IRQn ) ;
\r
240 * Configures a PIO or a group of PIO to generate an interrupt on status
\r
241 * change. The provided interrupt handler will be called with the triggering
\r
242 * pin as its parameter (enabling different pin instances to share the same
\r
244 * \param pPin Pointer to a Pin instance.
\r
245 * \param handler Interrupt handler function pointer.
\r
247 extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) )
\r
250 InterruptSource* pSource ;
\r
252 TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ;
\r
256 assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;
\r
258 /* Define new source */
\r
259 TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources ) ;
\r
261 pSource = &(_aIntSources[_dwNumSources]) ;
\r
262 pSource->pPin = pPin ;
\r
263 pSource->handler = handler ;
\r
266 /* PIO3 with additional interrupt support
\r
267 * Configure additional interrupt mode registers */
\r
268 if ( pPin->attribute & PIO_IT_AIME )
\r
270 // enable additional interrupt mode
\r
271 pio->PIO_AIMER = pPin->mask ;
\r
273 // if bit field of selected pin is 1, set as Rising Edge/High level detection event
\r
274 if ( pPin->attribute & PIO_IT_RE_OR_HL )
\r
276 pio->PIO_REHLSR = pPin->mask ;
\r
280 pio->PIO_FELLSR = pPin->mask;
\r
283 /* if bit field of selected pin is 1, set as edge detection source */
\r
284 if (pPin->attribute & PIO_IT_EDGE)
\r
285 pio->PIO_ESR = pPin->mask;
\r
287 pio->PIO_LSR = pPin->mask;
\r
291 /* disable additional interrupt mode */
\r
292 pio->PIO_AIMDR = pPin->mask;
\r
297 * Enables the given interrupt source if it has been configured. The status
\r
298 * register of the corresponding PIO controller is cleared prior to enabling
\r
300 * \param pPin Interrupt source to enable.
\r
302 extern void PIO_EnableIt( const Pin *pPin )
\r
304 TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ;
\r
306 assert( pPin != NULL ) ;
\r
310 uint32_t dwFound = 0;
\r
312 while ( (i < _dwNumSources) && !dwFound )
\r
314 if ( _aIntSources[i].pPin == pPin )
\r
320 assert( dwFound != 0 ) ;
\r
323 pPin->pio->PIO_ISR;
\r
324 pPin->pio->PIO_IER = pPin->mask ;
\r
328 * Disables a given interrupt source, with no added side effects.
\r
330 * \param pPin Interrupt source to disable.
\r
332 extern void PIO_DisableIt( const Pin *pPin )
\r
334 assert( pPin != NULL ) ;
\r
336 TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ;
\r
338 pPin->pio->PIO_IDR = pPin->mask;
\r