1*1b2596b5SMatthias Ringwald /**
2*1b2596b5SMatthias Ringwald * \file
3*1b2596b5SMatthias Ringwald *
4*1b2596b5SMatthias Ringwald * \brief Parallel Input/Output (PIO) interrupt handler for SAM.
5*1b2596b5SMatthias Ringwald *
6*1b2596b5SMatthias Ringwald * Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
7*1b2596b5SMatthias Ringwald *
8*1b2596b5SMatthias Ringwald * \asf_license_start
9*1b2596b5SMatthias Ringwald *
10*1b2596b5SMatthias Ringwald * \page License
11*1b2596b5SMatthias Ringwald *
12*1b2596b5SMatthias Ringwald * Redistribution and use in source and binary forms, with or without
13*1b2596b5SMatthias Ringwald * modification, are permitted provided that the following conditions are met:
14*1b2596b5SMatthias Ringwald *
15*1b2596b5SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright notice,
16*1b2596b5SMatthias Ringwald * this list of conditions and the following disclaimer.
17*1b2596b5SMatthias Ringwald *
18*1b2596b5SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright notice,
19*1b2596b5SMatthias Ringwald * this list of conditions and the following disclaimer in the documentation
20*1b2596b5SMatthias Ringwald * and/or other materials provided with the distribution.
21*1b2596b5SMatthias Ringwald *
22*1b2596b5SMatthias Ringwald * 3. The name of Atmel may not be used to endorse or promote products derived
23*1b2596b5SMatthias Ringwald * from this software without specific prior written permission.
24*1b2596b5SMatthias Ringwald *
25*1b2596b5SMatthias Ringwald * 4. This software may only be redistributed and used in connection with an
26*1b2596b5SMatthias Ringwald * Atmel microcontroller product.
27*1b2596b5SMatthias Ringwald *
28*1b2596b5SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29*1b2596b5SMatthias Ringwald * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30*1b2596b5SMatthias Ringwald * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31*1b2596b5SMatthias Ringwald * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32*1b2596b5SMatthias Ringwald * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33*1b2596b5SMatthias Ringwald * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34*1b2596b5SMatthias Ringwald * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35*1b2596b5SMatthias Ringwald * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36*1b2596b5SMatthias Ringwald * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37*1b2596b5SMatthias Ringwald * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38*1b2596b5SMatthias Ringwald * POSSIBILITY OF SUCH DAMAGE.
39*1b2596b5SMatthias Ringwald *
40*1b2596b5SMatthias Ringwald * \asf_license_stop
41*1b2596b5SMatthias Ringwald *
42*1b2596b5SMatthias Ringwald */
43*1b2596b5SMatthias Ringwald /*
44*1b2596b5SMatthias Ringwald * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45*1b2596b5SMatthias Ringwald */
46*1b2596b5SMatthias Ringwald
47*1b2596b5SMatthias Ringwald #include "pio.h"
48*1b2596b5SMatthias Ringwald #include "pio_handler.h"
49*1b2596b5SMatthias Ringwald
50*1b2596b5SMatthias Ringwald /**
51*1b2596b5SMatthias Ringwald * Maximum number of interrupt sources that can be defined. This
52*1b2596b5SMatthias Ringwald * constant can be increased, but the current value is the smallest possible one
53*1b2596b5SMatthias Ringwald * that will be compatible with all existing projects.
54*1b2596b5SMatthias Ringwald */
55*1b2596b5SMatthias Ringwald #define MAX_INTERRUPT_SOURCES 7
56*1b2596b5SMatthias Ringwald
57*1b2596b5SMatthias Ringwald /**
58*1b2596b5SMatthias Ringwald * Describes a PIO interrupt source, including the PIO instance triggering the
59*1b2596b5SMatthias Ringwald * interrupt and the associated interrupt handler.
60*1b2596b5SMatthias Ringwald */
61*1b2596b5SMatthias Ringwald struct s_interrupt_source {
62*1b2596b5SMatthias Ringwald uint32_t id;
63*1b2596b5SMatthias Ringwald uint32_t mask;
64*1b2596b5SMatthias Ringwald uint32_t attr;
65*1b2596b5SMatthias Ringwald
66*1b2596b5SMatthias Ringwald /* Interrupt handler. */
67*1b2596b5SMatthias Ringwald void (*handler) (const uint32_t, const uint32_t);
68*1b2596b5SMatthias Ringwald };
69*1b2596b5SMatthias Ringwald
70*1b2596b5SMatthias Ringwald
71*1b2596b5SMatthias Ringwald /* List of interrupt sources. */
72*1b2596b5SMatthias Ringwald static struct s_interrupt_source gs_interrupt_sources[MAX_INTERRUPT_SOURCES];
73*1b2596b5SMatthias Ringwald
74*1b2596b5SMatthias Ringwald /* Number of currently defined interrupt sources. */
75*1b2596b5SMatthias Ringwald static uint32_t gs_ul_nb_sources = 0;
76*1b2596b5SMatthias Ringwald
77*1b2596b5SMatthias Ringwald #if (SAM3S || SAM4S || SAM4E)
78*1b2596b5SMatthias Ringwald /* PIO Capture handler */
79*1b2596b5SMatthias Ringwald static void (*pio_capture_handler)(Pio *) = NULL;
80*1b2596b5SMatthias Ringwald extern uint32_t pio_capture_enable_flag;
81*1b2596b5SMatthias Ringwald #endif
82*1b2596b5SMatthias Ringwald
83*1b2596b5SMatthias Ringwald /**
84*1b2596b5SMatthias Ringwald * \brief Process an interrupt request on the given PIO controller.
85*1b2596b5SMatthias Ringwald *
86*1b2596b5SMatthias Ringwald * \param p_pio PIO controller base address.
87*1b2596b5SMatthias Ringwald * \param ul_id PIO controller ID.
88*1b2596b5SMatthias Ringwald */
pio_handler_process(Pio * p_pio,uint32_t ul_id)89*1b2596b5SMatthias Ringwald void pio_handler_process(Pio *p_pio, uint32_t ul_id)
90*1b2596b5SMatthias Ringwald {
91*1b2596b5SMatthias Ringwald uint32_t status;
92*1b2596b5SMatthias Ringwald uint32_t i;
93*1b2596b5SMatthias Ringwald
94*1b2596b5SMatthias Ringwald /* Read PIO controller status */
95*1b2596b5SMatthias Ringwald status = pio_get_interrupt_status(p_pio);
96*1b2596b5SMatthias Ringwald status &= pio_get_interrupt_mask(p_pio);
97*1b2596b5SMatthias Ringwald
98*1b2596b5SMatthias Ringwald /* Check pending events */
99*1b2596b5SMatthias Ringwald if (status != 0) {
100*1b2596b5SMatthias Ringwald /* Find triggering source */
101*1b2596b5SMatthias Ringwald i = 0;
102*1b2596b5SMatthias Ringwald while (status != 0) {
103*1b2596b5SMatthias Ringwald /* Source is configured on the same controller */
104*1b2596b5SMatthias Ringwald if (gs_interrupt_sources[i].id == ul_id) {
105*1b2596b5SMatthias Ringwald /* Source has PIOs whose statuses have changed */
106*1b2596b5SMatthias Ringwald if ((status & gs_interrupt_sources[i].mask) != 0) {
107*1b2596b5SMatthias Ringwald gs_interrupt_sources[i].handler(gs_interrupt_sources[i].id,
108*1b2596b5SMatthias Ringwald gs_interrupt_sources[i].mask);
109*1b2596b5SMatthias Ringwald status &= ~(gs_interrupt_sources[i].mask);
110*1b2596b5SMatthias Ringwald }
111*1b2596b5SMatthias Ringwald }
112*1b2596b5SMatthias Ringwald i++;
113*1b2596b5SMatthias Ringwald if (i >= MAX_INTERRUPT_SOURCES) {
114*1b2596b5SMatthias Ringwald break;
115*1b2596b5SMatthias Ringwald }
116*1b2596b5SMatthias Ringwald }
117*1b2596b5SMatthias Ringwald }
118*1b2596b5SMatthias Ringwald
119*1b2596b5SMatthias Ringwald /* Check capture events */
120*1b2596b5SMatthias Ringwald #if (SAM3S || SAM4S || SAM4E)
121*1b2596b5SMatthias Ringwald if (pio_capture_enable_flag) {
122*1b2596b5SMatthias Ringwald if (pio_capture_handler) {
123*1b2596b5SMatthias Ringwald pio_capture_handler(p_pio);
124*1b2596b5SMatthias Ringwald }
125*1b2596b5SMatthias Ringwald }
126*1b2596b5SMatthias Ringwald #endif
127*1b2596b5SMatthias Ringwald }
128*1b2596b5SMatthias Ringwald
129*1b2596b5SMatthias Ringwald /**
130*1b2596b5SMatthias Ringwald * \brief Set an interrupt handler for the provided pins.
131*1b2596b5SMatthias Ringwald * The provided handler will be called with the triggering pin as its parameter
132*1b2596b5SMatthias Ringwald * as soon as an interrupt is detected.
133*1b2596b5SMatthias Ringwald *
134*1b2596b5SMatthias Ringwald * \param p_pio PIO controller base address.
135*1b2596b5SMatthias Ringwald * \param ul_id PIO ID.
136*1b2596b5SMatthias Ringwald * \param ul_mask Pins (bit mask) to configure.
137*1b2596b5SMatthias Ringwald * \param ul_attr Pins attribute to configure.
138*1b2596b5SMatthias Ringwald * \param p_handler Interrupt handler function pointer.
139*1b2596b5SMatthias Ringwald *
140*1b2596b5SMatthias Ringwald * \return 0 if successful, 1 if the maximum number of sources has been defined.
141*1b2596b5SMatthias Ringwald */
pio_handler_set(Pio * p_pio,uint32_t ul_id,uint32_t ul_mask,uint32_t ul_attr,void (* p_handler)(uint32_t,uint32_t))142*1b2596b5SMatthias Ringwald uint32_t pio_handler_set(Pio *p_pio, uint32_t ul_id, uint32_t ul_mask,
143*1b2596b5SMatthias Ringwald uint32_t ul_attr, void (*p_handler) (uint32_t, uint32_t))
144*1b2596b5SMatthias Ringwald {
145*1b2596b5SMatthias Ringwald struct s_interrupt_source *pSource;
146*1b2596b5SMatthias Ringwald
147*1b2596b5SMatthias Ringwald if (gs_ul_nb_sources >= MAX_INTERRUPT_SOURCES)
148*1b2596b5SMatthias Ringwald return 1;
149*1b2596b5SMatthias Ringwald
150*1b2596b5SMatthias Ringwald /* Define new source */
151*1b2596b5SMatthias Ringwald pSource = &(gs_interrupt_sources[gs_ul_nb_sources]);
152*1b2596b5SMatthias Ringwald pSource->id = ul_id;
153*1b2596b5SMatthias Ringwald pSource->mask = ul_mask;
154*1b2596b5SMatthias Ringwald pSource->attr = ul_attr;
155*1b2596b5SMatthias Ringwald pSource->handler = p_handler;
156*1b2596b5SMatthias Ringwald gs_ul_nb_sources++;
157*1b2596b5SMatthias Ringwald
158*1b2596b5SMatthias Ringwald /* Configure interrupt mode */
159*1b2596b5SMatthias Ringwald pio_configure_interrupt(p_pio, ul_mask, ul_attr);
160*1b2596b5SMatthias Ringwald
161*1b2596b5SMatthias Ringwald return 0;
162*1b2596b5SMatthias Ringwald }
163*1b2596b5SMatthias Ringwald
164*1b2596b5SMatthias Ringwald #if (SAM3S || SAM4S || SAM4E)
165*1b2596b5SMatthias Ringwald /**
166*1b2596b5SMatthias Ringwald * \brief Set a capture interrupt handler for all PIO.
167*1b2596b5SMatthias Ringwald *
168*1b2596b5SMatthias Ringwald * The handler will be called with the triggering PIO as its parameter
169*1b2596b5SMatthias Ringwald * as soon as an interrupt is detected.
170*1b2596b5SMatthias Ringwald *
171*1b2596b5SMatthias Ringwald * \param p_handler Interrupt handler function pointer.
172*1b2596b5SMatthias Ringwald *
173*1b2596b5SMatthias Ringwald */
pio_capture_handler_set(void (* p_handler)(Pio *))174*1b2596b5SMatthias Ringwald void pio_capture_handler_set(void (*p_handler)(Pio *))
175*1b2596b5SMatthias Ringwald {
176*1b2596b5SMatthias Ringwald pio_capture_handler = p_handler;
177*1b2596b5SMatthias Ringwald }
178*1b2596b5SMatthias Ringwald #endif
179*1b2596b5SMatthias Ringwald
180*1b2596b5SMatthias Ringwald #ifdef ID_PIOA
181*1b2596b5SMatthias Ringwald /**
182*1b2596b5SMatthias Ringwald * \brief Set an interrupt handler for the specified pin.
183*1b2596b5SMatthias Ringwald * The provided handler will be called with the triggering pin as its parameter
184*1b2596b5SMatthias Ringwald * as soon as an interrupt is detected.
185*1b2596b5SMatthias Ringwald *
186*1b2596b5SMatthias Ringwald * \param ul_pin Pin index to configure.
187*1b2596b5SMatthias Ringwald * \param ul_flag Pin flag.
188*1b2596b5SMatthias Ringwald * \param p_handler Interrupt handler function pointer.
189*1b2596b5SMatthias Ringwald *
190*1b2596b5SMatthias Ringwald * \return 0 if successful, 1 if the maximum number of sources has been defined.
191*1b2596b5SMatthias Ringwald */
pio_handler_set_pin(uint32_t ul_pin,uint32_t ul_flag,void (* p_handler)(uint32_t,uint32_t))192*1b2596b5SMatthias Ringwald uint32_t pio_handler_set_pin(uint32_t ul_pin, uint32_t ul_flag,
193*1b2596b5SMatthias Ringwald void (*p_handler) (uint32_t, uint32_t))
194*1b2596b5SMatthias Ringwald {
195*1b2596b5SMatthias Ringwald Pio *p_pio = pio_get_pin_group(ul_pin);
196*1b2596b5SMatthias Ringwald uint32_t group_id = pio_get_pin_group_id(ul_pin);
197*1b2596b5SMatthias Ringwald uint32_t group_mask = pio_get_pin_group_mask(ul_pin);
198*1b2596b5SMatthias Ringwald
199*1b2596b5SMatthias Ringwald return pio_handler_set(p_pio, group_id, group_mask, ul_flag, p_handler);
200*1b2596b5SMatthias Ringwald }
201*1b2596b5SMatthias Ringwald
202*1b2596b5SMatthias Ringwald /**
203*1b2596b5SMatthias Ringwald * \brief Parallel IO Controller A interrupt handler.
204*1b2596b5SMatthias Ringwald * Redefined PIOA interrupt handler for NVIC interrupt table.
205*1b2596b5SMatthias Ringwald */
PIOA_Handler(void)206*1b2596b5SMatthias Ringwald void PIOA_Handler(void)
207*1b2596b5SMatthias Ringwald {
208*1b2596b5SMatthias Ringwald pio_handler_process(PIOA, ID_PIOA);
209*1b2596b5SMatthias Ringwald }
210*1b2596b5SMatthias Ringwald #endif
211*1b2596b5SMatthias Ringwald
212*1b2596b5SMatthias Ringwald #ifdef ID_PIOB
213*1b2596b5SMatthias Ringwald /**
214*1b2596b5SMatthias Ringwald * \brief Parallel IO Controller B interrupt handler
215*1b2596b5SMatthias Ringwald * Redefined PIOB interrupt handler for NVIC interrupt table.
216*1b2596b5SMatthias Ringwald */
PIOB_Handler(void)217*1b2596b5SMatthias Ringwald void PIOB_Handler(void)
218*1b2596b5SMatthias Ringwald {
219*1b2596b5SMatthias Ringwald pio_handler_process(PIOB, ID_PIOB);
220*1b2596b5SMatthias Ringwald }
221*1b2596b5SMatthias Ringwald #endif
222*1b2596b5SMatthias Ringwald
223*1b2596b5SMatthias Ringwald #ifdef ID_PIOC
224*1b2596b5SMatthias Ringwald /**
225*1b2596b5SMatthias Ringwald * \brief Parallel IO Controller C interrupt handler.
226*1b2596b5SMatthias Ringwald * Redefined PIOC interrupt handler for NVIC interrupt table.
227*1b2596b5SMatthias Ringwald */
PIOC_Handler(void)228*1b2596b5SMatthias Ringwald void PIOC_Handler(void)
229*1b2596b5SMatthias Ringwald {
230*1b2596b5SMatthias Ringwald pio_handler_process(PIOC, ID_PIOC);
231*1b2596b5SMatthias Ringwald }
232*1b2596b5SMatthias Ringwald #endif
233*1b2596b5SMatthias Ringwald
234*1b2596b5SMatthias Ringwald #ifdef ID_PIOD
235*1b2596b5SMatthias Ringwald /**
236*1b2596b5SMatthias Ringwald * \brief Parallel IO Controller D interrupt handler.
237*1b2596b5SMatthias Ringwald * Redefined PIOD interrupt handler for NVIC interrupt table.
238*1b2596b5SMatthias Ringwald */
PIOD_Handler(void)239*1b2596b5SMatthias Ringwald void PIOD_Handler(void)
240*1b2596b5SMatthias Ringwald {
241*1b2596b5SMatthias Ringwald pio_handler_process(PIOD, ID_PIOD);
242*1b2596b5SMatthias Ringwald }
243*1b2596b5SMatthias Ringwald #endif
244*1b2596b5SMatthias Ringwald
245*1b2596b5SMatthias Ringwald #ifdef ID_PIOE
246*1b2596b5SMatthias Ringwald /**
247*1b2596b5SMatthias Ringwald * \brief Parallel IO Controller E interrupt handler.
248*1b2596b5SMatthias Ringwald * Redefined PIOE interrupt handler for NVIC interrupt table.
249*1b2596b5SMatthias Ringwald */
PIOE_Handler(void)250*1b2596b5SMatthias Ringwald void PIOE_Handler(void)
251*1b2596b5SMatthias Ringwald {
252*1b2596b5SMatthias Ringwald pio_handler_process(PIOE, ID_PIOE);
253*1b2596b5SMatthias Ringwald }
254*1b2596b5SMatthias Ringwald #endif
255*1b2596b5SMatthias Ringwald
256*1b2596b5SMatthias Ringwald #ifdef ID_PIOF
257*1b2596b5SMatthias Ringwald /**
258*1b2596b5SMatthias Ringwald * \brief Parallel IO Controller F interrupt handler.
259*1b2596b5SMatthias Ringwald * Redefined PIOF interrupt handler for NVIC interrupt table.
260*1b2596b5SMatthias Ringwald */
PIOF_Handler(void)261*1b2596b5SMatthias Ringwald void PIOF_Handler(void)
262*1b2596b5SMatthias Ringwald {
263*1b2596b5SMatthias Ringwald pio_handler_process(PIOF, ID_PIOF);
264*1b2596b5SMatthias Ringwald }
265*1b2596b5SMatthias Ringwald #endif
266*1b2596b5SMatthias Ringwald
267*1b2596b5SMatthias Ringwald /**
268*1b2596b5SMatthias Ringwald * \brief Initialize PIO interrupt management logic.
269*1b2596b5SMatthias Ringwald *
270*1b2596b5SMatthias Ringwald * \param p_pio PIO controller base address.
271*1b2596b5SMatthias Ringwald * \param ul_irqn NVIC line number.
272*1b2596b5SMatthias Ringwald * \param ul_priority PIO controller interrupts priority.
273*1b2596b5SMatthias Ringwald */
pio_handler_set_priority(Pio * p_pio,IRQn_Type ul_irqn,uint32_t ul_priority)274*1b2596b5SMatthias Ringwald void pio_handler_set_priority(Pio *p_pio, IRQn_Type ul_irqn, uint32_t ul_priority)
275*1b2596b5SMatthias Ringwald {
276*1b2596b5SMatthias Ringwald uint32_t bitmask = 0;
277*1b2596b5SMatthias Ringwald
278*1b2596b5SMatthias Ringwald bitmask = pio_get_interrupt_mask(p_pio);
279*1b2596b5SMatthias Ringwald pio_disable_interrupt(p_pio, 0xFFFFFFFF);
280*1b2596b5SMatthias Ringwald pio_get_interrupt_status(p_pio);
281*1b2596b5SMatthias Ringwald NVIC_DisableIRQ(ul_irqn);
282*1b2596b5SMatthias Ringwald NVIC_ClearPendingIRQ(ul_irqn);
283*1b2596b5SMatthias Ringwald NVIC_SetPriority(ul_irqn, ul_priority);
284*1b2596b5SMatthias Ringwald NVIC_EnableIRQ(ul_irqn);
285*1b2596b5SMatthias Ringwald pio_enable_interrupt(p_pio, bitmask);
286*1b2596b5SMatthias Ringwald }
287