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 BasicInterrupt

SER BasicInterrupt Sample Application (SSK 2.x)

Overview

The SER BasicInterrupt sample application demonstrates how to configure and handle hardware interrupts on serial (SER) communication modules using the NAI Software Support Kit (SSK 2.x). It covers configuring a serial channel for asynchronous loopback communication, setting up an interrupt on the receive buffer high watermark status (or transmit complete status for PT1 modules), sending data to trigger the interrupt, and receiving the interrupt in a callback function. The sample provides a complete end-to-end interrupt example: channel configuration, ISR registration, interrupt steering, data transmission, and interrupt reception.

This sample supports the following serial module types: SC1, SC2, SC3, SC5, SC7, SC8, SC9, SCA, SCB, as well as combination modules with serial functionality (CMH, CMR, PT1). For PT1 modules, the sample uses the transmit complete status instead of the high watermark status because PT1 does not support loopback mode.

For the SSK 1.x version, see SER Interrupts (SSK 1.x).

Note
This sample is not available on DEOS. The interrupt callback mechanism requires POSIX thread support, which DEOS does not provide. Consult the SSK 2.x Software Development Guide for platform-specific build configuration.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a serial module installed (SC1-SC7, or a combination module with serial functionality).

  • SSK 2.x installed on your development host.

  • The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.

  • A platform that supports hardware interrupts (Petalinux or VxWorks).

How to Run

Launch the ser_basic_interrupt executable from your build output directory. On startup the application looks for a configuration file (default_SER_BasicInterrupt.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, the application configures the serial channel, sets up interrupts, and sends loopback data to trigger the interrupt automatically.

Board Connection and Module Selection

Note
This startup sequence is common to all NAI sample applications. The board connection and module selection code shown here is not specific to SER.

The main() function follows a standard SSK 2.x startup flow:

  1. Call naiapp_RunBoardMenu() to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_SER_BasicInterrupt.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear.

  2. Query the user for a card index with naiapp_query_CardIndex().

  3. Query for a module slot with naiapp_query_ModuleNumber().

  4. Retrieve the module ID with naibrd_GetModuleName() so downstream code can verify the selected slot contains a serial module.

  5. Query for a channel number with naiapp_query_ChannelNumber().

#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t SER_BasicInterrupt(void)
#else
int32_t main(void)
#endif
{
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   bool_t stop = NAI_FALSE;
   uint32_t moduleID;
   int32_t channelCount, chanNum;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == (bool_t)NAI_TRUE)
   {
      while (stop != NAI_TRUE)
      {
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(),
            DEF_SER_CARD_INDEX, &cardIndex);
         if (stop != NAI_TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            stop = naiapp_query_ModuleNumber(moduleCnt, DEF_SER_MODULE, &module);
            if (stop != NAI_TRUE)
            {
               check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
               if ((moduleID != 0))
               {
                  channelCount = naibrd_SER_GetChannelCount(moduleID);
                  stop = naiapp_query_ChannelNumber(channelCount,
                     DEF_SER_CHANNEL, &chanNum);
                  if (stop != NAI_TRUE)
                  {
                     g_serParams->cardIndex = cardIndex;
                     g_serParams->module = module;
                     g_serParams->modId = moduleID;
                     g_serParams->channel = chanNum;

                     Run_SER_BasicInterrupt();
                  }
               }
            }
         }
      }
   }

   naiapp_access_CloseAllOpenCards();
   return 0;
}

Note the SSK 2.x differences from SSK 1.x in this startup sequence:

  • The VxWorks preprocessor guard uses NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS (SSK 1.x uses __VXWORKS__).

  • The module identifier is retrieved with naibrd_GetModuleName() (SSK 1.x uses naibrd_GetModuleID()).

  • Boolean constants are NAI_TRUE / NAI_FALSE (SSK 1.x uses TRUE / FALSE).

  • Console output uses naiif_printf() from the platform abstraction layer (SSK 1.x uses printf() directly).

Important

