SAMV71 Xplained Ultra Software Package 1.5

pio_it.c

00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /*
00031  * \file
00032  */
00033 
00034 /*----------------------------------------------------------------------------
00035  *        Headers
00036  *----------------------------------------------------------------------------*/
00037 
00038 #include "chip.h"
00039 
00040 #include <assert.h>
00041 
00042 /*----------------------------------------------------------------------------
00043  *        Local definitions
00044  *----------------------------------------------------------------------------*/
00045 
00046 /* Maximum number of interrupt sources that can be defined. This
00047  * constant can be increased, but the current value is the smallest possible
00048  * that will be compatible with all existing projects. */
00049 #define MAX_INTERRUPT_SOURCES       7
00050 
00051 /*----------------------------------------------------------------------------
00052  *        Local types
00053  *----------------------------------------------------------------------------*/
00054 
00055 /**
00056  * Describes a PIO interrupt source, including the PIO instance triggering the
00057  * interrupt and the associated interrupt handler.
00058  */
00059 typedef struct _InterruptSource {
00060     /* Pointer to the source pin instance. */
00061     const Pin *pPin;
00062 
00063     /* Interrupt handler. */
00064     void (*handler)(const Pin *);
00065 } InterruptSource;
00066 
00067 /*----------------------------------------------------------------------------
00068  *        Local variables
00069  *----------------------------------------------------------------------------*/
00070 
00071 /* List of interrupt sources. */
00072 static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES];
00073 
00074 /* Number of currently defined interrupt sources. */
00075 static uint32_t _dwNumSources = 0;
00076 
00077 /*----------------------------------------------------------------------------
00078  *        Local Functions
00079  *----------------------------------------------------------------------------*/
00080 
00081 /**
00082  * \brief Handles all interrupts on the given PIO controller.
00083  * \param id  PIO controller ID.
00084  * \param pPio  PIO controller base address.
00085  */
00086 extern void PioInterruptHandler(uint32_t id, Pio *pPio)
00087 {
00088     uint32_t status;
00089     uint32_t i;
00090 
00091     /* Read PIO controller status */
00092     status = pPio->PIO_ISR;
00093     status &= pPio->PIO_IMR;
00094 
00095     /* Check pending events */
00096     if (status != 0) {
00097         TRACE_DEBUG("PIO interrupt on PIO controller #%d\n\r", id);
00098 
00099         /* Find triggering source */
00100         i = 0;
00101 
00102         while (status != 0) {
00103             /* There cannot be an un-configured source enabled. */
00104             assert(i < _dwNumSources);
00105 
00106             /* Source is configured on the same controller */
00107             if (_aIntSources[i].pPin->id == id) {
00108                 /* Source has PIOs whose statuses have changed */
00109                 if ((status & _aIntSources[i].pPin->mask) != 0) {
00110                     TRACE_DEBUG("Interrupt source #%d triggered\n\r", i);
00111                     _aIntSources[i].handler(_aIntSources[i].pPin);
00112                     status &= ~(_aIntSources[i].pPin->mask);
00113                 }
00114             }
00115 
00116             i++;
00117         }
00118     }
00119 }
00120 
00121 /*----------------------------------------------------------------------------
00122  *        Global Functions
00123  *----------------------------------------------------------------------------*/
00124 
00125 /**
00126  * \brief Parallel IO Controller A interrupt handler
00127  * \Redefined PIOA interrupt handler for NVIC interrupt table.
00128  */
00129 extern void PIOA_Handler(void)
00130 {
00131     PioInterruptHandler(ID_PIOA, PIOA);
00132 }
00133 
00134 /**
00135  * \brief Parallel IO Controller B interrupt handler
00136  * \Redefined PIOB interrupt handler for NVIC interrupt table.
00137  */
00138 extern void PIOB_Handler(void)
00139 {
00140     PioInterruptHandler(ID_PIOB, PIOB);
00141 }
00142 
00143 /**
00144  * \brief Parallel IO Controller C interrupt handler
00145  * \Redefined PIOC interrupt handler for NVIC interrupt table.
00146  */
00147 extern void PIOC_Handler(void)
00148 {
00149     PioInterruptHandler(ID_PIOC, PIOC);
00150 }
00151 
00152 
00153 /**
00154  * \brief Parallel IO Controller D interrupt handler
00155  * \Redefined PIOD interrupt handler for NVIC interrupt table.
00156  */
00157 extern void PIOD_Handler(void)
00158 {
00159     PioInterruptHandler(ID_PIOD, PIOD);
00160 }
00161 
00162 /**
00163  * \brief Parallel IO Controller E interrupt handler
00164  * \Redefined PIOE interrupt handler for NVIC interrupt table.
00165  */
00166 extern void PIOE_Handler(void)
00167 {
00168     PioInterruptHandler(ID_PIOE, PIOE);
00169 }
00170 
00171 /**
00172  * \brief Initializes the PIO interrupt management logic
00173  *
00174  * The desired priority of PIO interrupts must be provided.
00175  * Calling this function multiple times result in the reset of currently
00176  * configured interrupts.
00177  *
00178  * \param priority  PIO controller interrupts priority.
00179  */
00180 extern void PIO_InitializeInterrupts(uint32_t dwPriority)
00181 {
00182     TRACE_DEBUG("PIO_Initialize()\n\r");
00183 
00184     /* Reset sources */
00185     _dwNumSources = 0;
00186 
00187     /* Configure PIO interrupt sources */
00188     TRACE_DEBUG("PIO_Initialize: Configuring PIOA\n\r");
00189     PMC_EnablePeripheral(ID_PIOA);
00190     PIOA->PIO_ISR;
00191     PIOA->PIO_IDR = 0xFFFFFFFF;
00192     NVIC_DisableIRQ(PIOA_IRQn);
00193     NVIC_ClearPendingIRQ(PIOA_IRQn);
00194     NVIC_SetPriority(PIOA_IRQn, dwPriority);
00195     NVIC_EnableIRQ(PIOA_IRQn);
00196 
00197     TRACE_DEBUG("PIO_Initialize: Configuring PIOB\n\r");
00198     PMC_EnablePeripheral(ID_PIOB);
00199     PIOB->PIO_ISR;
00200     PIOB->PIO_IDR = 0xFFFFFFFF;
00201     NVIC_DisableIRQ(PIOB_IRQn);
00202     NVIC_ClearPendingIRQ(PIOB_IRQn);
00203     NVIC_SetPriority(PIOB_IRQn, dwPriority);
00204     NVIC_EnableIRQ(PIOB_IRQn);
00205 
00206     TRACE_DEBUG("PIO_Initialize: Configuring PIOC\n\r");
00207     PMC_EnablePeripheral(ID_PIOC);
00208     PIOC->PIO_ISR;
00209     PIOC->PIO_IDR = 0xFFFFFFFF;
00210     NVIC_DisableIRQ(PIOC_IRQn);
00211     NVIC_ClearPendingIRQ(PIOC_IRQn);
00212     NVIC_SetPriority(PIOC_IRQn, dwPriority);
00213     NVIC_EnableIRQ(PIOC_IRQn);
00214 
00215     TRACE_DEBUG("PIO_Initialize: Configuring PIOD\n\r");
00216     PMC_EnablePeripheral(ID_PIOD);
00217     PIOD->PIO_ISR;
00218     PIOD->PIO_IDR = 0xFFFFFFFF;
00219     NVIC_DisableIRQ(PIOD_IRQn);
00220     NVIC_ClearPendingIRQ(PIOD_IRQn);
00221     NVIC_SetPriority(PIOD_IRQn, dwPriority);
00222     NVIC_EnableIRQ(PIOD_IRQn);
00223 
00224     TRACE_DEBUG("PIO_Initialize: Configuring PIOE\n\r");
00225     PMC_EnablePeripheral(ID_PIOE);
00226     PIOE->PIO_ISR;
00227     PIOE->PIO_IDR = 0xFFFFFFFF;
00228     NVIC_DisableIRQ(PIOE_IRQn);
00229     NVIC_ClearPendingIRQ(PIOE_IRQn);
00230     NVIC_SetPriority(PIOE_IRQn, dwPriority);
00231     NVIC_EnableIRQ(PIOE_IRQn);
00232 }
00233 
00234 /**
00235  * Configures a PIO or a group of PIO to generate an interrupt on status
00236  * change. The provided interrupt handler will be called with the triggering
00237  * pin as its parameter (enabling different pin instances to share the same
00238  * handler).
00239  * \param pPin  Pointer to a Pin instance.
00240  * \param handler  Interrupt handler function pointer.
00241  */
00242 extern void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *))
00243 {
00244     Pio *pio;
00245     InterruptSource *pSource;
00246 
00247     TRACE_DEBUG("PIO_ConfigureIt()\n\r");
00248 
00249     assert(pPin);
00250     pio = pPin->pio;
00251     assert(_dwNumSources < MAX_INTERRUPT_SOURCES);
00252 
00253     /* Define new source */
00254     TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources);
00255 
00256     pSource = &(_aIntSources[_dwNumSources]);
00257     pSource->pPin = pPin;
00258     pSource->handler = handler;
00259     _dwNumSources++;
00260 
00261     /* PIO3 with additional interrupt support
00262      * Configure additional interrupt mode registers */
00263     if (pPin->attribute & PIO_IT_AIME) {
00264         // enable additional interrupt mode
00265         pio->PIO_AIMER  = pPin->mask;
00266 
00267         // if bit field of selected pin is 1, set as Rising Edge/High level detection event
00268         if (pPin->attribute & PIO_IT_RE_OR_HL)
00269             pio->PIO_REHLSR    = pPin->mask;
00270         else
00271             pio->PIO_FELLSR     = pPin->mask;
00272 
00273         /* if bit field of selected pin is 1, set as edge detection source */
00274         if (pPin->attribute & PIO_IT_EDGE)
00275             pio->PIO_ESR     = pPin->mask;
00276         else
00277             pio->PIO_LSR     = pPin->mask;
00278     } else {
00279         /* disable additional interrupt mode */
00280         pio->PIO_AIMDR       = pPin->mask;
00281     }
00282 }
00283 
00284 /**
00285  * Enables the given interrupt source if it has been configured. The status
00286  * register of the corresponding PIO controller is cleared prior to enabling
00287  * the interrupt.
00288  * \param pPin  Interrupt source to enable.
00289  */
00290 extern void PIO_EnableIt(const Pin *pPin)
00291 {
00292     uint32_t i = 0;
00293     uint32_t dwFound = 0;
00294 
00295     TRACE_DEBUG("PIO_EnableIt()\n\r");
00296 
00297     assert(pPin != NULL);
00298 
00299 #ifndef NOASSERT
00300 
00301     while ((i < _dwNumSources) && !dwFound) {
00302         if (_aIntSources[i].pPin == pPin)
00303             dwFound = 1;
00304 
00305         i++;
00306     }
00307 
00308     assert(dwFound != 0);
00309 #endif
00310 
00311     pPin->pio->PIO_ISR;
00312     pPin->pio->PIO_IER = pPin->mask;
00313 }
00314 
00315 /**
00316  * Disables a given interrupt source, with no added side effects.
00317  *
00318  * \param pPin  Interrupt source to disable.
00319  */
00320 extern void PIO_DisableIt(const Pin *pPin)
00321 {
00322     assert(pPin != NULL);
00323 
00324     TRACE_DEBUG("PIO_DisableIt()\n\r");
00325 
00326     pPin->pio->PIO_IDR = pPin->mask;
00327 }
00328 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines