[rtems commit] bsp/atsam: System initialization for PIO IRQs

Sebastian Huber sebh at rtems.org
Fri Dec 16 10:29:10 UTC 2016


Module:    rtems
Branch:    master
Commit:    a4936b59cb0afe55fb1a31754293586bbde38115
Changeset: http://git.rtems.org/rtems/commit/?id=a4936b59cb0afe55fb1a31754293586bbde38115

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Dec 15 14:55:45 2016 +0100

bsp/atsam: System initialization for PIO IRQs

---

 .../arm/atsam/libraries/libchip/include/pio_it.h   |  26 ++-
 .../arm/atsam/libraries/libchip/source/pio_it.c    | 217 +++++++++------------
 c/src/lib/libbsp/shared/include/fatal.h            |   8 +-
 3 files changed, 127 insertions(+), 124 deletions(-)

diff --git a/c/src/lib/libbsp/arm/atsam/libraries/libchip/include/pio_it.h b/c/src/lib/libbsp/arm/atsam/libraries/libchip/include/pio_it.h
index 4235ec9..b03973c 100644
--- a/c/src/lib/libbsp/arm/atsam/libraries/libchip/include/pio_it.h
+++ b/c/src/lib/libbsp/arm/atsam/libraries/libchip/include/pio_it.h
@@ -77,11 +77,31 @@ extern "C" {
 
 extern void PIO_InitializeInterrupts(uint32_t dwPriority);
 
-extern void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *));
+extern void PIO_ConfigureIt(const Pin *pPin,
+    void (*handler)(const Pin *, void *arg), void *arg);
 
-extern void PIO_EnableIt(const Pin *pPin);
 
-extern void PIO_DisableIt(const Pin *pPin);
+/**
+ * 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.
+ */
+static inline void PIO_EnableIt(const Pin *pPin)
+{
+	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.
+ */
+static inline void PIO_DisableIt(const Pin *pPin)
+{
+	pPin->pio->PIO_IDR = pPin->mask;
+}
 
 extern void PIO_IT_InterruptHandler(void);
 
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
index 61f0db2..7176288 100644
--- 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
@@ -37,7 +37,9 @@
 
 #include "chip.h"
 
-#include <assert.h>
+#include <rtems/irq-extension.h>
+#include <rtems/sysinit.h>
+#include <bsp/fatal.h>
 
 /*----------------------------------------------------------------------------
  *        Local definitions
@@ -61,7 +63,9 @@ typedef struct _InterruptSource {
 	const Pin *pPin;
 
 	/* Interrupt handler. */
-	void (*handler)(const Pin *);
+	void (*handler)(const Pin *, void *arg);
+
+	void *arg;
 } InterruptSource;
 
 /*----------------------------------------------------------------------------
@@ -83,37 +87,25 @@ static uint32_t _dwNumSources = 0;
  * \param id  PIO controller ID.
  * \param pPio  PIO controller base address.
  */
-extern void PioInterruptHandler(uint32_t id, Pio *pPio)
+static void PIO_Interrupt(Pio *pPio, uint32_t id)
 {
 	uint32_t status;
-	uint32_t i;
+	size_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);
-				}
-			}
+	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;
 
-			i++;
+			if ((status & mask) != 0) {
+				status &= ~mask;
+				(*is->handler)(pin, is->arg);
+			}
 		}
 	}
 }
@@ -126,27 +118,27 @@ extern void PioInterruptHandler(uint32_t id, Pio *pPio)
  * \brief Parallel IO Controller A interrupt handler
  * \Redefined PIOA interrupt handler for NVIC interrupt table.
  */
-extern void PIOA_Handler(void)
+static void PIOA_Interrupt(void *arg)
 {
-	PioInterruptHandler(ID_PIOA, PIOA);
+	PIO_Interrupt(arg, ID_PIOA);
 }
 
 /**
  * \brief Parallel IO Controller B interrupt handler
  * \Redefined PIOB interrupt handler for NVIC interrupt table.
  */
-extern void PIOB_Handler(void)
+static void PIOB_Interrupt(void *arg)
 {
-	PioInterruptHandler(ID_PIOB, PIOB);
+	PIO_Interrupt(arg, ID_PIOB);
 }
 
 /**
  * \brief Parallel IO Controller C interrupt handler
  * \Redefined PIOC interrupt handler for NVIC interrupt table.
  */
-extern void PIOC_Handler(void)
+static void PIOC_Interrupt(void *arg)
 {
-	PioInterruptHandler(ID_PIOC, PIOC);
+	PIO_Interrupt(arg, ID_PIOC);
 }
 
 