Common connection errors you may encounter at this stage:

  • No board found — verify that the board is powered on and physically connected. Check that the configuration file lists the correct interface and address.

  • Connection timeout — confirm network settings (for Ethernet connections) or bus configuration (for PCI/PCIe). Firewalls and IP mismatches are frequent causes.

  • Invalid card or module index — indices are zero-based for cards and one-based for modules. Ensure the values you pass match your hardware setup.

  • Module not present at selected slot — the slot you selected does not contain a serial module. Use the board menu to verify which slots are populated.

Program Structure

Entry Point

On standard platforms (Petalinux) the entry point is main(). On VxWorks the entry point is SER_BasicInterrupt() — the SSK 2.x build system selects the correct variant via a preprocessor guard.

The startup flow is the same in both cases:

  1. Attempt to load the saved configuration file via naiapp_RunBoardMenu(DEF_CONFIG_FILE).

  2. Enter a loop that queries for card index, module slot, and channel number.

  3. Store the selected parameters in the global g_serParams structure.

  4. Call Run_SER_BasicInterrupt() to validate the module, configure the channel, set up interrupts, and send test data.

  5. On exit, close all open board connections with naiapp_access_CloseAllOpenCards().

Module Validation

Run_SER_BasicInterrupt() validates the module ID against a list of supported serial module types using a switch statement. Supported types include NAIBRD_MODULE_ID_SC1 through NAIBRD_MODULE_ID_SCB, plus combination modules NAIBRD_MODULE_ID_CMH, NAIBRD_MODULE_ID_CMR, and NAIBRD_MODULE_ID_PT1:

switch (modID)
{
case NAIBRD_MODULE_ID_CMH:
case NAIBRD_MODULE_ID_CMR:
case NAIBRD_MODULE_ID_PT1:
case NAIBRD_MODULE_ID_SC1:
case NAIBRD_MODULE_ID_SC2:
case NAIBRD_MODULE_ID_SC3:
case NAIBRD_MODULE_ID_SC5:
case NAIBRD_MODULE_ID_SC7:
case NAIBRD_MODULE_ID_SC8:
case NAIBRD_MODULE_ID_SC9:
case NAIBRD_MODULE_ID_SCA:
case NAIBRD_MODULE_ID_SCB:
   Cfg_SER_Channel();
   status = NAI_SUCCESS;
   break;
default:
   naiif_printf(" *** Module selection not recognized as SER module. ***\r\n\r\n");
   status = NAI_ERROR_INVALID_MODULE;
   break;
}

Serial Channel Configuration

Before interrupts can be configured, the serial channel must be set up for communication. Cfg_SER_Channel() configures the channel for asynchronous loopback transmission (or RS-422 for PT1):

check_status(naibrd_SER_ChannelReset(cardIndex, module, chanNum));
check_status(naibrd_SER_ClearRxFifo(cardIndex, module, chanNum));
check_status(naibrd_SER_ClearTxFifo(cardIndex, module, chanNum));

check_status(naibrd_SER_SetChannelEnable(cardIndex, module, chanNum, NAI_TRUE));
check_status(naibrd_SER_SetCommProtocol(cardIndex, module, chanNum,
   NAIBRD_SER_PROTOCOL_ASYNC));
check_status(naibrd_SER_SetInterface(cardIndex, module, chanNum,
   NAIBRD_SER_INTF_LOOPBACK));
check_status(naibrd_SER_SetParityType(cardIndex, module, chanNum,
   NAIBRD_SER_PARITY_NONE));
check_status(naibrd_SER_SetNumDataBits(cardIndex, module, chanNum,
   NAIBRD_SER_DATA_BITS_8));
check_status(naibrd_SER_SetNumStopBits(cardIndex, module, chanNum,
   NAIBRD_SER_STOP_BITS_1));
check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600));
check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1));
  • Channel reset and FIFO clear — ensures the channel starts in a clean state.

  • Protocol — set to NAIBRD_SER_PROTOCOL_ASYNC for asynchronous communication.

  • Interface — set to NAIBRD_SER_INTF_LOOPBACK so transmitted data loops back to the receive buffer, enabling self-test without external wiring. PT1 modules use NAIBRD_SER_INTF_RS422 because they do not support loopback.

  • Line parameters — 8 data bits, no parity, 1 stop bit, 9600 baud.

Interrupt Configuration

