Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

RG Interrupts

RG Interrupts

Explanation

About the Sample Application Code

This C code is designed to interact with North Atlantic Industries (NAI) embedded function modules, specifically focusing on handling IRIG (Inter-range Instrumentation Group) interrupts. It demonstrates setting up and managing interrupts for an IRIG module. Here’s a detailed walk-through and explanation of the provided code:

Definitions and Includes

  • Header Inclusions: c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <ctype.h> #include "vxBusLib.h" #include "include/naiapp_boardaccess_menu.h" #include "include/naiapp_boardaccess_query.h" #include "include/naiapp_boardaccess_access.h" #include "include/naiapp_boardaccess_display.h" #include "include/naiapp_boardaccess_utils.h" #include "nai.h" #include "naibrd.h" #include "functions/naibrd_irig.h" #include "advanced/nai_ether_adv.h" These include standard libraries and specific NAI libraries required for board and IRIG functions.

  • Constant Definitions: c #define TIMEOUT 1000 #define FIRST_IRIG_CHANNEL_IDX 0 #define IRIG_CHANNEL1_INTERRUPT_VECTOR 0x000000A1u // #define IRIG_CHANNEL2_INTERRUPT_VECTOR 0x000000A2u static const int8_t *CONFIG_FILE = (const int8_t *)"default_RGInterrupts.txt"; Constants are defined for the timeout period, initial IRIG channel index, and the interrupt vectors.

Enumerations

  • Interrupt Status Type: c typedef enum interrupt_status_type_e { INTERRUPT_WAITING, INTERRUPT_RECEIVED, INTERRUPT_ERROR_UNEXPECTED_VECTOR } interrupt_status_type_t; Enumerates possible interrupt statuses.

Function Prototypes

These declare several functions used within the code:

void Run_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid);
void Setup_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, naibrd_irig_event_mapped_status_type_t type, uint32_t vector);
void CheckForStatusChange(int32_t cardIndex, int32_t modNum, int32_t channelCount);
void ClearInterrupt(int32_t cardIndex, int32_t module, naibrd_irig_event_mapped_status_type_t type);

#if defined (__VXWORKS__)
void MyIRIGIsr(uint32_t nVector);
#else
void MyIRIGIsr(void* param, uint32_t vector);
#endif

Main Application Execution

The main function here is either RG_Interrupts for VxWorks OS or main for other environments:

#if defined (__VXWORKS__)
int32_t RG_Interrupts(void)
#else
int32_t main(void)
#endif
{
   ...
}
  • Key Variables: c bool_t stop = FALSE; int32_t cardIndex; int32_t moduleCnt; int32_t module; uint32_t moduleID = 0; int8_t inputBuffer[80]; int32_t inputResponseCnt; These variables are used for controlling the flow and storing user input.

  • Flow Control: c if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE) { while (stop != TRUE) { …​ } } The application runs a board menu for interacting with the modules.

Handling IRIG Interrupts

  • Run_IRIG_Interrupts: Configures the IRIG module to generate interrupts based on specific conditions. c void Run_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid) { …​ }

  • Setup_IRIG_Interrupts: Sets up the IRIG module to trigger interrupts. c void Setup_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, naibrd_irig_event_mapped_status_type_t type, uint32_t vector) { …​ }

  • ClearInterrupt: Clears the interrupt status so that new interrupts can be processed. c void ClearInterrupt(int32_t cardIndex, int32_t module, naibrd_irig_event_mapped_status_type_t type) { …​ }

  • ISR Handling: Interrupt Service Routine (ISR) for handling IRIG interrupts. c #if defined (RUN_ISR) void MyIRIGIsr(void* param, uint32_t vector) { …​ } #endif

Running the Application

The function RG_Interrupts or main will prompt for a card index and module number, then sets up the necessary configurations to handle IRIG interrupts. The application will then wait for interrupts and handle them accordingly.

This sample code serves as an essential guide for those looking to understand or implement IRIG interrupt handling with NAI’s embedded function modules. It includes the setup of interrupts, handling of ISR, and clean-up processes, providing a comprehensive example for developers.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

#if defined (__VXWORKS__)
#include "vxBusLib.h"
#endif

/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_irig.h"
#include "advanced/nai_ether_adv.h"

#define TIMEOUT 1000      /* 1 second */

