diff options
Diffstat (limited to 'bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c')
-rw-r--r-- | bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c b/bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c new file mode 100644 index 0000000000..2c619db136 --- /dev/null +++ b/bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c @@ -0,0 +1,283 @@ +/* ---------------------------------------------------------------------------- */ +/* Atmel Microcontroller Software Support */ +/* SAM Software Package License */ +/* ---------------------------------------------------------------------------- */ +/* Copyright (c) 2015, Atmel Corporation */ +/* */ +/* All rights reserved. */ +/* */ +/* Redistribution and use in source and binary forms, with or without */ +/* modification, are permitted provided that the following condition is met: */ +/* */ +/* - Redistributions of source code must retain the above copyright notice, */ +/* this list of conditions and the disclaimer below. */ +/* */ +/* Atmel's name may not be used to endorse or promote products derived from */ +/* this software without specific prior written permission. */ +/* */ +/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ +/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ +/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ +/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ +/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ +/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ +/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* ---------------------------------------------------------------------------- */ + +/* + * \file + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +#include <rtems/irq-extension.h> +#include <rtems/sysinit.h> +#include <bsp/fatal.h> + +/*---------------------------------------------------------------------------- + * Local definitions + *----------------------------------------------------------------------------*/ + +/* Maximum number of interrupt sources that can be defined. This + * constant can be increased, but the current value is the smallest possible + * that will be compatible with all existing projects. */ +#define MAX_INTERRUPT_SOURCES 7 + +/*---------------------------------------------------------------------------- + * Local types + *----------------------------------------------------------------------------*/ + +/** + * Describes a PIO interrupt source, including the PIO instance triggering the + * interrupt and the associated interrupt handler. + */ +typedef struct _InterruptSource { + /* Pointer to the source pin instance. */ + const Pin *pPin; + + /* Interrupt handler. */ + void (*handler)(const Pin *, void *arg); + + void *arg; +} InterruptSource; + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/* List of interrupt sources. */ +static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES]; + +/* Number of currently defined interrupt sources. */ +static uint32_t _dwNumSources = 0; + +/*---------------------------------------------------------------------------- + * Local Functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Handles all interrupts on the given PIO controller. + * \param id PIO controller ID. + * \param pPio PIO controller base address. + */ +static void PIO_Interrupt(Pio *pPio, uint32_t id) +{ + uint32_t status; + size_t i; + + status = pPio->PIO_ISR; + status &= pPio->PIO_IMR; + + for (i = 0; status != 0 && i < MAX_INTERRUPT_SOURCES; ++i) { + const InterruptSource *is = &_aIntSources[i]; + const Pin *pin = is->pPin;; + + if (pin->id == id) { + uint32_t mask = pin->mask; + + if ((status & mask) != 0) { + status &= ~mask; + (*is->handler)(pin, is->arg); + } + } + } +} + +/*---------------------------------------------------------------------------- + * Global Functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Parallel IO Controller A interrupt handler + * \Redefined PIOA interrupt handler for NVIC interrupt table. + */ +static void PIOA_Interrupt(void *arg) +{ + PIO_Interrupt(arg, ID_PIOA); +} + +/** + * \brief Parallel IO Controller B interrupt handler + * \Redefined PIOB interrupt handler for NVIC interrupt table. + */ +static void PIOB_Interrupt(void *arg) +{ + PIO_Interrupt(arg, ID_PIOB); +} + +/** + * \brief Parallel IO Controller C interrupt handler + * \Redefined PIOC interrupt handler for NVIC interrupt table. + */ +static void PIOC_Interrupt(void *arg) +{ + PIO_Interrupt(arg, ID_PIOC); +} + + +/** + * \brief Parallel IO Controller D interrupt handler + * \Redefined PIOD interrupt handler for NVIC interrupt table. + */ +static void PIOD_Interrupt(void *arg) +{ + PIO_Interrupt(arg, ID_PIOD); +} + +/** + * \brief Parallel IO Controller E interrupt handler + * \Redefined PIOE interrupt handler for NVIC interrupt table. + */ +static void PIOE_Interrupt(void *arg) +{ + PIO_Interrupt(arg, ID_PIOE); +} + +static void PIO_SysInitializeInterrupts(void) +{ + rtems_status_code sc; + + TRACE_DEBUG("PIO_Initialize()\n\r"); + + /* Configure PIO interrupt sources */ + TRACE_DEBUG("PIO_Initialize: Configuring PIOA\n\r"); + PMC_EnablePeripheral(ID_PIOA); + PIOA->PIO_ISR; + PIOA->PIO_IDR = 0xFFFFFFFF; + sc = rtems_interrupt_handler_install( + PIOA_IRQn, + "PIO A", + RTEMS_INTERRUPT_UNIQUE, + PIOA_Interrupt, + PIOA + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(ATSAM_FATAL_PIO_IRQ_A); + } + + TRACE_DEBUG("PIO_Initialize: Configuring PIOB\n\r"); + PMC_EnablePeripheral(ID_PIOB); + PIOB->PIO_ISR; + PIOB->PIO_IDR = 0xFFFFFFFF; + sc = rtems_interrupt_handler_install( + PIOB_IRQn, + "PIO B", + RTEMS_INTERRUPT_UNIQUE, + PIOB_Interrupt, + PIOB + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(ATSAM_FATAL_PIO_IRQ_B); + } + + TRACE_DEBUG("PIO_Initialize: Configuring PIOC\n\r"); + PMC_EnablePeripheral(ID_PIOC); + PIOC->PIO_ISR; + PIOC->PIO_IDR = 0xFFFFFFFF; + sc = rtems_interrupt_handler_install( + PIOC_IRQn, + "PIO C", + RTEMS_INTERRUPT_UNIQUE, + PIOC_Interrupt, + PIOC + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(ATSAM_FATAL_PIO_IRQ_C); + } + + TRACE_DEBUG("PIO_Initialize: Configuring PIOD\n\r"); + PMC_EnablePeripheral(ID_PIOD); + PIOD->PIO_ISR; + PIOD->PIO_IDR = 0xFFFFFFFF; + sc = rtems_interrupt_handler_install( + PIOD_IRQn, + "PIO D", + RTEMS_INTERRUPT_UNIQUE, + PIOD_Interrupt, + PIOD + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(ATSAM_FATAL_PIO_IRQ_D); + } + + TRACE_DEBUG("PIO_Initialize: Configuring PIOE\n\r"); + PMC_EnablePeripheral(ID_PIOE); + PIOE->PIO_ISR; + PIOE->PIO_IDR = 0xFFFFFFFF; + sc = rtems_interrupt_handler_install( + PIOE_IRQn, + "PIO E", + RTEMS_INTERRUPT_UNIQUE, + PIOE_Interrupt, + PIOE + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(ATSAM_FATAL_PIO_IRQ_E); + } +} + +RTEMS_SYSINIT_ITEM(PIO_SysInitializeInterrupts, RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_LAST); + +/** + * Configures a PIO or a group of PIO to generate an interrupt on status + * change. The provided interrupt handler will be called with the triggering + * pin as its parameter (enabling different pin instances to share the same + * handler). + * \param pPin Pointer to a Pin instance. + * \param handler Interrupt handler function pointer. + * \param arg Pointer to interrupt handler argument + */ +void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *, void *arg), + void *arg) +{ + InterruptSource *pSource; + rtems_interrupt_level level; + + TRACE_DEBUG("PIO_ConfigureIt()\n\r"); + + rtems_interrupt_disable(level); + + if (_dwNumSources == MAX_INTERRUPT_SOURCES) { + bsp_fatal(ATSAM_FATAL_PIO_CONFIGURE_IT); + } + + pSource = &(_aIntSources[_dwNumSources]); + pSource->pPin = pPin; + pSource->handler = handler; + pSource->arg = arg; + + _dwNumSources++; + + rtems_interrupt_enable(level); + + /* Define new source */ + TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources); +} |