The Cfg_SER_Interrupt() function performs the complete interrupt setup. The serial module uses an "EventMapped" interrupt pattern rather than the "ChanMapped" pattern used by DT and TTL modules.

Interrupt Steering Selection

The sample uses preprocessor defines to select the interrupt steering target. Only one steering option should be active at a time:

#define STEER_ONBOARD
#undef  STEER_PCIE
#undef  STEER_CPCI
#undef  STEER_VME

#if defined (STEER_ONBOARD)
   interruptSteering = NAIBRD_INT_STEERING_ONBOARD_ARM;
#elif defined (STEER_PCIE)
   interruptSteering = NAIBRD_INT_STEERING_PCIE;
#elif defined (STEER_CPCI)
   interruptSteering = NAIBRD_INT_STEERING_CPCI;
#elif defined (STEER_VME)
   interruptSteering = NAIBRD_INT_STEERING_VME;
#endif

Status Type and Watermark

The interrupt status type depends on the module. For most serial modules, the sample monitors the receive buffer high watermark status (NAIBRD_SER_EVENT_MAP_STATUS_COMM_HIGH_WATERMARK_LATCHED). For PT1 modules, it uses the transmit complete status (NAIBRD_SER_EVENT_MAP_STATUS_COMM_TXCOMPLETE_LATCHED):

if (g_serParams->modId == NAIBRD_MODULE_ID_PT1)
{
   interruptStatus = NAIBRD_SER_EVENT_MAP_STATUS_COMM_TXCOMPLETE_LATCHED;
}
else
{
   interruptStatus = NAIBRD_SER_EVENT_MAP_STATUS_COMM_HIGH_WATERMARK_LATCHED;
   status = check_status(naibrd_SER_SetRxBufferHiWatermark(cardIndex, module,
      chanNum, 25));
}

The high watermark is set to 25, meaning the interrupt will fire when 25 or more words accumulate in the receive buffer.

Connecting ISR and Configuring Delivery

/* Connect the ISR callback */
status = naibrd_ConnectISR(cardIndex, SampleCallBack);

/* Set edge triggering */
status = check_status(naibrd_SER_SetEventMappedInterruptTriggerType(cardIndex,
   module, chanNum, interruptStatus, NAIBRD_INT_TRIGGER_TYPE_EDGE));

/* Set interrupt vector (unique per channel) */
status = check_status(naibrd_SER_SetEventMappedInterruptVector(cardIndex,
   module, chanNum, NAIBRD_SER_EVENT_MAP_COMM, interruptVector));

/* Set interrupt steering */
status = check_status(naibrd_SER_SetEventMappedInterruptSteering(cardIndex,
   module, chanNum, NAIBRD_SER_EVENT_MAP_COMM, interruptSteering));

/* Enable the interrupt */
status = check_status(naibrd_SER_SetEventMappedInterruptEnable(cardIndex,
   module, chanNum, interruptStatus, NAI_TRUE));
  • naibrd_SER_SetEventMappedInterruptTriggerType() — selects edge or level triggering per channel and status type.

  • naibrd_SER_SetEventMappedInterruptVector() — assigns a unique vector per channel. The sample uses 0xA1 through 0xA8 based on channel number.

  • naibrd_SER_SetEventMappedInterruptSteering() — routes the interrupt to the selected bus.

  • naibrd_SER_SetEventMappedInterruptEnable() — enables interrupt generation for the specified status type.

Interrupt Vector Assignment

The sample assigns a unique interrupt vector to each channel so the ISR can identify the source:

switch (chanNum)
{
case 1:  interruptVector = 0x000000A1u; break;
case 2:  interruptVector = 0x000000A2u; break;
case 3:  interruptVector = 0x000000A3u; break;
case 4:  interruptVector = 0x000000A4u; break;
case 5:  interruptVector = 0x000000A5u; break;
case 6:  interruptVector = 0x000000A6u; break;
case 7:  interruptVector = 0x000000A7u; break;
case 8:  interruptVector = 0x000000A8u; break;
default: status = NAI_ERROR_INVALID_CHANNEL; break;
}

Data Transmission and Interrupt Triggering