@@ -154,83 +146,106 @@ extern void PIOC_Handler(void)
  * \brief Parallel IO Controller D interrupt handler
  * \Redefined PIOD interrupt handler for NVIC interrupt table.
  */
-extern void PIOD_Handler(void)
+static void PIOD_Interrupt(void *arg)
 {
-	PioInterruptHandler(ID_PIOD, PIOD);
+	PIO_Interrupt(arg, ID_PIOD);
 }
 
 /**
  * \brief Parallel IO Controller E interrupt handler
  * \Redefined PIOE interrupt handler for NVIC interrupt table.
  */
-extern void PIOE_Handler(void)
+static void PIOE_Interrupt(void *arg)
 {
-	PioInterruptHandler(ID_PIOE, PIOE);
+	PIO_Interrupt(arg, ID_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)
+static void PIO_SysInitializeInterrupts(void)
 {
-	TRACE_DEBUG("PIO_Initialize()\n\r");
+	rtems_status_code sc;
 
-	/* Reset sources */
-	_dwNumSources = 0;
+	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;
-	NVIC_DisableIRQ(PIOA_IRQn);
-	NVIC_ClearPendingIRQ(PIOA_IRQn);
-	NVIC_SetPriority(PIOA_IRQn, dwPriority);
-	NVIC_EnableIRQ(PIOA_IRQn);
+	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;
-	NVIC_DisableIRQ(PIOB_IRQn);
-	NVIC_ClearPendingIRQ(PIOB_IRQn);
-	NVIC_SetPriority(PIOB_IRQn, dwPriority);
-	NVIC_EnableIRQ(PIOB_IRQn);
+	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;
-	NVIC_DisableIRQ(PIOC_IRQn);
-	NVIC_ClearPendingIRQ(PIOC_IRQn);
-	NVIC_SetPriority(PIOC_IRQn, dwPriority);
-	NVIC_EnableIRQ(PIOC_IRQn);
+	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;
-	NVIC_DisableIRQ(PIOD_IRQn);
-	NVIC_ClearPendingIRQ(PIOD_IRQn);
-	NVIC_SetPriority(PIOD_IRQn, dwPriority);
-	NVIC_EnableIRQ(PIOD_IRQn);
+	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;
-	NVIC_DisableIRQ(PIOE_IRQn);
-	NVIC_ClearPendingIRQ(PIOE_IRQn);
-	NVIC_SetPriority(PIOE_IRQn, dwPriority);
-	NVIC_EnableIRQ(PIOE_IRQn);
+	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
@@ -239,25 +254,33 @@ extern void PIO_InitializeInterrupts(uint32_t dwPriority)
  * \param pPin  Pointer to a Pin instance.
  * \param handler  Interrupt handler function pointer.
  */
-extern void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *))
+void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *, void *arg),
+    void *arg)
 {
 	Pio *pio;
 	InterruptSource *pSource;
+	rtems_interrupt_level level;
 
 	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);
+	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;
 	_dwNumSources++;
 
+	rtems_interrupt_enable(level);
+
+	/* Define new source */
+	TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources);
+
 	/* PIO3 with additional interrupt support
 	 * Configure additional interrupt mode registers */
 	if (pPin->attribute & PIO_IT_AIME) {
@@ -280,49 +303,3 @@ extern void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *))
 		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;
-}
-
diff --git a/c/src/lib/libbsp/shared/include/fatal.h b/c/src/lib/libbsp/shared/include/fatal.h
index 1336c78..fd8b678 100644
--- a/c/src/lib/libbsp/shared/include/fatal.h
+++ b/c/src/lib/libbsp/shared/include/fatal.h
@@ -127,7 +127,13 @@ typedef enum {
   QORIQ_FATAL_RESTART_INTERRUPT_FAILED,
 
   /* ATSAM fatal codes */
-  ATSAM_FATAL_XDMA_IRQ_INSTALL = BSP_FATAL_CODE_BLOCK(11)
+  ATSAM_FATAL_XDMA_IRQ_INSTALL = BSP_FATAL_CODE_BLOCK(11),
+  ATSAM_FATAL_PIO_IRQ_A,
+  ATSAM_FATAL_PIO_IRQ_B,
+  ATSAM_FATAL_PIO_IRQ_C,
+  ATSAM_FATAL_PIO_IRQ_D,
+  ATSAM_FATAL_PIO_IRQ_E,
+  ATSAM_FATAL_PIO_CONFIGURE_IT
 } bsp_fatal_code;
 
 RTEMS_NO_RETURN static inline void




More information about the vc mailing list