diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-01-12 15:34:31 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-01-19 08:36:20 +0100 |
commit | e1eeb883d82ce218c2a9c754795cb3c86ac0f36d (patch) | |
tree | 646a7c22772297094bb77303953eda0e71679dd9 /c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c | |
parent | bsps/arm: Copy vector table only if necessary (diff) | |
download | rtems-e1eeb883d82ce218c2a9c754795cb3c86ac0f36d.tar.bz2 |
bsp/atsam: Import SAM Software Package
Import selected files of the "SAM V71 / V70 / E70 / S70 Software
Package" obtained from the "SAMV71-XULT GNU Software Package 1.5".
Converted files via dos2unix before import.
Update #2529.
Diffstat (limited to 'c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c')
-rw-r--r-- | c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c | 328 |
1 files changed, 328 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c new file mode 100644 index 0000000000..61f0db26c1 --- /dev/null +++ b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c @@ -0,0 +1,328 @@ +/* ---------------------------------------------------------------------------- */ +/* 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 <assert.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 *); +} 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. + */ +extern void PioInterruptHandler(uint32_t id, Pio *pPio) +{ + uint32_t status; + uint32_t i; + + /* Read PIO controller status */ + status = pPio->PIO_ISR; + status &= pPio->PIO_IMR; + + /* Check pending events */ + if (status != 0) { + TRACE_DEBUG("PIO interrupt on PIO controller #%d\n\r", id); + + /* Find triggering source */ + i = 0; + + while (status != 0) { + /* There cannot be an un-configured source enabled. */ + assert(i < _dwNumSources); + + /* Source is configured on the same controller */ + if (_aIntSources[i].pPin->id == id) { + /* Source has PIOs whose statuses have changed */ + if ((status & _aIntSources[i].pPin->mask) != 0) { + TRACE_DEBUG("Interrupt source #%d triggered\n\r", i); + _aIntSources[i].handler(_aIntSources[i].pPin); + status &= ~(_aIntSources[i].pPin->mask); + } + } + + i++; + } + } +} + +/*---------------------------------------------------------------------------- + * Global Functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Parallel IO Controller A interrupt handler + * \Redefined PIOA interrupt handler for NVIC interrupt table. + */ +extern void PIOA_Handler(void) +{ + PioInterruptHandler(ID_PIOA, PIOA); +} + +/** + * \brief Parallel IO Controller B interrupt handler + * \Redefined PIOB interrupt handler for NVIC interrupt table. + */ +extern void PIOB_Handler(void) +{ + PioInterruptHandler(ID_PIOB, PIOB); +} + +/** + * \brief Parallel IO Controller C interrupt handler + * \Redefined PIOC interrupt handler for NVIC interrupt table. + */ +extern void PIOC_Handler(void) +{ + PioInterruptHandler(ID_PIOC, PIOC); +} + + +/** + * \brief Parallel IO Controller D interrupt handler + * \Redefined PIOD interrupt handler for NVIC interrupt table. + */ +extern void PIOD_Handler(void) +{ + PioInterruptHandler(ID_PIOD, PIOD); +} + +/** + * \brief Parallel IO Controller E interrupt handler + * \Redefined PIOE interrupt handler for NVIC interrupt table. + */ +extern void PIOE_Handler(void) +{ + PioInterruptHandler(ID_PIOE, PIOE); +} + +/** + * \brief Initializes the PIO interrupt management logic + * + * The desired priority of PIO interrupts must be provided. + * Calling this function multiple times result in the reset of currently + * configured interrupts. + * + * \param priority PIO controller interrupts priority. + */ +extern void PIO_InitializeInterrupts(uint32_t dwPriority) +{ + TRACE_DEBUG("PIO_Initialize()\n\r"); + + /* Reset sources */ + _dwNumSources = 0; + + /* Configure PIO interrupt sources */ + TRACE_DEBUG("PIO_Initialize: Configuring PIOA\n\r"); + PMC_EnablePeripheral(ID_PIOA); + PIOA->PIO_ISR; + PIOA->PIO_IDR = 0xFFFFFFFF; + NVIC_DisableIRQ(PIOA_IRQn); + NVIC_ClearPendingIRQ(PIOA_IRQn); + NVIC_SetPriority(PIOA_IRQn, dwPriority); + NVIC_EnableIRQ(PIOA_IRQn); + + TRACE_DEBUG("PIO_Initialize: Configuring PIOB\n\r"); + PMC_EnablePeripheral(ID_PIOB); + PIOB->PIO_ISR; + PIOB->PIO_IDR = 0xFFFFFFFF; + NVIC_DisableIRQ(PIOB_IRQn); + NVIC_ClearPendingIRQ(PIOB_IRQn); + NVIC_SetPriority(PIOB_IRQn, dwPriority); + NVIC_EnableIRQ(PIOB_IRQn); + + TRACE_DEBUG("PIO_Initialize: Configuring PIOC\n\r"); + PMC_EnablePeripheral(ID_PIOC); + PIOC->PIO_ISR; + PIOC->PIO_IDR = 0xFFFFFFFF; + NVIC_DisableIRQ(PIOC_IRQn); + NVIC_ClearPendingIRQ(PIOC_IRQn); + NVIC_SetPriority(PIOC_IRQn, dwPriority); + NVIC_EnableIRQ(PIOC_IRQn); + + TRACE_DEBUG("PIO_Initialize: Configuring PIOD\n\r"); + PMC_EnablePeripheral(ID_PIOD); + PIOD->PIO_ISR; + PIOD->PIO_IDR = 0xFFFFFFFF; + NVIC_DisableIRQ(PIOD_IRQn); + NVIC_ClearPendingIRQ(PIOD_IRQn); + NVIC_SetPriority(PIOD_IRQn, dwPriority); + NVIC_EnableIRQ(PIOD_IRQn); + + TRACE_DEBUG("PIO_Initialize: Configuring PIOE\n\r"); + PMC_EnablePeripheral(ID_PIOE); + PIOE->PIO_ISR; + PIOE->PIO_IDR = 0xFFFFFFFF; + NVIC_DisableIRQ(PIOE_IRQn); + NVIC_ClearPendingIRQ(PIOE_IRQn); + NVIC_SetPriority(PIOE_IRQn, dwPriority); + NVIC_EnableIRQ(PIOE_IRQn); +} + +/** + * 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. + */ +extern void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *)) +{ + Pio *pio; + InterruptSource *pSource; + + TRACE_DEBUG("PIO_ConfigureIt()\n\r"); + + assert(pPin); + pio = pPin->pio; + assert(_dwNumSources < MAX_INTERRUPT_SOURCES); + + /* Define new source */ + TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources); + + pSource = &(_aIntSources[_dwNumSources]); + pSource->pPin = pPin; + pSource->handler = handler; + _dwNumSources++; + + /* PIO3 with additional interrupt support + * Configure additional interrupt mode registers */ + if (pPin->attribute & PIO_IT_AIME) { + // enable additional interrupt mode + pio->PIO_AIMER = pPin->mask; + + // if bit field of selected pin is 1, set as Rising Edge/High level detection event + if (pPin->attribute & PIO_IT_RE_OR_HL) + pio->PIO_REHLSR = pPin->mask; + else + pio->PIO_FELLSR = pPin->mask; + + /* if bit field of selected pin is 1, set as edge detection source */ + if (pPin->attribute & PIO_IT_EDGE) + pio->PIO_ESR = pPin->mask; + else + pio->PIO_LSR = pPin->mask; + } else { + /* disable additional interrupt mode */ + pio->PIO_AIMDR = pPin->mask; + } +} + +/** + * Enables the given interrupt source if it has been configured. The status + * register of the corresponding PIO controller is cleared prior to enabling + * the interrupt. + * \param pPin Interrupt source to enable. + */ +extern void PIO_EnableIt(const Pin *pPin) +{ + uint32_t i = 0; + uint32_t dwFound = 0; + + TRACE_DEBUG("PIO_EnableIt()\n\r"); + + assert(pPin != NULL); + +#ifndef NOASSERT + + while ((i < _dwNumSources) && !dwFound) { + if (_aIntSources[i].pPin == pPin) + dwFound = 1; + + i++; + } + + assert(dwFound != 0); +#endif + + pPin->pio->PIO_ISR; + pPin->pio->PIO_IER = pPin->mask; +} + +/** + * Disables a given interrupt source, with no added side effects. + * + * \param pPin Interrupt source to disable. + */ +extern void PIO_DisableIt(const Pin *pPin) +{ + assert(pPin != NULL); + + TRACE_DEBUG("PIO_DisableIt()\n\r"); + + pPin->pio->PIO_IDR = pPin->mask; +} + |