After the interrupt is configured, Run_SER_BasicInterrupt() loads 30 words of incremental data into the transmit buffer and initiates transmission. In loopback mode, this data arrives in the receive buffer, triggering the high watermark interrupt when the count exceeds 25:

for (i = 0; i < NUM_WORDS_TO_SEND; i++)
{
   SendData[i] = (uint8_t)(i + 0x31);
}

check_status(naibrd_SER_LoadBufferWithTimeOut32(cardIndex, module, chanNum,
   SendData, NUM_WORDS_TO_SEND, NUM_WORDS_TO_SEND, NAI_TIMEOUT_NONE, &numSent));
naiif_msDelay(150);
check_status(naibrd_SER_TransmitInitiate(cardIndex, module, chanNum));

ISR Callback

The ISR callback executes when the hardware interrupt fires:

static void SampleCallBack(uint32_t vector)
{
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
   logMsg("\r\n\r\nInterrupt Received! Vector:0x%x\r\n", vector, 0, 0, 0, 0, 0);
#else
   naibsp_printf("\r\n\r\nInterrupt Received! Vector:0x%x\r\n", vector);
#endif
}

Platform-Specific Behavior

  • VxWorks — uses logMsg() for deferred logging from interrupt context.

  • Petalinux — uses naibsp_printf(), a BSP-level print function safe for interrupt context.

Note
The callback uses naibsp_printf() (BSP layer), not naiif_printf() (application layer). BSP-level print functions are designed for use in interrupt context.

Clearing Interrupt Status

The Clear_InterruptStatus() helper clears the latched interrupt status so subsequent interrupts can be received:

static void Clear_InterruptStatus(naibrd_ser_event_mapped_status_type_t interruptStatus)
{
   naibrd_SER_ClearEventMappedStatus(cardIndex, module, chanNum, interruptStatus);
}

This function is called before the interrupt is enabled to ensure a clean starting state. After an interrupt fires, you must clear the latched status before a new interrupt of the same type will occur.

Troubleshooting Reference

This table summarizes common errors and symptoms. Consult the SC3 Manual for hardware-specific diagnostic procedures.

Error / Symptom Possible Causes Suggested Resolution

No board found or connection timeout

Board not powered, incorrect or missing configuration file, network issue

Verify hardware is powered and connected. If default_SER_BasicInterrupt.txt exists, check that it lists the correct interface and address.

Module not recognized as SER

Selected slot contains a non-serial module, or module ID not in the supported list

Verify the slot contains a supported serial module (SC1-SCB, CMH, CMR, or PT1)

NAI_ERROR_NOT_SUPPORTED from naibrd_ConnectISR()

Platform does not support hardware interrupts, or interrupt support not enabled

Verify you are running on Petalinux or VxWorks with interrupt support compiled in

Interrupt configured but never fires

High watermark not reached, loopback not configured, or missing configuration step

Verify the interface is set to loopback and that enough data is sent to exceed the watermark threshold (25 words)

Interrupt fires once but never again

Latched status not cleared after interrupt

Call naibrd_SER_ClearEventMappedStatus() to clear the latch and re-arm the interrupt

Wrong vector received in ISR

Vector mismatch between configuration and ISR logic

Verify the vector assignment matches the channel number

PT1 module interrupt does not fire with high watermark

PT1 does not support loopback, high watermark status not applicable

The sample automatically uses transmit complete status for PT1. Ensure the module ID is correctly detected.

Ethernet communication does not support interrupts

Interrupt steering requires a direct bus connection (PCIe, CPCI, VME, or onboard ARM)

Use a direct hardware connection rather than Ethernet for interrupt-based applications

Full Source

The complete source for this sample is provided below for reference. The sections above explain each part in detail.

Full Source — ser_basic_interrupt.c (SSK 2.x)
/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"

/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_ser.h"

/* naiif include files */
#include "nai_libs/naiif/include/naiif_stdio.h"

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


#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
#include "logLib.h"
#endif

static const int8_t *DEF_CONFIG_FILE = (const int8_t *) "default_SER_BasicInterrupt.txt";

/* Function prototypes */
static int32_t Run_SER_BasicInterrupt();
static void Cfg_SER_Channel();

