forked from Imagelibrary/rtems
bsp/atsam: System initialization for PIO IRQs
This commit is contained in:
@@ -77,11 +77,31 @@ extern "C" {
|
|||||||
|
|
||||||
extern void PIO_InitializeInterrupts(uint32_t dwPriority);
|
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);
|
extern void PIO_IT_InterruptHandler(void);
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,9 @@
|
|||||||
|
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <rtems/irq-extension.h>
|
||||||
|
#include <rtems/sysinit.h>
|
||||||
|
#include <bsp/fatal.h>
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
* Local definitions
|
* Local definitions
|
||||||
@@ -61,7 +63,9 @@ typedef struct _InterruptSource {
|
|||||||
const Pin *pPin;
|
const Pin *pPin;
|
||||||
|
|
||||||
/* Interrupt handler. */
|
/* Interrupt handler. */
|
||||||
void (*handler)(const Pin *);
|
void (*handler)(const Pin *, void *arg);
|
||||||
|
|
||||||
|
void *arg;
|
||||||
} InterruptSource;
|
} InterruptSource;
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
@@ -83,37 +87,25 @@ static uint32_t _dwNumSources = 0;
|
|||||||
* \param id PIO controller ID.
|
* \param id PIO controller ID.
|
||||||
* \param pPio PIO controller base address.
|
* \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 status;
|
||||||
uint32_t i;
|
size_t i;
|
||||||
|
|
||||||
/* Read PIO controller status */
|
|
||||||
status = pPio->PIO_ISR;
|
status = pPio->PIO_ISR;
|
||||||
status &= pPio->PIO_IMR;
|
status &= pPio->PIO_IMR;
|
||||||
|
|
||||||
/* Check pending events */
|
for (i = 0; status != 0 && i < MAX_INTERRUPT_SOURCES; ++i) {
|
||||||
if (status != 0) {
|
const InterruptSource *is = &_aIntSources[i];
|
||||||
TRACE_DEBUG("PIO interrupt on PIO controller #%d\n\r", id);
|
const Pin *pin = is->pPin;;
|
||||||
|
|
||||||
/* Find triggering source */
|
if (pin->id == id) {
|
||||||
i = 0;
|
uint32_t mask = pin->mask;
|
||||||
|
|
||||||
while (status != 0) {
|
if ((status & mask) != 0) {
|
||||||
/* There cannot be an un-configured source enabled. */
|
status &= ~mask;
|
||||||
assert(i < _dwNumSources);
|
(*is->handler)(pin, is->arg);
|
||||||
|
|
||||||
/* 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++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,27 +118,27 @@ extern void PioInterruptHandler(uint32_t id, Pio *pPio)
|
|||||||
* \brief Parallel IO Controller A interrupt handler
|
* \brief Parallel IO Controller A interrupt handler
|
||||||
* \Redefined PIOA interrupt handler for NVIC interrupt table.
|
* \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
|
* \brief Parallel IO Controller B interrupt handler
|
||||||
* \Redefined PIOB interrupt handler for NVIC interrupt table.
|
* \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
|
* \brief Parallel IO Controller C interrupt handler
|
||||||
* \Redefined PIOC interrupt handler for NVIC interrupt table.
|
* \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
|
* \brief Parallel IO Controller D interrupt handler
|
||||||
* \Redefined PIOD interrupt handler for NVIC interrupt table.
|
* \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
|
* \brief Parallel IO Controller E interrupt handler
|
||||||
* \Redefined PIOE interrupt handler for NVIC interrupt table.
|
* \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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static void PIO_SysInitializeInterrupts(void)
|
||||||
* \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");
|
rtems_status_code sc;
|
||||||
|
|
||||||
/* Reset sources */
|
TRACE_DEBUG("PIO_Initialize()\n\r");
|
||||||
_dwNumSources = 0;
|
|
||||||
|
|
||||||
/* Configure PIO interrupt sources */
|
/* Configure PIO interrupt sources */
|
||||||
TRACE_DEBUG("PIO_Initialize: Configuring PIOA\n\r");
|
TRACE_DEBUG("PIO_Initialize: Configuring PIOA\n\r");
|
||||||
PMC_EnablePeripheral(ID_PIOA);
|
PMC_EnablePeripheral(ID_PIOA);
|
||||||
PIOA->PIO_ISR;
|
PIOA->PIO_ISR;
|
||||||
PIOA->PIO_IDR = 0xFFFFFFFF;
|
PIOA->PIO_IDR = 0xFFFFFFFF;
|
||||||
NVIC_DisableIRQ(PIOA_IRQn);
|
sc = rtems_interrupt_handler_install(
|
||||||
NVIC_ClearPendingIRQ(PIOA_IRQn);
|
PIOA_IRQn,
|
||||||
NVIC_SetPriority(PIOA_IRQn, dwPriority);
|
"PIO A",
|
||||||
NVIC_EnableIRQ(PIOA_IRQn);
|
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");
|
TRACE_DEBUG("PIO_Initialize: Configuring PIOB\n\r");
|
||||||
PMC_EnablePeripheral(ID_PIOB);
|
PMC_EnablePeripheral(ID_PIOB);
|
||||||
PIOB->PIO_ISR;
|
PIOB->PIO_ISR;
|
||||||
PIOB->PIO_IDR = 0xFFFFFFFF;
|
PIOB->PIO_IDR = 0xFFFFFFFF;
|
||||||
NVIC_DisableIRQ(PIOB_IRQn);
|
sc = rtems_interrupt_handler_install(
|
||||||
NVIC_ClearPendingIRQ(PIOB_IRQn);
|
PIOB_IRQn,
|
||||||
NVIC_SetPriority(PIOB_IRQn, dwPriority);
|
"PIO B",
|
||||||
NVIC_EnableIRQ(PIOB_IRQn);
|
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");
|
TRACE_DEBUG("PIO_Initialize: Configuring PIOC\n\r");
|
||||||
PMC_EnablePeripheral(ID_PIOC);
|
PMC_EnablePeripheral(ID_PIOC);
|
||||||
PIOC->PIO_ISR;
|
PIOC->PIO_ISR;
|
||||||
PIOC->PIO_IDR = 0xFFFFFFFF;
|
PIOC->PIO_IDR = 0xFFFFFFFF;
|
||||||
NVIC_DisableIRQ(PIOC_IRQn);
|
sc = rtems_interrupt_handler_install(
|
||||||
NVIC_ClearPendingIRQ(PIOC_IRQn);
|
PIOC_IRQn,
|
||||||
NVIC_SetPriority(PIOC_IRQn, dwPriority);
|
"PIO C",
|
||||||
NVIC_EnableIRQ(PIOC_IRQn);
|
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");
|
TRACE_DEBUG("PIO_Initialize: Configuring PIOD\n\r");
|
||||||
PMC_EnablePeripheral(ID_PIOD);
|
PMC_EnablePeripheral(ID_PIOD);
|
||||||
PIOD->PIO_ISR;
|
PIOD->PIO_ISR;
|
||||||
PIOD->PIO_IDR = 0xFFFFFFFF;
|
PIOD->PIO_IDR = 0xFFFFFFFF;
|
||||||
NVIC_DisableIRQ(PIOD_IRQn);
|
sc = rtems_interrupt_handler_install(
|
||||||
NVIC_ClearPendingIRQ(PIOD_IRQn);
|
PIOD_IRQn,
|
||||||
NVIC_SetPriority(PIOD_IRQn, dwPriority);
|
"PIO D",
|
||||||
NVIC_EnableIRQ(PIOD_IRQn);
|
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");
|
TRACE_DEBUG("PIO_Initialize: Configuring PIOE\n\r");
|
||||||
PMC_EnablePeripheral(ID_PIOE);
|
PMC_EnablePeripheral(ID_PIOE);
|
||||||
PIOE->PIO_ISR;
|
PIOE->PIO_ISR;
|
||||||
PIOE->PIO_IDR = 0xFFFFFFFF;
|
PIOE->PIO_IDR = 0xFFFFFFFF;
|
||||||
NVIC_DisableIRQ(PIOE_IRQn);
|
sc = rtems_interrupt_handler_install(
|
||||||
NVIC_ClearPendingIRQ(PIOE_IRQn);
|
PIOE_IRQn,
|
||||||
NVIC_SetPriority(PIOE_IRQn, dwPriority);
|
"PIO E",
|
||||||
NVIC_EnableIRQ(PIOE_IRQn);
|
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
|
* 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
|
* 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 pPin Pointer to a Pin instance.
|
||||||
* \param handler Interrupt handler function pointer.
|
* \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;
|
Pio *pio;
|
||||||
InterruptSource *pSource;
|
InterruptSource *pSource;
|
||||||
|
rtems_interrupt_level level;
|
||||||
|
|
||||||
TRACE_DEBUG("PIO_ConfigureIt()\n\r");
|
TRACE_DEBUG("PIO_ConfigureIt()\n\r");
|
||||||
|
|
||||||
assert(pPin);
|
|
||||||
pio = pPin->pio;
|
pio = pPin->pio;
|
||||||
assert(_dwNumSources < MAX_INTERRUPT_SOURCES);
|
|
||||||
|
|
||||||
/* Define new source */
|
rtems_interrupt_disable(level);
|
||||||
TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources);
|
|
||||||
|
if (_dwNumSources == MAX_INTERRUPT_SOURCES) {
|
||||||
|
bsp_fatal(ATSAM_FATAL_PIO_CONFIGURE_IT);
|
||||||
|
}
|
||||||
|
|
||||||
pSource = &(_aIntSources[_dwNumSources]);
|
pSource = &(_aIntSources[_dwNumSources]);
|
||||||
pSource->pPin = pPin;
|
pSource->pPin = pPin;
|
||||||
pSource->handler = handler;
|
pSource->handler = handler;
|
||||||
_dwNumSources++;
|
_dwNumSources++;
|
||||||
|
|
||||||
|
rtems_interrupt_enable(level);
|
||||||
|
|
||||||
|
/* Define new source */
|
||||||
|
TRACE_DEBUG("PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources);
|
||||||
|
|
||||||
/* PIO3 with additional interrupt support
|
/* PIO3 with additional interrupt support
|
||||||
* Configure additional interrupt mode registers */
|
* Configure additional interrupt mode registers */
|
||||||
if (pPin->attribute & PIO_IT_AIME) {
|
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;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,13 @@ typedef enum {
|
|||||||
QORIQ_FATAL_RESTART_INTERRUPT_FAILED,
|
QORIQ_FATAL_RESTART_INTERRUPT_FAILED,
|
||||||
|
|
||||||
/* ATSAM fatal codes */
|
/* 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;
|
} bsp_fatal_code;
|
||||||
|
|
||||||
RTEMS_NO_RETURN static inline void
|
RTEMS_NO_RETURN static inline void
|
||||||
|
|||||||
Reference in New Issue
Block a user