summaryrefslogtreecommitdiffstats
path: root/bsps/arm/atsam/contrib/libraries/libchip/source/pio_it.c
diff options
context:
space:
mode:
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.c283
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);
+}