#define FIRST_IRIG_CHANNEL_IDX    0

#define IRIG_CHANNEL1_INTERRUPT_VECTOR 0x000000A1u
//#define IRIG_CHANNEL2_INTERRUPT_VECTOR 0x000000A2u

static const int8_t *CONFIG_FILE = (const int8_t *)"default_RGInterrupts.txt";

typedef enum interrupt_status_type_e
{
   INTERRUPT_WAITING,
   INTERRUPT_RECEIVED,
   INTERRUPT_ERROR_UNEXPECTED_VECTOR
} interrupt_status_type_t;

/* Function prototypes */
void Run_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid);
void Setup_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, naibrd_irig_event_mapped_status_type_t type,
   uint32_t vector);
void CheckForStatusChange(int32_t cardIndex, int32_t modNum, int32_t channelCount);
void ClearInterrupt(int32_t cardIndex, int32_t module, naibrd_irig_event_mapped_status_type_t type);

#if defined (__VXWORKS__)
void MyIRIGIsr(uint32_t nVector);
#else
void MyIRIGIsr(void* param, uint32_t vector);
#endif

const naibrd_irig_event_mapped_status_type_t type[] = {
   NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED
   /* TODO: NAI_IRIG_STATUS_CHANNEL1_LATCHED, NAI_IRIG_STATUS_CHANNEL2_LATCHED, NAI_IRIG_STATUS_CHANNEL3_LATCHED,
   NAI_IRIG_STATUS_CHANNEL4_LATCHED,
   NAI_IRIG_STATUS_CHANNEL5_LATCHED, NAI_IRIG_STATUS_CHANNEL6_LATCHED, NAI_IRIG_STATUS_CHANNEL7_LATCHED,
   NAI_IRIG_STATUS_CHANNEL8_LATCHED*/
};
const uint32_t vector[] = {
   IRIG_CHANNEL1_INTERRUPT_VECTOR
   /* TODO: IRIG_CHANNEL1_INTERRUPT_VECTOR, IRIG_CHANNEL2_INTERRUPT_VECTOR, IRIG_CHANNEL3_INTERRUPT_VECTOR,
   IRIG_CHANNEL4_INTERRUPT_VECTOR,
   IRIG_CHANNEL5_INTERRUPT_VECTOR, IRIG_CHANNEL6_INTERRUPT_VECTOR, IRIG_CHANNEL7_INTERRUPT_VECTOR,
   IRIG_CHANNEL8_INTERRUPT_VECTOR*/
};

volatile uint8_t isrLock = 0;
volatile uint32_t irqIRIGCount = 0;
volatile uint32_t receivedVector = 0;
volatile nai_status_bit_t receivedChannelStatus = 0;
volatile naibrd_irig_event_mapped_status_type_t receivedType = NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
volatile interrupt_status_type_t interruptStatus = INTERRUPT_WAITING;

/**************************************************************************************************************/
/** \defgroup IRIGInterrupts IRIG Interrupts
The purpose of the IRIG Interrupts sample application is to illustrate the methods to call in the naibrd
library to configure a given IRIG TODO status to interrupt on. Interrupts in this example are routed
to the cPCI backplane.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t RG_Interrupts(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  Run_IRIG_Interrupts(cardIndex, module, moduleID);
               }
            }
         }

         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   printf("\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();

   return 0;
}

/**************************************************************************************************************/
/** \ingroup IRIGInterrupts
Configures an IRIG module to interrupt on the TODO status. The user can choose, via the USE_ISR
preprocessor directive to use interrupts or poll instead.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum    (Input) Module Number of the module to access (1 - [max modules for board]).
\param modid     (Input) The ID of the module.
*/
/**************************************************************************************************************/
void Run_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid)
{
   int32_t channelCount;
   int32_t chanIndex;
   bool_t bContinue = TRUE;
#if defined (RUN_ISR)
   nai_status_bit_t channelStatus;
#endif

   channelCount = naibrd_IRIG_GetChannelCount(modid);

   for (chanIndex = FIRST_IRIG_CHANNEL_IDX; chanIndex < channelCount; chanIndex++)
   {
      /* Make sure there are no pending interrupts before they are enabled. */
      ClearInterrupt(cardIndex, modNum, type[chanIndex]);

      /* Setup Interrupts */
      Setup_IRIG_Interrupts(cardIndex, modNum, type[chanIndex], vector[chanIndex]);
   }

#if defined (RUN_ISR)
   /* Install the ISR */
   check_status(naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_DONT_CARE, (nai_isr_t)MyIRIGIsr, NULL));