static nai_status_t Cfg_SER_Interrupt();
static void SampleCallBack(uint32_t vector);
static void Clear_InterruptStatus(naibrd_ser_event_mapped_status_type_t interruptStatus);

static const int32_t DEF_SER_CARD_INDEX = 0;
static const int32_t DEF_SER_MODULE =     1;
static const int32_t DEF_SER_CHANNEL =    1;

#define NUM_WORDS_TO_SEND                 30

naiapp_AppParameters_t g_serparams;
p_naiapp_AppParameters_t g_serParams = &g_serparams;

/**************************************************************************************************************/
/** \defgroup SERInterrupts

\brief This sample application demonstrates how to configure and use interrupts with a serial module.

The SER_BasicInterrupt sample application illustrates the methods to call in the naibrd library to perform basic interrupt operations with
the serial module.

\note There are many ways to configure interrupt steering based on your system and where the application is running. Pleaes refer to the C
preprocessor defines in `Cfg_SER_Interrupt()` to change this for your configuration.

The main steps include:
- Querying the user for the card index and module number.
- Configuring the serial channel for asynchronous communication.
- Setting up interrupts for the serial channel.
- Handling interrupts and displaying the results.
*/
/**************************************************************************************************************/
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t SER_BasicInterrupt(void)
#else
int32_t main(void)
#endif
{
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   bool_t stop = NAI_FALSE;
   uint32_t moduleID;
   int32_t channelCount, chanNum;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == (bool_t)NAI_TRUE)
   {
      while (stop != NAI_TRUE)
      {
         /* Select Card Index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), DEF_SER_CARD_INDEX, &cardIndex);
         if (stop != NAI_TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Select Module */
            stop = naiapp_query_ModuleNumber(moduleCnt, DEF_SER_MODULE, &module);
            if (stop != NAI_TRUE)
            {
               check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
               if ((moduleID != 0))
               {
                  channelCount = naibrd_SER_GetChannelCount(moduleID);
                  stop = naiapp_query_ChannelNumber(channelCount, DEF_SER_CHANNEL, &chanNum);
                  if (stop != NAI_TRUE)
                  {
                     g_serParams->cardIndex = cardIndex;
                     g_serParams->module = module;
                     g_serParams->modId = moduleID;
                     g_serParams->channel = chanNum;

                     Run_SER_BasicInterrupt();
                     naiif_printf("\r\nType Q to quit or Enter to continue:\r\n");
                     stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
                  }
               }
            }
         }
      }
   }

   naiif_printf("\r\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 Receive Buffer High Water-mark status.
and monitor the general purpose input.
*/
/**************************************************************************************************************/
static int32_t Run_SER_BasicInterrupt()
{
   int32_t cardIndex = g_serParams->cardIndex;
   int32_t module = g_serParams->module;
   uint32_t modID = g_serParams->modId;
   int32_t chanNum = g_serParams->channel;

   uint32_t SendData[NUM_WORDS_TO_SEND];
   int32_t numSent, i;
   uint32_t outRxBuffCnt;

   bool_t bQuit = NAI_FALSE;
   nai_status_t status;

   if (!bQuit)
   {
      switch (modID)
      {
      case NAIBRD_MODULE_ID_CMH:
      case NAIBRD_MODULE_ID_CMR:
      case NAIBRD_MODULE_ID_PT1:
      case NAIBRD_MODULE_ID_SC1:
      case NAIBRD_MODULE_ID_SC2:
      case NAIBRD_MODULE_ID_SC3:
      case NAIBRD_MODULE_ID_SC5:
      case NAIBRD_MODULE_ID_SC7:
      case NAIBRD_MODULE_ID_SC8:
      case NAIBRD_MODULE_ID_SC9:
      case NAIBRD_MODULE_ID_SCA:
      case NAIBRD_MODULE_ID_SCB:
         Cfg_SER_Channel();
         status = NAI_SUCCESS;
         break;
      default:
         naiif_printf(" *** Module selection not recognized as SER module. ***\r\n\r\n");
         status = NAI_ERROR_INVALID_MODULE;
         break;
      }
      if (status == NAI_SUCCESS)
      {
         Cfg_SER_Interrupt();
         naiif_printf("\r\nWaiting for an interrupt .....\r\n");

         /* Send some data in loop back to trigger the interrupt */
         naiif_printf("Sending Data:\r\n");
         for (i = 0; i < NUM_WORDS_TO_SEND; i++)
         {
            SendData[i] = (uint8_t)(i + 0x31); /* incremental data*/
            naiif_printf("data[%2d] = 0x%X\r\n", i, SendData[i]);
         }

         check_status(naibrd_SER_LoadBufferWithTimeOut32(cardIndex, module, chanNum, SendData, NUM_WORDS_TO_SEND, NUM_WORDS_TO_SEND,
            NAI_TIMEOUT_NONE, &numSent));
         naiif_msDelay(150);
         check_status(naibrd_SER_TransmitInitiate(cardIndex, module, chanNum));
         naiif_msDelay(150);
         check_status(naibrd_SER_GetRxBufferCnt(cardIndex, module, chanNum, &outRxBuffCnt));
         naiif_printf("\r\n%d words waiting in RX buffer. ", outRxBuffCnt);
      }
   }
   return cardIndex;
}

/**************************************************************************************************************/
/** \ingroup SERInterrupts
Configures a serial module for asynchronous loopback transmission.
*/
/**************************************************************************************************************/
static void Cfg_SER_Channel()
{
   int32_t cardIndex = g_serParams->cardIndex;
   int32_t module = g_serParams->module;
   int32_t chanNum = g_serParams->channel;

   check_status(naibrd_SER_ChannelReset(cardIndex, module, chanNum));
   check_status(naibrd_SER_ClearRxFifo(cardIndex, module, chanNum));
   check_status(naibrd_SER_ClearTxFifo(cardIndex, module, chanNum));

   check_status(naibrd_SER_SetChannelEnable(cardIndex, module, chanNum, NAI_TRUE));                   /* Enable channel */
   check_status(naibrd_SER_SetCommProtocol(cardIndex, module, chanNum, NAIBRD_SER_PROTOCOL_ASYNC));   /* Async mode  */
   if (g_serParams->modId == NAIBRD_MODULE_ID_PT1)
   {
      check_status(naibrd_SER_SetInterface(cardIndex, module, chanNum, NAIBRD_SER_INTF_RS422));       /* PT1 does not support loopback */
   }
   else
   {
      check_status(naibrd_SER_SetInterface(cardIndex, module, chanNum, NAIBRD_SER_INTF_LOOPBACK));    /* LoopBack    */
   }
   check_status(naibrd_SER_SetParityType(cardIndex, module, chanNum, NAIBRD_SER_PARITY_NONE));        /* No Parity   */
   check_status(naibrd_SER_SetNumDataBits(cardIndex, module, chanNum, NAIBRD_SER_DATA_BITS_8));       /* 8 Data Bits */
   check_status(naibrd_SER_SetNumStopBits(cardIndex, module, chanNum, NAIBRD_SER_STOP_BITS_1));       /* 1 Stop Bits */
   check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600));                            /* Baud rate   */
   check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1));                         /* Enable the Receiver */

   /* Wait for configuration to be ready */
   naiif_msDelay(150);
}

/**************************************************************************************************************/
/** \ingroup SERInterrupts
Configures a serial module to interrupt on the Receive Buffer High Water-mark status and inserts a user callback
interrupt service routine. Prints out interrupt configuration.
*/
/**************************************************************************************************************/
static nai_status_t Cfg_SER_Interrupt()
{
   int32_t cardIndex = g_serParams->cardIndex;
   int32_t module = g_serParams->module;
   int32_t chanNum = g_serParams->channel;

   nai_status_t status = NAI_SUCCESS;
   naibrd_ser_event_mapped_status_type_t interruptStatus;
   uint32_t interruptVector, outvector;
   naibrd_int_steering_t interruptSteering, outsteering;
   uint32_t hiWaterMark = 0u;
   naibrd_int_trigger_type_t outtriggerType;
   bool_t outenable;

   /* Pick one interrupt steering that applies to the board and system you are using */
#define STEER_ONBOARD
#undef  STEER_PCIE
#undef  STEER_CPCI
#undef  STEER_VME
#define  VME_INT_LEVEL  5


#if defined (STEER_ONBOARD)
   interruptSteering = NAIBRD_INT_STEERING_ONBOARD_ARM;
#elif defined (STEER_PCIE)
   interruptSteering = NAIBRD_INT_STEERING_PCIE;
#elif defined (STEER_CPCI)
   interruptSteering = NAIBRD_INT_STEERING_CPCI;
#elif defined (STEER_VME)
   interruptSteering = NAIBRD_INT_STEERING_VME;
#endif

   if (g_serParams->modId == NAIBRD_MODULE_ID_PT1)
   {
      /* PT1 does not have a loopback interface, so we will not be able to use the high watermark status for an interrupt */
      interruptStatus = NAIBRD_SER_EVENT_MAP_STATUS_COMM_TXCOMPLETE_LATCHED;
   }
   else
   {
      interruptStatus = NAIBRD_SER_EVENT_MAP_STATUS_COMM_HIGH_WATERMARK_LATCHED;

      /* Set serial specific flag, this will trigger an interrupt when 25 words are present in the serial RX buffer */
      status = check_status(naibrd_SER_SetRxBufferHiWatermark(cardIndex, module, chanNum, 25));
   }

   /* Set interrupt vector and status type based on the desired channel */
   switch (chanNum)
   {
   case 1:
      interruptVector = 0x000000A1u;
      break;
   case 2:
      interruptVector = 0x000000A2u;
      break;
   case 3:
      interruptVector = 0x000000A3u;
      break;
   case 4:
      interruptVector = 0x000000A4u;
      break;
   case 5:
      interruptVector = 0x000000A5u;
      break;
   case 6:
      interruptVector = 0x000000A6u;
      break;
   case 7:
      interruptVector = 0x000000A7u;
      break;
   case 8:
      interruptVector = 0x000000A8u;
      break;
   default:
      status = NAI_ERROR_INVALID_CHANNEL;
      interruptVector = 0x0u;
      break;
   }

   if (status == NAI_SUCCESS)
   {
      /* Make sure interrupt is cleared before we start */
      Clear_InterruptStatus(interruptStatus);

      /* Specify callback function for interrupt type */
#ifdef NAI_USE_INTF_VME
      if (interruptSteering == NAIBRD_INT_STEERING_VME)
      {
         naibsp_sys_vme_SetVmeIntLvl(cardIndex, VME_INT_LEVEL);   /* HNP VME you need vector, think of a better way to set */
      }
#endif

      status = naibrd_ConnectISR(cardIndex, SampleCallBack); /* Invoked once per card, not per interrupt type */
      if (status == NAI_ERROR_NOT_SUPPORTED)
      {
         naiif_printf("\r\n**Interrupts are either not supported on this platform or not enabled**\r\n");
      }
      else if (status != NAI_SUCCESS)
      {
         naiif_printf("\r\n**Failed to connect ISR!**\r\n");
      }

      status = check_status(naibrd_SER_SetEventMappedInterruptTriggerType(cardIndex, module, chanNum, interruptStatus,
                                                                          NAIBRD_INT_TRIGGER_TYPE_EDGE));
      status = check_status(naibrd_SER_SetEventMappedInterruptVector(cardIndex, module, chanNum, NAIBRD_SER_EVENT_MAP_COMM,
                                                                     interruptVector));
      status = check_status(naibrd_SER_SetEventMappedInterruptSteering(cardIndex, module, chanNum, NAIBRD_SER_EVENT_MAP_COMM,
                                                                       interruptSteering));
      status = check_status(naibrd_SER_SetEventMappedInterruptEnable(cardIndex, module, chanNum, interruptStatus, NAI_TRUE));

      /* Get Interrupt Config */
      check_status(naibrd_SER_GetEventMappedInterruptTriggerType(cardIndex, module, chanNum, interruptStatus, &outtriggerType));
      check_status(naibrd_SER_GetEventMappedInterruptVector(cardIndex, module, chanNum, NAIBRD_SER_EVENT_MAP_COMM, &outvector));
      check_status(naibrd_SER_GetEventMappedInterruptSteering(cardIndex, module, chanNum, NAIBRD_SER_EVENT_MAP_COMM,  &outsteering));
      check_status(naibrd_SER_GetEventMappedInterruptEnable(cardIndex, module, chanNum, interruptStatus, &outenable));
      check_status(naibrd_SER_GetRxBufferHiWatermark(cardIndex, module, chanNum, &hiWaterMark));

      naiif_printf("\r\nInterrupt Configuration\r\n");
      naiif_printf("=======================\r\n");
      naiif_printf("Card Index:%d\r\n", cardIndex);
      naiif_printf("Module Number:%d\r\n", module);
      naiif_printf("Channel:%d\r\n", chanNum);
      naiif_printf("Trigger Type: %s\r\n", outtriggerType == NAIBRD_INT_TRIGGER_TYPE_EDGE ? "EDGE" : "LEVEL");
      naiif_printf("Vector: 0x%x\r\n", outvector);
      naiif_printf("Steering: ");
      switch (outsteering)
      {
      case NAIBRD_INT_STEERING_VME:
         naiif_printf("VME\r\n");
         break;
      case NAIBRD_INT_STEERING_ONBOARD_ARM:
         naiif_printf("Onboard ARM\r\n");
         break;
      case NAIBRD_INT_STEERING_PCIE:
         naiif_printf("PCIE\r\n");
         break;
      case NAIBRD_INT_STEERING_CPCI:
         naiif_printf("CPCI\r\n");
         break;
      }

      if (interruptStatus == NAIBRD_SER_EVENT_MAP_STATUS_COMM_HIGH_WATERMARK_LATCHED)
      {
         naiif_printf("Hi watermark interrupt enable: %s\r\n", outenable == NAI_TRUE ? "TRUE" : "FALSE");
         naiif_printf("Status: Receive buffer high water-mark (%d bytes)\r\n", hiWaterMark);
         naiif_printf("\r\n\r\n Waiting for channel %d's RX buffer to have %d words in it to trigger interrupt.\r\n", chanNum, hiWaterMark);
         naiif_printf("Hi watermark interrupt enable: %s\r\n", outenable == NAI_TRUE ? "TRUE" : "FALSE");
      }

      if (interruptStatus == NAIBRD_SER_EVENT_MAP_STATUS_COMM_TXCOMPLETE_LATCHED)
      {
         naiif_printf("Transmit complete interrupt enable: %s\r\n", outenable == NAI_TRUE ? "TRUE" : "FALSE");
         naiif_printf("\r\n\r\n Waiting for transmit complete to trigger interrupt.\r\n");
      }
   }
   return status;
}

