SAMV71 Xplained Ultra Software Package 1.3

pio_it.c

00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2014, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
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 {
00061     /* Pointer to the source pin instance. */
00062     const Pin *pPin;
00063 
00064     /* Interrupt handler. */
00065     void (*handler)( const Pin* ) ;
00066 } InterruptSource ;
00067 
00068 /*----------------------------------------------------------------------------
00069  *        Local variables
00070  *----------------------------------------------------------------------------*/
00071 
00072 /* List of interrupt sources. */
00073 static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ;
00074 
00075 /* Number of currently defined interrupt sources. */
00076 static uint32_t _dwNumSources = 0;
00077 
00078 /*----------------------------------------------------------------------------
00079  *        Local Functions
00080  *----------------------------------------------------------------------------*/
00081 
00082 /**
00083  * \brief Handles all interrupts on the given PIO controller.
00084  * \param id  PIO controller ID.
00085  * \param pPio  PIO controller base address.
00086  */
00087 extern void PioInterruptHandler( uint32_t id, Pio *pPio )
00088 {
00089     uint32_t status;
00090     uint32_t i;
00091 
00092     /* Read PIO controller status */
00093     status = pPio->PIO_ISR;
00094     status &= pPio->PIO_IMR;
00095 
00096     /* Check pending events */
00097     if ( status != 0 ) {
00098         TRACE_DEBUG( "PIO interrupt on PIO controller #%d\n\r", id ) ;
00099 
00100         /* Find triggering source */
00101         i = 0;
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             i++;
00116         }
00117     }
00118 }
00119 
00120 /*----------------------------------------------------------------------------
00121  *        Global Functions
00122  *----------------------------------------------------------------------------*/
00123 
00124 /**
00125  * \brief Parallel IO Controller A interrupt handler
00126  * \Redefined PIOA interrupt handler for NVIC interrupt table.
00127  */
00128 extern void PIOA_Handler( void )
00129 {
00130     PioInterruptHandler( ID_PIOA, PIOA ) ;
00131 }
00132 
00133 /**
00134  * \brief Parallel IO Controller B interrupt handler
00135  * \Redefined PIOB interrupt handler for NVIC interrupt table.
00136  */
00137 extern void PIOB_Handler( void )
00138 {
00139     PioInterruptHandler( ID_PIOB, PIOB ) ;
00140 }
00141 
00142 /**
00143  * \brief Parallel IO Controller C interrupt handler
00144  * \Redefined PIOC interrupt handler for NVIC interrupt table.
00145  */
00146 extern void PIOC_Handler( void )
00147 {
00148     PioInterruptHandler( ID_PIOC, PIOC ) ;
00149 }
00150 
00151 
00152 /**
00153  * \brief Parallel IO Controller D interrupt handler
00154  * \Redefined PIOD interrupt handler for NVIC interrupt table.
00155  */
00156 extern void PIOD_Handler( void )
00157 {
00158     PioInterruptHandler( ID_PIOD, PIOD ) ;
00159 }
00160 
00161 /**
00162  * \brief Parallel IO Controller E interrupt handler
00163  * \Redefined PIOE interrupt handler for NVIC interrupt table.
00164  */
00165 extern void PIOE_Handler( void )
00166 {
00167     PioInterruptHandler( ID_PIOE, PIOE ) ;
00168 }
00169 
00170 /**
00171  * \brief Initializes the PIO interrupt management logic
00172  *
00173  * The desired priority of PIO interrupts must be provided.
00174  * Calling this function multiple times result in the reset of currently
00175  * configured interrupts.
00176  *
00177  * \param priority  PIO controller interrupts priority.
00178  */
00179 extern void PIO_InitializeInterrupts( uint32_t dwPriority )
00180 {
00181     TRACE_DEBUG( "PIO_Initialize()\n\r" ) ;
00182 
00183     /* Reset sources */
00184     _dwNumSources = 0 ;
00185 
00186     /* Configure PIO interrupt sources */
00187     TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ;
00188     PMC_EnablePeripheral( ID_PIOA ) ;
00189     PIOA->PIO_ISR ;
00190     PIOA->PIO_IDR = 0xFFFFFFFF ;
00191     NVIC_DisableIRQ( PIOA_IRQn ) ;
00192     NVIC_ClearPendingIRQ( PIOA_IRQn ) ;
00193     NVIC_SetPriority( PIOA_IRQn, dwPriority ) ;
00194     NVIC_EnableIRQ( PIOA_IRQn ) ;
00195 
00196     TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ;
00197     PMC_EnablePeripheral( ID_PIOB ) ;
00198     PIOB->PIO_ISR ;
00199     PIOB->PIO_IDR = 0xFFFFFFFF ;
00200     NVIC_DisableIRQ( PIOB_IRQn ) ;
00201     NVIC_ClearPendingIRQ( PIOB_IRQn ) ;
00202     NVIC_SetPriority( PIOB_IRQn, dwPriority ) ;
00203     NVIC_EnableIRQ( PIOB_IRQn ) ;
00204 
00205     TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ;
00206     PMC_EnablePeripheral( ID_PIOC ) ;
00207     PIOC->PIO_ISR ;
00208     PIOC->PIO_IDR = 0xFFFFFFFF ;
00209     NVIC_DisableIRQ( PIOC_IRQn ) ;
00210     NVIC_ClearPendingIRQ( PIOC_IRQn ) ;
00211     NVIC_SetPriority( PIOC_IRQn, dwPriority ) ;
00212     NVIC_EnableIRQ( PIOC_IRQn ) ;
00213 
00214     TRACE_DEBUG( "PIO_Initialize: Configuring PIOD\n\r" ) ;
00215     PMC_EnablePeripheral( ID_PIOD ) ;
00216     PIOD->PIO_ISR ;
00217     PIOD->PIO_IDR = 0xFFFFFFFF ;
00218     NVIC_DisableIRQ( PIOD_IRQn ) ;
00219     NVIC_ClearPendingIRQ( PIOD_IRQn ) ;
00220     NVIC_SetPriority( PIOD_IRQn, dwPriority ) ;
00221     NVIC_EnableIRQ( PIOD_IRQn ) ;
00222 
00223     TRACE_DEBUG( "PIO_Initialize: Configuring PIOE\n\r" ) ;
00224     PMC_EnablePeripheral( ID_PIOE ) ;
00225     PIOE->PIO_ISR ;
00226     PIOE->PIO_IDR = 0xFFFFFFFF ;
00227     NVIC_DisableIRQ( PIOE_IRQn ) ;
00228     NVIC_ClearPendingIRQ( PIOE_IRQn ) ;
00229     NVIC_SetPriority( PIOE_IRQn, dwPriority ) ;
00230     NVIC_EnableIRQ( PIOE_IRQn ) ;
00231 }
00232 
00233 /**
00234  * Configures a PIO or a group of PIO to generate an interrupt on status
00235  * change. The provided interrupt handler will be called with the triggering
00236  * pin as its parameter (enabling different pin instances to share the same
00237  * handler).
00238  * \param pPin  Pointer to a Pin instance.
00239  * \param handler  Interrupt handler function pointer.
00240  */
00241 extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) )
00242 {
00243     Pio* pio ;
00244     InterruptSource* pSource ;
00245 
00246     TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ;
00247 
00248     assert( pPin ) ;
00249     pio = pPin->pio ;
00250     assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;
00251 
00252     /* Define new source */
00253     TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources ) ;
00254 
00255     pSource = &(_aIntSources[_dwNumSources]) ;
00256     pSource->pPin = pPin ;
00257     pSource->handler = handler ;
00258     _dwNumSources++ ;
00259 
00260     /* PIO3 with additional interrupt support
00261      * Configure additional interrupt mode registers */
00262     if ( pPin->attribute & PIO_IT_AIME ) {
00263         // enable additional interrupt mode
00264         pio->PIO_AIMER  = pPin->mask ;
00265 
00266         // if bit field of selected pin is 1, set as Rising Edge/High level detection event
00267         if ( pPin->attribute & PIO_IT_RE_OR_HL ) {
00268             pio->PIO_REHLSR    = pPin->mask ;
00269         } else {
00270             pio->PIO_FELLSR     = pPin->mask;
00271         }
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     assert( dwFound != 0 ) ;
00308 #endif
00309 
00310     pPin->pio->PIO_ISR;
00311     pPin->pio->PIO_IER = pPin->mask ;
00312 }
00313 
00314 /**
00315  * Disables a given interrupt source, with no added side effects.
00316  *
00317  * \param pPin  Interrupt source to disable.
00318  */
00319 extern void PIO_DisableIt( const Pin *pPin )
00320 {
00321     assert( pPin != NULL ) ;
00322 
00323     TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ;
00324 
00325     pPin->pio->PIO_IDR = pPin->mask;
00326 }
00327 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines