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

SER Interrupts

SER Interrupts

Explanation

About Sample Application Code for NAI’s SSK

This C code demonstrates how to interact with North Atlantic Industries (NAI) embedded function modules, specifically focusing on configuring and handling serial interrupts. The code is designed to work with the NAI System Support Kit (SSK) and their specialized libraries. Below is a detailed breakdown of each part of the code to help users understand its structure and functionality.

File Inclusions and Declarations

#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_ser.h"
#include "advanced/nai_ether_adv.h"

This code includes standard C libraries, conditional inclusion for VxWorks, and essential header files for interacting with NAI hardware and serial modules.

Definitions

  • NUM_DATA_TX and MAX_DATA_RX: Constants related to data transmission.

  • CLEAR_FIFO_TIMEOUT: Timeout value for clearing the FIFO buffer.

  • FIRST_SER_CHANNEL_IDX: An index pointer indicating the start channel for serial communication.

  • SER_CHANNELX_INTERRUPT_VECTOR: Each serial channel’s interrupt vector.

Static and Typedef

#define NUM_DATA_TX  8
#define MAX_DATA_RX  20
#define CLEAR_FIFO_TIMEOUT 1000
#define FIRST_SER_CHANNEL_IDX 0

#define SER_CHANNEL1_INTERRUPT_VECTOR 0x000000A1u
#define SER_CHANNEL2_INTERRUPT_VECTOR 0x000000A2u
#define SER_CHANNEL3_INTERRUPT_VECTOR 0x000000A3u
#define SER_CHANNEL4_INTERRUPT_VECTOR 0x000000A4u
#define SER_CHANNEL5_INTERRUPT_VECTOR 0x000000A5u
#define SER_CHANNEL6_INTERRUPT_VECTOR 0x000000A6u
#define SER_CHANNEL7_INTERRUPT_VECTOR 0x000000A7u
#define SER_CHANNEL8_INTERRUPT_VECTOR 0x000000A8u

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

typedef enum interrupt_status_type_e
{
   INTERRUPT_WAITING,
   INTERRUPT_RECEIVED,
   INTERRUPT_ERROR_UNEXPECTED_VECTOR
} interrupt_status_type_t;
  • CONFIG_FILE: Config file path.

  • interrupt_status_type_e: Enumeration for interrupt status types.

Function Prototypes

These functions are declared to manage serial interrupts:

  • 'void Run_SER_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid);'

  • 'void Setup_SER_Interrupts(int32_t cardIndex, int32_t modNum, nai_ser_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, nai_ser_status_type_t type);' #if defined (VXWORKS)

  • 'void MySERIsr(uint32_t nVector);' #else

  • 'void MySERIsr(void* param, uint32_t vector);' #endif

Interrupt Variables and Types

const nai_ser_status_type_t type[] = {
   NAI_SER_STATUS_CHANNEL1_LATCHED, NAI_SER_STATUS_CHANNEL2_LATCHED, NAI_SER_STATUS_CHANNEL3_LATCHED,
   NAI_SER_STATUS_CHANNEL4_LATCHED,
   NAI_SER_STATUS_CHANNEL5_LATCHED, NAI_SER_STATUS_CHANNEL6_LATCHED, NAI_SER_STATUS_CHANNEL7_LATCHED,
   NAI_SER_STATUS_CHANNEL8_LATCHED
};

const uint32_t vector[] = {
   SER_CHANNEL1_INTERRUPT_VECTOR, SER_CHANNEL2_INTERRUPT_VECTOR, SER_CHANNEL3_INTERRUPT_VECTOR,
   SER_CHANNEL4_INTERRUPT_VECTOR,
   SER_CHANNEL5_INTERRUPT_VECTOR, SER_CHANNEL6_INTERRUPT_VECTOR, SER_CHANNEL7_INTERRUPT_VECTOR,
   SER_CHANNEL8_INTERRUPT_VECTOR
};

volatile uint8_t isrLock = 0;
volatile uint32_t irqSERCount = 0;
volatile uint32_t receivedVector = 0;
volatile nai_ser_status_t receivedChannelStatus = 0;
volatile nai_ser_status_type_t receivedType = NAI_SER_STATUS_GEN5_ENUM_COUNT;
volatile interrupt_status_type_t interruptStatus = INTERRUPT_WAITING;
  • Interrupt Variables: Define the status and vector variables for handling interrupts.

Main Function

The main function initializes and runs the serial interrupts application based on the specified configuration and module settings.

Functions

'Run_SER_Interrupts'

This function configures a serial module to interrupt on Transmit Completed status and handle interrupts or polling accordingly.

'Setup_SER_Interrupts'

Configures the settings for serial module interrupts like edge level, vector, interrupt steering, and enabling interrupts.

'MySERIsr'

Defines the ISR (Interrupt Service Routine) which processes incoming interrupts and sets appropriate flags.

'CheckForStatusChange'

This function checks each serial channel for interrupt status (Transmit Complete) and sets flags for the received interrupt. This function is used when polling instead of using an ISR.

'ClearInterrupt'

Clears the interrupt flag and resets variables to allow subsequent interrupts to occur.

Conclusion

This sample application illustrates configuring and managing serial interrupts on NAI�s embedded function modules. It uses a combination of ISRs and polling methods tailored for environments like VxWorks or generic operating systems. This guide aids understanding how to set up, trigger, and handle interrupts effectively with NAI hardware.

#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_ser.h"
#include "advanced/nai_ether_adv.h"

#define NUM_DATA_TX  8
#define MAX_DATA_RX  20
#define CLEAR_FIFO_TIMEOUT 1000      /* 1 second */

/* For 99ARM2-module 3 (SF2), The first 5 channels are GPIO. If running this code on that module,
    then set FIRST_SER_CHANNEL_IDX to 5, otherwise set it to 0. */
#define FIRST_SER_CHANNEL_IDX    0

#define SER_CHANNEL1_INTERRUPT_VECTOR 0x000000A1u
#define SER_CHANNEL2_INTERRUPT_VECTOR 0x000000A2u
#define SER_CHANNEL3_INTERRUPT_VECTOR 0x000000A3u
#define SER_CHANNEL4_INTERRUPT_VECTOR 0x000000A4u
#define SER_CHANNEL5_INTERRUPT_VECTOR 0x000000A5u
#define SER_CHANNEL6_INTERRUPT_VECTOR 0x000000A6u
#define SER_CHANNEL7_INTERRUPT_VECTOR 0x000000A7u
#define SER_CHANNEL8_INTERRUPT_VECTOR 0x000000A8u

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

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

/* Function prototypes */
void Run_SER_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid);
void Setup_SER_Interrupts(int32_t cardIndex, int32_t modNum, nai_ser_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, nai_ser_status_type_t type);

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

const nai_ser_status_type_t type[] = {
   NAI_SER_STATUS_CHANNEL1_LATCHED, NAI_SER_STATUS_CHANNEL2_LATCHED, NAI_SER_STATUS_CHANNEL3_LATCHED,
   NAI_SER_STATUS_CHANNEL4_LATCHED,
   NAI_SER_STATUS_CHANNEL5_LATCHED, NAI_SER_STATUS_CHANNEL6_LATCHED, NAI_SER_STATUS_CHANNEL7_LATCHED,
   NAI_SER_STATUS_CHANNEL8_LATCHED
};
const uint32_t vector[] = {
   SER_CHANNEL1_INTERRUPT_VECTOR, SER_CHANNEL2_INTERRUPT_VECTOR, SER_CHANNEL3_INTERRUPT_VECTOR,
   SER_CHANNEL4_INTERRUPT_VECTOR,
   SER_CHANNEL5_INTERRUPT_VECTOR, SER_CHANNEL6_INTERRUPT_VECTOR, SER_CHANNEL7_INTERRUPT_VECTOR,
   SER_CHANNEL8_INTERRUPT_VECTOR
};

volatile uint8_t isrLock = 0;
volatile uint32_t irqSERCount = 0;
volatile uint32_t receivedVector = 0;
volatile nai_ser_status_t receivedChannelStatus = 0;
volatile nai_ser_status_type_t receivedType = NAI_SER_STATUS_GEN5_ENUM_COUNT;
volatile interrupt_status_type_t interruptStatus = INTERRUPT_WAITING;

/**************************************************************************************************************/
/** \defgroup SERInterrupts Serial Interrupts
The purpose of the Serial Interrupts sample application is to illustrate the methods to call in the naibrd
library to configure a given serial channel status to interrupt on. Interrupts in this example are routed
to the cPCI backplane.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SER_Interrupt_Sample(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_SER_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 SERInterrupts
Configures a serial module to interrupt on the Transmit Completed 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_SER_Interrupts(int32_t cardIndex, int32_t modNum, uint32_t modid)
{
   int32_t channelCount;
   int32_t chanIndex;
   bool_t bContinue = TRUE;
#if defined (RUN_ISR)
   uint32_t channelStatus;
#endif

   channelCount = naibrd_SER_GetChannelCount(modid);

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

      /* Setup Interrupts */
      Setup_SER_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)MySERIsr, NULL));
#endif

   printf("\nInterrupts are fired from a NAI-75G5 to NAI-INT2.  Modify the parameters in");
   printf("\nthe function naibrd_InstallISR and naibrd_SER_SetInterruptSteering 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_SER_GetChannelStatus(cardIndex, modNum, receivedType, &channelStatus));
               receivedChannelStatus = channelStatus;

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

               /* 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, irqSERCount);
               break;
            }
            case INTERRUPT_WAITING:
            {
               /* Nothing to do but wait for an interrupt. */
               break;
            }
            default:
               break;
         }
      }
#if defined (__VXWORKS__)
      taskDelay(1);
#endif
   } while (bContinue);

}

/**************************************************************************************************************/
/** \ingroup SERInterrupts
Configures a serial module to interrupt on the Transmit Complete 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 type (latched or realtime).
\param vector    (Input) Interrupt vector to identify which channel caused the interrupt.
*/
/**************************************************************************************************************/
void Setup_SER_Interrupts(int32_t cardIndex, int32_t modNum, nai_ser_status_type_t type, uint32_t vector)
{
   check_status(naibrd_SER_SetInterruptEdgeLevel(cardIndex, modNum, type, 0));
   check_status(naibrd_SER_SetInterruptVector(cardIndex, modNum, type, vector));
   check_status(naibrd_SER_SetInterruptSteering(cardIndex, modNum, type, NAIBRD_INT_STEERING_CPCI_APP));
   check_status(naibrd_SER_SetInterruptEnable(cardIndex, modNum, type, NAI_SER_GEN5_INT_TXCOMPLETE));
}

#if defined (RUN_ISR)
/*****************************/
/* Interrupt Service Routine */
/*****************************/
#if defined (__VXWORKS__)
void MySERIsr(uint32_t nVector)
#else
void MySERIsr(void* param, uint32_t vector)
#endif
{
   irqSERCount++;
   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 SER_CHANNEL1_INTERRUPT_VECTOR:
         receivedType = type[0];
         interruptStatus = INTERRUPT_RECEIVED;
         break;
      case SER_CHANNEL2_INTERRUPT_VECTOR:
         interruptStatus = INTERRUPT_RECEIVED;
         receivedType = type[1];
         break;
      case SER_CHANNEL3_INTERRUPT_VECTOR:
         receivedType = type[2];
         interruptStatus = INTERRUPT_RECEIVED;
         break;
      case SER_CHANNEL4_INTERRUPT_VECTOR:
         receivedType = type[3];
         interruptStatus = INTERRUPT_RECEIVED;
         break;
      case SER_CHANNEL5_INTERRUPT_VECTOR:
         receivedType = type[4];
         interruptStatus = INTERRUPT_RECEIVED;
         break;
      case SER_CHANNEL6_INTERRUPT_VECTOR:
         interruptStatus = INTERRUPT_RECEIVED;
         receivedType = type[5];
         break;
      case SER_CHANNEL7_INTERRUPT_VECTOR:
         receivedType = type[6];
         interruptStatus = INTERRUPT_RECEIVED;
         break;
      case SER_CHANNEL8_INTERRUPT_VECTOR:
         receivedType = type[7];
         interruptStatus = INTERRUPT_RECEIVED;
         break;
      default:
         receivedType = NAI_SER_STATUS_GEN5_ENUM_COUNT;
         receivedChannelStatus = 0;
         interruptStatus = INTERRUPT_ERROR_UNEXPECTED_VECTOR;
         break;
   }
   isrLock = 0;
}
#else

/**************************************************************************************************************/
/** \ingroup SERInterrupts
Checks each channel (up to channelCount) for the Transmit Complete 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)
{
   uint32_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_SER_GetChannelStatus(cardIndex, modNum, type[chanIndex], &channelStatus));
      if (0 != (channelStatus & NAI_SER_GEN5_INT_TXCOMPLETE))
      {
         irqSERCount++;
         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 SERInterrupts
Clears channel status and resets applicable application variables- to allow another interrupt to occur.
status has been met.
\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 type (latched or realtime).
*/
/**************************************************************************************************************/
void ClearInterrupt(int32_t cardIndex, int32_t modNum, nai_ser_status_type_t type)
{
   check_status(naibrd_SER_ClearChannelStatus(cardIndex, modNum, type, NAI_SER_GEN5_INT_TXCOMPLETE));

   receivedVector = 0xFFFFFFFF;
   receivedType = NAI_SER_STATUS_GEN5_ENUM_COUNT;
   receivedChannelStatus = 0;
   irqSERCount = 0;
   interruptStatus = INTERRUPT_WAITING;
}

Help Bot

X