summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-01-12 15:34:31 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-01-19 08:36:20 +0100
commite1eeb883d82ce218c2a9c754795cb3c86ac0f36d (patch)
tree646a7c22772297094bb77303953eda0e71679dd9 /c/src/lib/libbsp/arm/atsam/libraries/libchip/source/pio_it.c
parentbsps/arm: Copy vector table only if necessary (diff)
downloadrtems-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.c328
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;
+}
+