]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/pio_it.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libchip_samv7 / source / pio_it.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2014, 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 /*\r
31  * \file\r
32  */\r
33 \r
34 /*----------------------------------------------------------------------------\r
35  *        Headers\r
36  *----------------------------------------------------------------------------*/\r
37 \r
38 #include "chip.h"\r
39 \r
40 #include <assert.h>\r
41 \r
42 /*----------------------------------------------------------------------------\r
43  *        Local definitions\r
44  *----------------------------------------------------------------------------*/\r
45 \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
50 \r
51 /*----------------------------------------------------------------------------\r
52  *        Local types\r
53  *----------------------------------------------------------------------------*/\r
54 \r
55 /**\r
56  * Describes a PIO interrupt source, including the PIO instance triggering the\r
57  * interrupt and the associated interrupt handler.\r
58  */\r
59 typedef struct _InterruptSource\r
60 {\r
61     /* Pointer to the source pin instance. */\r
62     const Pin *pPin;\r
63 \r
64     /* Interrupt handler. */\r
65     void (*handler)( const Pin* ) ;\r
66 } InterruptSource ;\r
67 \r
68 /*----------------------------------------------------------------------------\r
69  *        Local variables\r
70  *----------------------------------------------------------------------------*/\r
71 \r
72 /* List of interrupt sources. */\r
73 static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ;\r
74 \r
75 /* Number of currently defined interrupt sources. */\r
76 static uint32_t _dwNumSources = 0;\r
77 \r
78 /*----------------------------------------------------------------------------\r
79  *        Local Functions\r
80  *----------------------------------------------------------------------------*/\r
81 \r
82 /**\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
86  */\r
87 extern void PioInterruptHandler( uint32_t id, Pio *pPio )\r
88 {\r
89     uint32_t status;\r
90     uint32_t i;\r
91 \r
92     /* Read PIO controller status */\r
93     status = pPio->PIO_ISR;\r
94     status &= pPio->PIO_IMR;\r
95 \r
96     /* Check pending events */\r
97     if ( status != 0 )\r
98     {\r
99         TRACE_DEBUG( "PIO interrupt on PIO controller #%d\n\r", id ) ;\r
100 \r
101         /* Find triggering source */\r
102         i = 0;\r
103         while ( status != 0 )\r
104         {\r
105             /* There cannot be an unconfigured source enabled. */\r
106             assert(i < _dwNumSources);\r
107 \r
108             /* Source is configured on the same controller */\r
109             if (_aIntSources[i].pPin->id == id)\r
110             {\r
111                 /* Source has PIOs whose statuses have changed */\r
112                 if ( (status & _aIntSources[i].pPin->mask) != 0 )\r
113                 {\r
114                     TRACE_DEBUG( "Interrupt source #%d triggered\n\r", i ) ;\r
115 \r
116                     _aIntSources[i].handler(_aIntSources[i].pPin);\r
117                     status &= ~(_aIntSources[i].pPin->mask);\r
118                 }\r
119             }\r
120             i++;\r
121         }\r
122     }\r
123 }\r
124 \r
125 /*----------------------------------------------------------------------------\r
126  *        Global Functions\r
127  *----------------------------------------------------------------------------*/\r
128 \r
129 /**\r
130  * \brief Parallel IO Controller A interrupt handler\r
131  * \Redefined PIOA interrupt handler for NVIC interrupt table.\r
132  */\r
133 extern void PIOA_Handler( void )\r
134 {\r
135     PioInterruptHandler( ID_PIOA, PIOA ) ;\r
136 }\r
137 \r
138 /**\r
139  * \brief Parallel IO Controller B interrupt handler\r
140  * \Redefined PIOB interrupt handler for NVIC interrupt table.\r
141  */\r
142 extern void PIOB_Handler( void )\r
143 {\r
144     PioInterruptHandler( ID_PIOB, PIOB ) ;\r
145 }\r
146 \r
147 /**\r
148  * \brief Parallel IO Controller C interrupt handler\r
149  * \Redefined PIOC interrupt handler for NVIC interrupt table.\r
150  */\r
151 extern void PIOC_Handler( void )\r
152 {\r
153     PioInterruptHandler( ID_PIOC, PIOC ) ;\r
154 }\r
155 \r
156 \r
157 /**\r
158  * \brief Parallel IO Controller D interrupt handler\r
159  * \Redefined PIOD interrupt handler for NVIC interrupt table.\r
160  */\r
161 extern void PIOD_Handler( void )\r
162 {\r
163     PioInterruptHandler( ID_PIOD, PIOD ) ;\r
164 }\r
165 \r
166 \r
167 /**\r
168  * \brief Parallel IO Controller E interrupt handler\r
169  * \Redefined PIOE interrupt handler for NVIC interrupt table.\r
170  */\r
171 extern void PIOE_Handler( void )\r
172 {\r
173     PioInterruptHandler( ID_PIOE, PIOE ) ;\r
174 }\r
175 \r
176 /**\r
177  * \brief Initializes the PIO interrupt management logic\r
178  *\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
182  *\r
183  * \param priority  PIO controller interrupts priority.\r
184  */\r
185 extern void PIO_InitializeInterrupts( uint32_t dwPriority )\r
186 {\r
187     TRACE_DEBUG( "PIO_Initialize()\n\r" ) ;\r
188 \r
189     /* Reset sources */\r
190     _dwNumSources = 0 ;\r
191 \r
192     /* Configure PIO interrupt sources */\r
193     TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ;\r
194     PMC_EnablePeripheral( ID_PIOA ) ;\r
195     PIOA->PIO_ISR ;\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
201 \r
202     TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ;\r
203     PMC_EnablePeripheral( ID_PIOB ) ;\r
204     PIOB->PIO_ISR ;\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
210 \r
211     TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ;\r
212     PMC_EnablePeripheral( ID_PIOC ) ;\r
213     PIOC->PIO_ISR ;\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
219 \r
220     TRACE_DEBUG( "PIO_Initialize: Configuring PIOD\n\r" ) ;\r
221     PMC_EnablePeripheral( ID_PIOD ) ;\r
222     PIOD->PIO_ISR ;\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
228 \r
229     TRACE_DEBUG( "PIO_Initialize: Configuring PIOE\n\r" ) ;\r
230     PMC_EnablePeripheral( ID_PIOE ) ;\r
231     PIOE->PIO_ISR ;\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
237 }\r
238 \r
239 /**\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
243  * handler).\r
244  * \param pPin  Pointer to a Pin instance.\r
245  * \param handler  Interrupt handler function pointer.\r
246  */\r
247 extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) )\r
248 {\r
249     Pio* pio ;\r
250     InterruptSource* pSource ;\r
251 \r
252     TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ;\r
253 \r
254     assert( pPin ) ;\r
255     pio = pPin->pio ;\r
256     assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;\r
257 \r
258     /* Define new source */\r
259     TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%d.\n\r",  _dwNumSources ) ;\r
260 \r
261     pSource = &(_aIntSources[_dwNumSources]) ;\r
262     pSource->pPin = pPin ;\r
263     pSource->handler = handler ;\r
264     _dwNumSources++ ;\r
265 \r
266     /* PIO3 with additional interrupt support\r
267      * Configure additional interrupt mode registers */\r
268     if ( pPin->attribute & PIO_IT_AIME )\r
269     {\r
270         // enable additional interrupt mode\r
271         pio->PIO_AIMER       = pPin->mask ;\r
272 \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
275         {\r
276             pio->PIO_REHLSR    = pPin->mask ;\r
277         }\r
278         else\r
279         {\r
280             pio->PIO_FELLSR     = pPin->mask;\r
281         }\r
282 \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
286         else\r
287             pio->PIO_LSR     = pPin->mask;\r
288     }\r
289     else\r
290     {\r
291         /* disable additional interrupt mode */\r
292         pio->PIO_AIMDR       = pPin->mask;\r
293     }\r
294 }\r
295 \r
296 /**\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
299  * the interrupt.\r
300  * \param pPin  Interrupt source to enable.\r
301  */\r
302 extern void PIO_EnableIt( const Pin *pPin )\r
303 {\r
304     TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ;\r
305 \r
306     assert( pPin != NULL ) ;\r
307 \r
308 #ifndef NOASSERT\r
309     uint32_t i = 0;\r
310     uint32_t dwFound = 0;\r
311 \r
312     while ( (i < _dwNumSources) && !dwFound )\r
313     {\r
314         if ( _aIntSources[i].pPin == pPin )\r
315         {\r
316             dwFound = 1 ;\r
317         }\r
318         i++ ;\r
319     }\r
320     assert( dwFound != 0 ) ;\r
321 #endif\r
322 \r
323     pPin->pio->PIO_ISR;\r
324     pPin->pio->PIO_IER = pPin->mask ;\r
325 }\r
326 \r
327 /**\r
328  * Disables a given interrupt source, with no added side effects.\r
329  *\r
330  * \param pPin  Interrupt source to disable.\r
331  */\r
332 extern void PIO_DisableIt( const Pin *pPin )\r
333 {\r
334     assert( pPin != NULL ) ;\r
335 \r
336     TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ;\r
337 \r
338     pPin->pio->PIO_IDR = pPin->mask;\r
339 }\r
340 \r