#endif

   printf("\nInterrupts are fired from a NAI-75G5 to NAI-INT2.  Modify the parameters in");
   printf("\nthe function naibrd_InstallISR and naibrd_IRIG_SetEventMappedInterruptSteering for other interrupt configuration.");
   printf("\nWaiting for Interrupts .....\n");

   do
   {
#if !defined (RUN_ISR)
      CheckForStatusChange(cardIndex, modNum, channelCount);
#if defined (__VXWORKS__)
      taskDelay(1);
#endif
#endif  /* RUN_ISR */

      if (isrLock == 0)
      {
         switch (interruptStatus)
         {
            case INTERRUPT_RECEIVED:
            {
               /* This indicates that we received the interrupt that was expected. */
#if defined (RUN_ISR)
         /* Read the latched channel status register to see what caused the interrupt. */
               check_status(naibrd_IRIG_GetEventMappedStatus(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, receivedType, &channelStatus));
               receivedChannelStatus = channelStatus;

#endif /* RUN_ISR */
               printf("Interrupt Received: Vector- 0x%X, ChannelStatus- 0x%X, count- %u\n",
                  receivedVector, receivedChannelStatus, irqIRIGCount);

               /* Subsequent interrupts will not occur until the previous ones have been cleared. */
               ClearInterrupt(cardIndex, modNum, receivedType);
               break;
            }
            case INTERRUPT_ERROR_UNEXPECTED_VECTOR:
            {
               /* This indicates that we received the interrupt that was not expected. */
               printf("Unexpected Interrupt Received: Vector- 0x%X, count- %u\n",
                  receivedVector, irqIRIGCount);
               break;
            }
            case INTERRUPT_WAITING:
            {
               /* Nothing to do but wait for an interrupt. */
               break;
            }
            default:
               break;
         }
      }
#if defined (__VXWORKS__)
      taskDelay(1);
#endif
   } while (bContinue);

}

/**************************************************************************************************************/
/** \ingroup IRIGInterrupts
Configures an IRIG module to interrupt on the TODO status.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum    (Input) Module Number of the module to access (1 - [max modules for board]).
\param type      (Input) Interrupt Status Type: refer to naibrd_irig_event_mapped_status_type_t definition.
\param vector    (Input) Interrupt vector to identify which channel caused the interrupt.
*/
/**************************************************************************************************************/
void Setup_IRIG_Interrupts(int32_t cardIndex, int32_t modNum, naibrd_irig_event_mapped_status_type_t type,
   uint32_t vector)
{
   naibrd_irig_event_mapped_category_type_t categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
   switch (type)
   {
      case NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_BIT_SOFT_FAULT_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_BIT_SOFT_FAULT_REALTIME:
         categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
      break;
      case NAIBRD_IRIG_EVTMAP_STATUS_REF_LOSS_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_REF_LOSS_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_RX_REF_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_RX_REF_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_REF_PULSE_RX_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_REF_PULSE_RX_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_INTERRUPT_1PPS_OUTPUT_HIGH_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_INTERRUPT_1PPS_OUTPUT_HIGH_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_RX_CONTROL_BITS_CHANGED_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_RX_CONTROL_BITS_CHANGED_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_CONTROL_BITS_RX_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_CONTROL_BITS_RX_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_CHANGE_REF_SRC_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_CHANGE_REF_SRC_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_EVENT_DETECTED_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_EVENT_DETECTED_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_USER_INTERRUPT_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_USER_INTERRUPT_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_DST_ADJUST_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_DST_ADJUST_REALTIME:
      case NAIBRD_IRIG_EVTMAP_STATUS_TEST_INTERRUPT_LATCHED:
      case NAIBRD_IRIG_EVTMAP_STATUS_TEST_INTERRUPT_REALTIME:
         categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_GENERAL;
      break;
      default:
         categoryType = NAIBRD_IRIG_EVTMAP_CATEGORY_BIT;
      break;
   }
   check_status(naibrd_IRIG_SetEventMappedInterruptTriggerType(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, type, NAIBRD_IRIG_EDGE_INTERRUPT));
   check_status(naibrd_IRIG_SetEventMappedInterruptVector(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, categoryType, vector));
   check_status(naibrd_IRIG_SetEventMappedInterruptSteering(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, categoryType, NAIBRD_INT_STEERING_CPCI_APP));
   check_status(naibrd_IRIG_SetEventMappedInterruptEnable(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, type, TRUE));
}

