source: rtems/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c @ a5c56af

5
Last change on this file since a5c56af was a5c56af, checked in by Sebastian Huber <sebastian.huber@…>, on 12/15/16 at 14:03:56

bsp/atsam: Move interrupt setup to PIO_Configure()

  • Property mode set to 100644
File size: 8.5 KB
Line 
1/* ---------------------------------------------------------------------------- */
2/*                  Atmel Microcontroller Software Support                      */
3/*                       SAM Software Package License                           */
4/* ---------------------------------------------------------------------------- */
5/* Copyright (c) 2015, Atmel Corporation                                        */
6/*                                                                              */
7/* All rights reserved.                                                         */
8/*                                                                              */
9/* Redistribution and use in source and binary forms, with or without           */
10/* modification, are permitted provided that the following condition is met:    */
11/*                                                                              */
12/* - Redistributions of source code must retain the above copyright notice,     */
13/* this list of conditions and the disclaimer below.                            */
14/*                                                                              */
15/* Atmel's name may not be used to endorse or promote products derived from     */
16/* this software without specific prior written permission.                     */
17/*                                                                              */
18/* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
19/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
20/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
21/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
22/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
23/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
24/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
25/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
26/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
27/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
28/* ---------------------------------------------------------------------------- */
29
30/*
31 * \file
32 */
33
34/*----------------------------------------------------------------------------
35 *        Headers
36 *----------------------------------------------------------------------------*/
37
38#include "chip.h"
39
40#include <rtems/irq-extension.h>
41#include <rtems/sysinit.h>
42#include <bsp/fatal.h>
43
44/*----------------------------------------------------------------------------
45 *        Local definitions
46 *----------------------------------------------------------------------------*/
47
48/* Maximum number of interrupt sources that can be defined. This
49 * constant can be increased, but the current value is the smallest possible
50 * that will be compatible with all existing projects. */
51#define MAX_INTERRUPT_SOURCES       7
52
53/*----------------------------------------------------------------------------
54 *        Local types
55 *----------------------------------------------------------------------------*/
56
57/**
58 * Describes a PIO interrupt source, including the PIO instance triggering the
59 * interrupt and the associated interrupt handler.
60 */
61typedef struct _InterruptSource {
62        /* Pointer to the source pin instance. */
63        const Pin *pPin;
64
65        /* Interrupt handler. */
66        void (*handler)(const Pin *, void *arg);
67
68        void *arg;
69} InterruptSource;
70
71/*----------------------------------------------------------------------------
72 *        Local variables
73 *----------------------------------------------------------------------------*/
74
75/* List of interrupt sources. */
76static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES];
77
78/* Number of currently defined interrupt sources. */
79static uint32_t _dwNumSources = 0;
80
81/*----------------------------------------------------------------------------
82 *        Local Functions
83 *----------------------------------------------------------------------------*/
84
85/**
86 * \brief Handles all interrupts on the given PIO controller.
87 * \param id  PIO controller ID.
88 * \param pPio  PIO controller base address.
89 */
90static void PIO_Interrupt(Pio *pPio, uint32_t id)
91{
92        uint32_t status;
93        size_t i;
94
95        status = pPio->PIO_ISR;
96        status &= pPio->PIO_IMR;
97
98        for (i = 0; status != 0 && i < MAX_INTERRUPT_SOURCES; ++i) {
99                const InterruptSource *is = &_aIntSources[i];
100                const Pin *pin = is->pPin;;
101
102                if (pin->id == id) {
103                        uint32_t mask = pin->mask;
104
105                        if ((status & mask) != 0) {
106                                status &= ~mask;
107                                (*is->handler)(pin, is->arg);
108                        }
109                }
110        }
111}
112
113/*----------------------------------------------------------------------------
114 *        Global Functions
115 *----------------------------------------------------------------------------*/
116
117/**
118 * \brief Parallel IO Controller A interrupt handler
119 * \Redefined PIOA interrupt handler for NVIC interrupt table.
120 */
121static void PIOA_Interrupt(void *arg)
122{
123        PIO_Interrupt(arg, ID_PIOA);
124}
125
126/**
127 * \brief Parallel IO Controller B interrupt handler
128 * \Redefined PIOB interrupt handler for NVIC interrupt table.
129 */
130static void PIOB_Interrupt(void *arg)
131{
132        PIO_Interrupt(arg, ID_PIOB);
133}
134
135/**
136 * \brief Parallel IO Controller C interrupt handler
137 * \Redefined PIOC interrupt handler for NVIC interrupt table.
138 */
139static void PIOC_Interrupt(void *arg)
140{
141        PIO_Interrupt(arg, ID_PIOC);
142}
143
144
145/**
146 * \brief Parallel IO Controller D interrupt handler
147 * \Redefined PIOD interrupt handler for NVIC interrupt table.
148 */
149static void PIOD_Interrupt(void *arg)
150{
151        PIO_Interrupt(arg, ID_PIOD);
152}
153
154/**
155 * \brief Parallel IO Controller E interrupt handler
156 * \Redefined PIOE interrupt handler for NVIC interrupt table.
157 */
158static void PIOE_Interrupt(void *arg)
159{
160        PIO_Interrupt(arg, ID_PIOE);
161}
162
163static void PIO_SysInitializeInterrupts(void)
164{
165        rtems_status_code sc;
166
167        TRACE_DEBUG("PIO_Initialize()\n\r");
168
169        /* Configure PIO interrupt sources */
170        TRACE_DEBUG("PIO_Initialize: Configuring PIOA\n\r");
171        PMC_EnablePeripheral(ID_PIOA);
172        PIOA->PIO_ISR;
173        PIOA->PIO_IDR = 0xFFFFFFFF;
174        sc = rtems_interrupt_handler_install(
175                PIOA_IRQn,
176                "PIO A",
177                RTEMS_INTERRUPT_UNIQUE,
178                PIOA_Interrupt,
179                PIOA
180        );
181        if (sc != RTEMS_SUCCESSFUL) {
182                bsp_fatal(ATSAM_FATAL_PIO_IRQ_A);
183        }
184
185        TRACE_DEBUG("PIO_Initialize: Configuring PIOB\n\r");
186        PMC_EnablePeripheral(ID_PIOB);
187        PIOB->PIO_ISR;
188        PIOB->PIO_IDR = 0xFFFFFFFF;
189        sc = rtems_interrupt_handler_install(
190                PIOB_IRQn,
191                "PIO B",
192                RTEMS_INTERRUPT_UNIQUE,
193                PIOB_Interrupt,
194                PIOB
195        );
196        if (sc != RTEMS_SUCCESSFUL) {
197                bsp_fatal(ATSAM_FATAL_PIO_IRQ_B);
198        }
199
200        TRACE_DEBUG("PIO_Initialize: Configuring PIOC\n\r");
201        PMC_EnablePeripheral(ID_PIOC);
202        PIOC->PIO_ISR;
203        PIOC->PIO_IDR = 0xFFFFFFFF;
204        sc = rtems_interrupt_handler_install(
205                PIOC_IRQn,
206                "PIO C",
207                RTEMS_INTERRUPT_UNIQUE,
208                PIOC_Interrupt,
209                PIOC
210        );
211        if (sc != RTEMS_SUCCESSFUL) {
212                bsp_fatal(ATSAM_FATAL_PIO_IRQ_C);
213        }
214
215        TRACE_DEBUG("PIO_Initialize: Configuring PIOD\n\r");
216        PMC_EnablePeripheral(ID_PIOD);
217        PIOD->PIO_ISR;
218        PIOD->PIO_IDR = 0xFFFFFFFF;
219        sc = rtems_interrupt_handler_install(
220                PIOD_IRQn,
221                "PIO D",
222                RTEMS_INTERRUPT_UNIQUE,
223                PIOD_Interrupt,
224                PIOD
225        );
226        if (sc != RTEMS_SUCCESSFUL) {
227                bsp_fatal(ATSAM_FATAL_PIO_IRQ_D);
228        }
229
230        TRACE_DEBUG("PIO_Initialize: Configuring PIOE\n\r");
231        PMC_EnablePeripheral(ID_PIOE);
232        PIOE->PIO_ISR;
233        PIOE->PIO_IDR = 0xFFFFFFFF;
234        sc = rtems_interrupt_handler_install(
235                PIOE_IRQn,
236                "PIO E",
237                RTEMS_INTERRUPT_UNIQUE,
238                PIOE_Interrupt,
239                PIOE
240        );
241        if (sc != RTEMS_SUCCESSFUL) {
242                bsp_fatal(ATSAM_FATAL_PIO_IRQ_E);
243        }
244}
245
246RTEMS_SYSINIT_ITEM(PIO_SysInitializeInterrupts, RTEMS_SYSINIT_BSP_START,
247    RTEMS_SYSINIT_ORDER_LAST);
248
249/**
250 * Configures a PIO or a group of PIO to generate an interrupt on status
251 * change. The provided interrupt handler will be called with the triggering
252 * pin as its parameter (enabling different pin instances to share the same
253 * handler).
254 * \param pPin  Pointer to a Pin instance.
255 * \param handler  Interrupt handler function pointer.
256 */
257void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *, void *arg),
258    void *arg)
259{
260        InterruptSource *pSource;
261        rtems_interrupt_level level;
262
263        TRACE_DEBUG("PIO_ConfigureIt()\n\r");
264
265        rtems_interrupt_disable(level);
266
267        if (_dwNumSources == MAX_INTERRUPT_SOURCES) {
268                bsp_fatal(ATSAM_FATAL_PIO_CONFIGURE_IT);
269        }
270
271        pSource = &(_aIntSources[_dwNumSources]);
272        pSource->pPin = pPin;
273        pSource->handler = handler;
274        _dwNumSources++;
275
276        rtems_interrupt_enable(level);
277
278        /* Define new source */
279        TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources);
280}
Note: See TracBrowser for help on using the repository browser.