/**************************************************************************************************************/
/** \ingroup SERInterrupts
The callback function that is installed via naibrd_ConnectISR(). This function will be called when the
interrupt is received. Prints out that the interrupt has been received.
\param vector (Input) Interrupt vector to identify which channel caused the interrupt.
*/
/**************************************************************************************************************/
static void SampleCallBack(uint32_t vector)
{
   /* Printing in an ISR is always a bad idea. For demonstration purposes only.
    * logMsg & naibsp_printf are a little better since they queue up messages. */
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
   logMsg("\r\n\r\nInterrupt Received! Vector:0x%x\r\n", vector, 0, 0, 0, 0, 0);
#else
   naibsp_printf("\r\n\r\nInterrupt Received! Vector:0x%x\r\n", vector);
#endif

}

/**************************************************************************************************************/
/** \ingroup SERInterrupts
Clears the interrupt status (in this case either the high watermark or transmit complete status).
This is needed to be able to receive any additional interrupts of this type.
\param interruptStatus (Input) The status to clear.
*/
/**************************************************************************************************************/
static void Clear_InterruptStatus(naibrd_ser_event_mapped_status_type_t interruptStatus)
{
   int32_t cardIndex = g_serParams->cardIndex;
   int32_t module = g_serParams->module;
   int32_t chanNum = g_serParams->channel;

   /* Clear the interrupt status */
   naibrd_SER_ClearEventMappedStatus(cardIndex, module, chanNum, interruptStatus);
}

Help Bot

X