#if defined (RUN_ISR)
/*****************************/
/* Interrupt Service Routine */
/*****************************/
#if defined (__VXWORKS__)
void MyIRIGIsr(uint32_t nVector)
#else
void MyIRIGIsr(void* param, uint32_t vector)
#endif
{
   irqIRIGCount++;
   isrLock = 1;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(param);
#endif

#if defined (__VXWORKS__)
   /* Get the vector that caused the interrupt */
   unsigned int vector = nai_Onboard_GetInterruptVector();
   /* Clear Interrupt */
   nai_Onboard_ClearInterrupt();
#endif

   /* Determine what interrupt was received */
   receivedVector = vector;
   switch (vector)
   {
      case IRIG_CHANNEL1_INTERRUPT_VECTOR:
         receivedType = type[0];
         interruptStatus = INTERRUPT_RECEIVED;
         break;
      case IRIG_CHANNEL2_INTERRUPT_VECTOR:
         interruptStatus = INTERRUPT_RECEIVED;
         receivedType = type[1];
         break;
      default:
         receivedType = NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
         receivedChannelStatus = 0;
         interruptStatus = INTERRUPT_ERROR_UNEXPECTED_VECTOR;
         break;
   }
   isrLock = 0;
}
#else

/**************************************************************************************************************/
/** \ingroup IRIGInterrupts
Checks each channel (up to channelCount) for the TODO status. Set's interrupt received flag
if condition has been met. This is function is only called if the user undefined RUN_ISR.
\param cardIndex    (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum       (Input) Module Number of the module to access (1 - [max modules for board]).
\param channelCount (Input) Channel Number of the channel to access (1 - [max channels for module]).
*/
/**************************************************************************************************************/
void CheckForStatusChange(int32_t cardIndex, int32_t modNum, int32_t channelCount)
{
   nai_status_bit_t channelStatus;
   static int32_t chanIndex = 0;

   /* chanIndex is a static variable and allows processing multiple interrupts. In the event that multiple
      interrupts occur at once, the first interrupt is flagged and every subsequent call to this function will
      check the next channel and flag the interrupt. */
   do
   {
      check_status(naibrd_IRIG_GetEventMappedStatus(cardIndex, modNum, FIRST_IRIG_CHANNEL_IDX + 1, type[chanIndex], &channelStatus));
      if (NAI_STATUS_BIT_LO != channelStatus)
      {
         irqIRIGCount++;
         receivedVector = vector[chanIndex];
         receivedType = type[chanIndex];
         receivedChannelStatus = channelStatus;
         interruptStatus = INTERRUPT_RECEIVED;
      }
      chanIndex++;
   } while ((chanIndex < channelCount) && (INTERRUPT_RECEIVED != interruptStatus));

   if (chanIndex >= channelCount)
   {
      chanIndex = 0;
   }
}
#endif  /* RUN_ISR */

/**************************************************************************************************************/
/** \ingroup IRIGInterrupts
Clears channel status and resets applicable application variables to allow another interrupt to occur.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum    (Input) Module Number of the module to access (1 - [max modules for board]).
\param type      (Input) Interrupt Status Type: refer to naibrd_irig_event_mapped_status_type_t definition.
*/
/**************************************************************************************************************/
void ClearInterrupt(int32_t cardIndex, int32_t module, naibrd_irig_event_mapped_status_type_t type)
{
   check_status(naibrd_IRIG_ClearEventMappedStatus(cardIndex, module, FIRST_IRIG_CHANNEL_IDX + 1, type));

   receivedVector = 0xFFFFFFFF;
   receivedType = NAIBRD_IRIG_EVTMAP_STATUS_BIT_DATA_LOSS_LATCHED;
   receivedChannelStatus = NAI_STATUS_BIT_LO;
   irqIRIGCount = 0;
   interruptStatus = INTERRUPT_WAITING;
}

Help Bot

X