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

AR Interrupt Ethernet

AR Interrupt Ethernet Sample Application (SSK 1.x)

Overview

The AR Interrupt Ethernet sample application demonstrates how to receive ARINC 429 (AR) interrupt notifications over an Ethernet network using the NAI Software Support Kit (SSK 1.x) Interrupt Driven Response (IDR) mechanism. When an ARINC message arrives on a configured receive channel, the board generates an interrupt and — instead of invoking a local ISR — sends a UDP packet to a remote host containing the interrupt status and any embedded read/write commands you configured. Your application runs an IDR server that listens for these packets, decodes the status, and reads the FIFO data.

This is the Ethernet IDR-only variant of the ARINC interrupt handling samples. It operates on a single channel and delivers all interrupt information in a single UDP message to a remote host. For the combined ISR + IDR version that supports multi-channel monitoring and both onboard/offboard ISR delivery alongside Ethernet IDR, see the AR Interrupt sample application guide. For a simplified ISR-only starting point with no Ethernet involvement, see the AR Interrupt Basic sample application guide.

This sample supports the following ARINC module types: AR1, AR2, CM2, and CM5.

Why Ethernet IDR?

Standard interrupt delivery (ISR) requires your application to run on the same board or be connected via a backplane bus (PCI/PCIe/cPCI). Ethernet IDR removes that constraint entirely:

  • Remote monitoring — your application can run on any host reachable over the network. There is no need for a physical bus connection to the board.

  • All status in one message — the IDR packet contains the interrupt status register value and any read/write command results you configured, eliminating the need for separate register reads after the interrupt fires.

  • Automatic re-arming — you can include a write command in the IDR configuration that clears the latched status register as part of the response, so interrupts re-arm without a separate API call from the host.

  • Reduced host-side complexity — no ISR installation, no IRQ management, no thread synchronization. Your application simply listens on a UDP socket.

The tradeoff is that Ethernet IDR is only available on Gen4 and later boards, and network latency is inherently higher than a local ISR. For latency-critical applications where the host is directly connected to the board, standard ISR delivery may be more appropriate.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with an ARINC module installed (AR1, AR2, or a combination module such as CM2, CM5).

  • A Gen4 or later board with Ethernet connectivity. Earlier board generations do not support the Ethernet IDR protocol.

  • SSK 1.x installed on your development host.

  • The sample applications built. Refer to the SSK 1.x build instructions for your platform if you have not already compiled them.

  • Network connectivity between the host running this sample and the board. The host must be reachable at the IP address configured in the IDR settings (default: 192.168.1.100).

How to Run

Launch the AR_Interrupt_Ethernet executable from your build output directory. On startup the application looks for a configuration file (default_AR_Interrupt_Ethernet.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 prompts you for channel selection, trigger mode, IDR network settings, and interrupt display options, then begins listening for IDR packets from the board.

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 AR. For details on board connection configuration, see the First Time Setup Guide.

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

  1. Initialize AR, interrupt, and IDR configuration structures with defaults using initializeARConfigurations(), initializeInterruptConfigurations(), and initializeIDRConfigurations(). The IDR initialization sets the default response IP address (192.168.1.100), UDP port (52802), and protocol (ETHER_GEN4_UDP_PROTOCOL).

  2. Call naiapp_RunBoardMenu() to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_AR_Interrupt_Ethernet.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.

  3. Query the user for card index and module number.

  4. Retrieve the module ID with naibrd_GetModuleID() to verify an ARINC module is installed at the selected slot.

#if defined (__VXWORKS__)
int32_t AR_Interrupt_Basic_Ethernet(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   initializeARConfigurations( 0, 0, 0, 0, 0, 0, MAX_FIFO_COUNT, DEF_AR_TIMESTAMP, FALSE);
   initializeInterruptConfigurations(FALSE,FALSE,FALSE,0,0,0,0);

   initializeIDRConfigurations(0,0,DEF_RX_RESPONSE_PROTOCOL,DEF_RX_RESPONSE_PORT,
                              DEF_RX_RESPONSE_IPv4_ADDR, DEF_RX_RESPONSE_IPv4_LENGTH,
                              COMMANDS,0,ETHERNET_OVERHEAD_FIFO_COMMAND,DEF_ETHERNET_AR_IDR_ID);

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         inputARConfig.cardIndex = cardIndex;
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            inputARConfig.module = module;
            if (stop != TRUE)
            {
               inputARConfig.modid = naibrd_GetModuleID(cardIndex, module);
               if ((inputARConfig.modid != 0))
               {
                  Run_AR_Interrupt_Basic_Ethernet();
               }
            }
         }
         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;
}

Note the three initialization calls before the board menu. initializeIDRConfigurations() is unique to the Ethernet variant — it populates the IDRConfig structure with default network settings that are used later when configuring the board’s IDR engine.

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 an ARINC module. Use the board menu to verify which slots are populated.

Program Structure

The AR Interrupt Ethernet sample is split across multiple source files:

  • AR_Interrupt_Ethernet.c — the application entry point. Contains main() and Run_AR_Interrupt_Basic_Ethernet(), which orchestrates the Gen4 check, user prompts, IDR setup, interrupt configuration, IDR server execution, and cleanup.

  • nai_ar_int_ether.c — Ethernet IDR-specific code shared with the AR_Interrupt full variant. Contains setupIDRConfiguration_AR(), IDR command construction functions (InitARRxIDRCommands(), MakeARRxReadRegsCommand(), MakeARRxWriteRegsCommand()), and HandleAREtherInterrupt() which decodes incoming IDR packets.

  • nai_ar_int.c — shared interrupt configuration logic. Contains configureARToInterruptOnRx(), enableARInterrupts(), GetARLatchStatusTriggerMode(), and ClearInterrupt_AR().

  • nai_ar_cfg.c — shared ARINC configuration. Contains Cfg_Rx_AR(), initializeARConfigurations(), and channel setup functions.

Shared Data Structures

The sample uses three key structures to track configuration state:

/* From nai_ar_cfg.h */
typedef struct
{
   int32_t cardIndex;
   int32_t module;
   uint32_t modid;
   int32_t channel;
   int32_t maxChannel;
   int32_t minChannel;
   int32_t buffer_Length;
   nai_ar_tstamp_t ar_timeStamp;
   bool_t timeStampEnable;
} ArConfig;

ArConfig captures the ARINC module identification and channel settings. In the Ethernet variant, channel specifies the single channel to monitor for interrupts. timeStampEnable controls whether timestamps are captured with each received ARINC message.

/* From naiapp_interrupt.h */
typedef struct _InterruptConfig
{
   bool_t  bPromptForInterruptClear;
   bool_t  bProcessOnboardInterrupts;
   bool_t  displayData;
   int32_t interrupt_Edge_Trigger;
   int32_t steering;
   int32_t irq;
   int32_t cardIndex;
} InterruptConfig;

InterruptConfig captures the interrupt delivery preferences: trigger mode (edge vs. level), steering destination, and whether data should be displayed to the console or logged to a file. The bProcessOnboardInterrupts flag determines whether the IDR commands target the board’s onboard interface or an offboard (PCI) interface.

/* From naiapp_interrupt_ether.h */
typedef struct _IDRConfig
{
   int32_t  cardIndex;
   nai_intf_t boardInterface;
   uint16_t protocol;
   uint16_t port;
   uint8_t  *ipAddress;
   uint8_t  ipLength;
   uint8_t  *commands;
   uint16_t cmdcount;
   uint16_t cmdlength;
   uint16_t idrId;
} IDRConfig;

IDRConfig captures the Ethernet IDR network settings: the UDP protocol, destination IP address and port where interrupt notifications are sent, and the command buffer that stores the read/write operations the board executes when an interrupt fires. The cmdcount and cmdlength fields track the number and total byte length of the embedded commands.

Gen4 Ethernet Requirement Check

The first thing Run_AR_Interrupt_Basic_Ethernet() does after determining the channel count is verify that the connected board supports Gen4 Ethernet commands. This is a hard requirement — earlier board generations do not have the IDR engine.

inputARConfig.maxChannel = naibrd_AR_GetChannelCount( inputARConfig.modid );
inputARConfig.minChannel = 1;

/* check if AR module supports GEN 4 Ethernet */
bGen4ArIDRCommands = SupportsGen4Ether( inputARConfig.cardIndex );

if ( !bGen4ArIDRCommands )
{
   printf( "AR Ethernet Interrupt Support Prior to Generation 4 Ethernet commands currently not supported\n" );
   bQuit = TRUE;
}

SupportsGen4Ether() is a shared utility function that queries the board’s Ethernet generation capability. If the board does not support Gen4, the application exits the interrupt flow immediately with an error message. There is no fallback to an older protocol — you must use a Gen4 or later board for Ethernet IDR.

In your own application, always call SupportsGen4Ether() before attempting any IDR configuration. Calling naibrd_Ether_SetIDRConfig() on a pre-Gen4 board will fail.

Important

Common Errors

  • "Generation 4 Ethernet commands currently not supported" — the connected board does not support IDR. Verify you are using a Gen4 or later board. Check the board’s firmware version if you believe the hardware should support Gen4.

User Configuration Prompts

After the Gen4 check passes, the sample prompts the user for several configuration parameters before setting up the IDR and interrupt system. In your own application, you would set these values programmatically rather than prompting interactively.

bQuit = naiapp_query_ChannelNumber( inputARConfig.maxChannel, inputARConfig.minChannel, &inputARConfig.channel );

/* Query user for Trigger Status of interrupts */
bQuit = GetARLatchStatusTriggerMode( &inputInterruptConfig.interrupt_Edge_Trigger );

bQuit = QueryIDRConfigInformation( &inputIDRConfig );

bQuit = QueryUserForOnboardOffboardInterrupts( &inputInterruptConfig.bProcessOnboardInterrupts );

bQuit = QueryUserForEtherIDRMsgDisplay( &bDisplayEtherUPR );

bQuit = QueryUserForDisplayingData( &inputInterruptConfig.displayData );

bQuit = QueryUserForTimeStampEnable( &inputARConfig.timeStampEnable );

The prompts collect:

  • Channel number — which receive channel to monitor for interrupts (1 through the module’s maximum channel count).

  • Trigger mode — edge-triggered (0) or level-triggered (1, default). Level-triggered is recommended for ARINC receive interrupts because messages may arrive in bursts, and you want the interrupt to remain active until all data is processed.

  • IDR configuration — QueryIDRConfigInformation() prompts for the destination IP address, port, and protocol. Defaults are 192.168.1.100, port 52802, UDP protocol.

  • Onboard/offboard processing — determines the board interface and interrupt steering. Onboard uses NAI_INTF_ONBOARD with NAIBRD_INT_STEERING_ON_BOARD_1 steering. Offboard uses NAI_INTF_PCI with NAIBRD_INT_STEERING_CPCI_APP steering.

  • IDR message display — whether to show the raw Ethernet IDR message on the console.

  • Data display — whether to print received FIFO data to the console (stdout) or log it to a file (AR_Interrupt_FIFO_Data.txt).

  • Timestamp enable — whether to include timestamps with received ARINC messages.

IDR Configuration

The IDR (Interrupt Driven Response) is the core mechanism that makes Ethernet-based interrupt delivery work. When an interrupt fires, the board’s IDR engine executes a preconfigured sequence of register read/write commands, packages the results into a UDP packet, and sends it to the specified IP address and port. Your application never needs to issue separate register read commands after the interrupt — all the data arrives in a single network message.

Setting Up the IDR

After the user selects onboard or offboard processing, the sample configures the board interface and steering, then calls setupIDRConfiguration_AR() to build and install the IDR command set:

if ( inputInterruptConfig.bProcessOnboardInterrupts == TRUE )
{
   inputIDRConfig.cardIndex = inputARConfig.cardIndex;
   inputIDRConfig.boardInterface = NAI_INTF_ONBOARD;
   inputInterruptConfig.steering = NAIBRD_INT_STEERING_ON_BOARD_1;
}
else /* OffBoard Interrupt */
{
   inputIDRConfig.cardIndex = 0;
   inputIDRConfig.boardInterface = NAI_INTF_PCI;
   inputInterruptConfig.steering = NAIBRD_INT_STEERING_CPCI_APP;
}
setupIDRConfiguration_AR( inputARConfig, &inputIDRConfig, bGen4ArIDRCommands );
check_status( naibrd_Ether_StartIDR( inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID ) );

The steering value NAIBRD_INT_STEERING_ON_BOARD_1 tells the module to route the interrupt to the board’s onboard processor, which then triggers the IDR engine. This is the standard choice for Ethernet IDR — the onboard processor intercepts the interrupt and executes the IDR commands. The offboard path (NAIBRD_INT_STEERING_CPCI_APP) is used when the board is accessed over a backplane and the IDR engine is reached through that path.

Building IDR Commands

setupIDRConfiguration_AR() in nai_ar_int_ether.c clears any previous IDR configuration and then constructs the command buffer:

void setupIDRConfiguration_AR( ArConfig inputARConfig, IDRConfig* inputIDRConfig, bool_t bGen4ArIDRCommands )
{
   int32_t cardIndex = inputIDRConfig->cardIndex;
   uint16_t protocol = inputIDRConfig->protocol;
   uint16_t port = inputIDRConfig->port;
   uint8_t* ipAddress = inputIDRConfig->ipAddress;
   uint8_t ipLength = inputIDRConfig->ipLength;
   int32_t vector = NAI_AR_INTERRUPT_VECTOR;
   uint8_t *commands   = inputIDRConfig->commands;
   uint16_t *cmdcount  = &inputIDRConfig->cmdcount;
   uint16_t *cmdlength = &inputIDRConfig->cmdlength;

   check_status( naibrd_Ether_ClearIDRConfig( cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID ) );
   InitARRxIDRCommands( inputARConfig, inputIDRConfig, bGen4ArIDRCommands );
   check_status( naibrd_Ether_SetIDRConfig( cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID,
      protocol, ipLength, ipAddress, port, vector, *cmdcount, *cmdlength, commands ) );
}

The key API calls are:

  • naibrd_Ether_ClearIDRConfig() — clears any existing IDR configuration for the specified IDR ID. Always call this before reconfiguring an IDR to avoid stale command data.

  • InitARRxIDRCommands() — builds the embedded Ethernet read command that reads the channel’s latched interrupt status register when the interrupt fires. This is the command whose result appears in the IDR response packet.

  • naibrd_Ether_SetIDRConfig() — installs the complete IDR configuration on the board: destination protocol, IP address, port, interrupt vector to match, command count, command byte length, and the command buffer itself. After this call, the board knows where to send notifications and what register operations to embed in each packet.

IDR Read Command Construction

InitARRxIDRCommands() calls MakeARRxReadRegsCommand() to construct a Gen4 Ethernet read command targeting the channel’s latched interrupt status register:

void MakeARRxReadRegsCommand( ArConfig inputARConfig, IDRConfig* inputIDRConfig,
   uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex )
{
   uint32_t AR_GEN5_LatchedIntStatusAddr[] = NAI_AR_GEN5_REG_CH_LATCHED_INT_STATUS_ADD;
   uint16_t msgIndex = startIndex;
   uint16_t seqno;
   uint32_t count, stride;
   uint32_t regaddr;

   if (bGen4Ether)
   {
      seqno = 0;
      regaddr = boardAddress + moduleOffset + AR_GEN5_LatchedIntStatusAddr[inputARConfig.channel-1];
      count = 1;
      stride = 4;

      msgIndex = (uint16_t)nai_ether_MakeReadMessage( &inputIDRConfig->commands[startIndex],
         seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface,
         regaddr, stride, count, NAI_REG32 );

      inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
      command_index_interrupt_status = inputIDRConfig->cmdcount;
      inputIDRConfig->cmdcount++;
   }
}

The function computes the absolute register address by adding the board base address, the module offset within the board, and the per-channel latched interrupt status register offset. nai_ether_MakeReadMessage() encodes this into the Gen4 Ethernet wire format and appends it to the command buffer. The command_index_interrupt_status variable records which command index in the IDR response will contain the status register value — this is used later when decoding the response packet.

In your own application, you can add additional read or write commands to the IDR buffer. For example, MakeARRxWriteRegsCommand() constructs a write command that clears the latched status register (writes 0xFFFF) to re-arm interrupts automatically as part of the IDR response:

void MakeARRxWriteRegsCommand( ArConfig inputARConfig, IDRConfig* inputIDRConfig,
   uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex )
{
   uint32_t AR_GEN5_LatchedIntStatusAddr[] = NAI_AR_GEN5_REG_CH_LATCHED_INT_STATUS_ADD;
   uint32_t data = 0xFFFF;   /* Clear Rx interrupt bits */

   if (bGen4Ether)
   {
      uint16_t seqno = 0;
      uint32_t regaddr = moduleOffset + boardAddress + AR_GEN5_LatchedIntStatusAddr[inputARConfig.channel-1];
      uint32_t count = 1;
      uint32_t stride = 4;
      uint16_t msgIndex;

      msgIndex = (uint16_t)nai_ether_BeginWriteMessage( &inputIDRConfig->commands[startIndex],
         seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface,
         regaddr, stride, count, NAI_REG32 );
      msgIndex = (uint16_t)nai_ether_WriteMessageData( &inputIDRConfig->commands[startIndex],
         msgIndex, NAI_REG32, &data, NAI_REG32, count );
      msgIndex = (uint16_t)nai_ether_FinishMessage( &inputIDRConfig->commands[startIndex],
         msgIndex, NAI_ETHER_GEN4 );

      inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
      inputIDRConfig->cmdcount++;
   }
}

The write command uses the three-step message construction pattern: nai_ether_BeginWriteMessage() writes the header, nai_ether_WriteMessageData() appends the data payload (0xFFFF to clear all status bits), and nai_ether_FinishMessage() finalizes the message. Including this write in the IDR means the board clears its own status register immediately after sending the notification, so interrupts re-arm without requiring a separate API call from the host.

Important

Common Errors

  • naibrd_Ether_SetIDRConfig() fails — verify the IDR ID is valid and that no other IDR is already configured with the same ID. Always call naibrd_Ether_ClearIDRConfig() first.

  • Incorrect register address — the board address and module offset must be queried at runtime with naibrd_GetAddress() and naibrd_GetModuleOffset(). Hardcoded addresses will fail on different board configurations.

  • Wrong board interface — NAI_INTF_ONBOARD is for onboard processing; NAI_INTF_PCI is for offboard. Using the wrong interface causes the IDR read/write commands to target the wrong bus.

Interrupt Configuration

After the IDR is configured and started, the sample configures the ARINC module to generate interrupts on receive. This uses the same interrupt configuration functions as the standard (ISR-based) variant.

Module Interrupt Setup

configureARToInterruptOnRx() performs four steps on the selected channel:

void configureARToInterruptOnRx( InterruptConfig inputInterruptConfig, ArConfig inputARConfig )
{
   int32_t cardIndex = inputARConfig.cardIndex;
   int32_t module = inputARConfig.module;
   int32_t channel = inputARConfig.channel;
   int32_t vector = NAI_AR_INTERRUPT_VECTOR;
   int32_t interrupt_Edge_Trigger = inputInterruptConfig.interrupt_Edge_Trigger;
   int32_t steering = inputInterruptConfig.steering;

   /* clear interruptConfigs of previous channels */
   check_status( naibrd_AR_SetInterruptEnable( cardIndex, module, channel, 0 ) );
   check_status( naibrd_AR_ClearStatus( cardIndex, module, channel, 0xFFFF ) );

   check_status( naibrd_AR_SetInterruptVector( cardIndex, module, channel, vector ) );
   check_status( naibrd_AR_SetInterruptEdgeLevel( cardIndex, module, channel, interrupt_Edge_Trigger ) );
   check_status( naibrd_AR_SetInterruptSteering( cardIndex, module, channel, steering ) );
}

The steps are:

  1. Disable and clear — naibrd_AR_SetInterruptEnable() with 0 disables all interrupt sources. naibrd_AR_ClearStatus() with 0xFFFF clears all latched status bits. This prevents stale status from triggering an immediate interrupt.

  2. Set vector — naibrd_AR_SetInterruptVector() assigns NAI_AR_INTERRUPT_VECTOR to the channel. This vector must match the vector specified in the naibrd_Ether_SetIDRConfig() call so the IDR engine knows which interrupts to service.

  3. Set trigger mode — naibrd_AR_SetInterruptEdgeLevel() configures edge (0) or level (1) triggering. Level-triggered is the default and the recommended choice for ARINC receive interrupts.

  4. Set steering — naibrd_AR_SetInterruptSteering() routes the interrupt to the appropriate destination. For Ethernet IDR, this is NAIBRD_INT_STEERING_ON_BOARD_1 (onboard) so the interrupt reaches the IDR engine.

Enable Interrupts

After configuration, enableARInterrupts() enables the RX Data Available interrupt on the selected channel:

enableARInterrupts( inputARConfig, AR_RX_DATA_AVAIL );

This calls naibrd_AR_SetInterruptEnable() with the AR_RX_DATA_AVAIL bitmask. From this point forward, any ARINC message received on the channel will trigger an interrupt, which the IDR engine intercepts and sends as a UDP packet to the configured host.

ARINC Receive Channel Configuration

Cfg_Rx_AR() configures the physical ARINC receive channel so that data actually arrives:

Cfg_Rx_AR( inputARConfig );

This shared function performs the following per channel: resets the channel, disables TX/RX, sets the timestamp control, configures FIFO status thresholds, clears the RX FIFO, enables the receiver, sets the data rate (the sample prompts for low or high speed), sets the RX FIFO threshold to the maximum FIFO size, configures parity as odd, enables store-on-error, and optionally enables timestamps. The data rate is either 12.5 kbit/s (low speed, standard ARINC 429) or 100 kbit/s (high speed).

Important

Common Errors

  • No interrupts received — verify that naibrd_AR_SetInterruptSteering() used the correct steering constant for Ethernet IDR (NAIBRD_INT_STEERING_ON_BOARD_1 for onboard). Using the wrong steering routes the interrupt to a different destination.

  • Interrupt vector mismatch — the vector passed to naibrd_AR_SetInterruptVector() must match the vector in naibrd_Ether_SetIDRConfig(). A mismatch means the IDR engine will not recognize the interrupt.

  • Stale interrupts fire immediately — always clear status with naibrd_AR_ClearStatus() before enabling interrupts. Latched status from a previous run will trigger immediately if not cleared.

IDR Server and UDP Message Handling

Once the IDR is started and interrupts are enabled, the sample launches the IDR server to listen for incoming UDP packets from the board:

AR_ClearInterrupt = ClearInterrupt_AR;
arEtherIntFunc = HandleAREtherInterrupt;
bQuit = runIDRServer( inputIDRConfig );

The two function pointer assignments register the callback functions used by the IDR server framework:

  • AR_ClearInterrupt — points to ClearInterrupt_AR(), which reads and clears the latched status register. This is called to re-arm interrupts after each notification is processed.

  • arEtherIntFunc — points to HandleAREtherInterrupt(), the main handler that decodes each incoming IDR UDP packet.

runIDRServer() is a shared utility that opens a UDP socket on the configured port and enters a receive loop. Each time a packet arrives, it dispatches to the registered handler function.

Decoding IDR Packets

HandleAREtherInterrupt() in nai_ar_int_ether.c processes each incoming IDR packet. The IDR response contains one or more embedded command results corresponding to the read/write commands configured during IDR setup:

void HandleAREtherInterrupt( uint16_t msglen, uint8_t msg[], uint16_t tdr_idr_id )
{
   static uint32_t status;
   static FIFO fifoToPrint;

   int32_t index;
   uint16_t seq;
   nai_ether_typecode_t typeCode;
   nai_ether_gen_t gen = NAI_ETHER_GEN4;
   int32_t size;
   int32_t commandIndex;
   int32_t outnummsgs;
   int32_t outcount;
   uint32_t mask = 0x1;
   uint32_t statusMasked;
   uint32_t stat[NAI_AR_MAX_DATA_LEN];
   uint32_t data[NAI_AR_MAX_DATA_LEN];
   uint32_t tstamp[NAI_AR_MAX_DATA_LEN];

   nai_ether_DecodeMessageHeader(msg, msglen, &seq, &typeCode, gen, &size);

   commandIndex = ( seq & ( 0x0F << 6 ) ) >> 6;
   naibrd_Wait( 1000000 );

   switch (typeCode)
   {
      case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_WRITE_4:
         break;
      case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4:
         if ( inputIDRConfig.cmdcount-1 == commandIndex )
         {
            status = msg[11];
            status = ( status | ( msg[10] << 8 ) );
            statusMasked = status & mask;

            if ( statusMasked == mask )
            {
               check_status( naibrd_AR_GetRxBufferCnt( inputARConfig.cardIndex,
                  inputARConfig.module, inputARConfig.channel, &outcount ) );
               fifoToPrint.maxDataLength = NAI_AR_MAX_DATA_LEN;
               if ( outcount > 0 )
               {
                  check_status( naibrd_AR_ReadFifo( inputARConfig.cardIndex,
                     inputARConfig.module, inputARConfig.channel,
                     inputARConfig.timeStampEnable, outcount,
                     stat, data, tstamp, &outnummsgs ) );
                  for ( index = 0; index < outcount; index++ )
                  {
                     fifoToPrint.data[index].fifoData = data[index];
                     fifoToPrint.data[index].fifoStatus = (uint16_t)stat[index];
                     fifoToPrint.data[index].fifoTimeStamp = tstamp[index];
                  }
                  fifoToPrint.length = outcount;
               }
            }
         }
         break;
   }
   if ( commandIndex == inputIDRConfig.cmdcount - 1 )
   {
      printf( "\nInterrupt Occurred\n" );
      printEthernetInterruptInformation( tdr_idr_id, status, fifoDataFile,
         fifoToPrint.length, fifoToPrint );
   }
   /* Clear Interrupt Latch */
   check_status( naibrd_AR_ClearStatus( inputARConfig.cardIndex,
      inputARConfig.module, inputARConfig.channel, 0xFFFF ) );
}

The handler performs the following steps:

  1. Decode the message header — nai_ether_DecodeMessageHeader() extracts the sequence number, type code, and payload size from the raw UDP packet. The commandIndex is extracted from the sequence number to determine which IDR command this response corresponds to.

  2. Process by type code — write command completions (NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_WRITE_4) are acknowledged silently. Read command completions contain the register data.

  3. Extract status — for the read command matching the latched status register (identified by commandIndex == inputIDRConfig.cmdcount - 1), the handler extracts the 16-bit status value from the message payload bytes.

  4. Check RX Data Available — the status is masked with 0x1 (AR_RX_DATA_AVAIL). If the bit is set, the handler reads the FIFO buffer count with naibrd_AR_GetRxBufferCnt() and drains the FIFO with naibrd_AR_ReadFifo().

  5. Display results — printEthernetInterruptInformation() prints the IDR ID, status value, and all received FIFO messages (data, status, and timestamp for each).

  6. Clear status — naibrd_AR_ClearStatus() with 0xFFFF clears all latched status bits to re-arm the interrupt for the next event.

IDR Response Display

printEthernetInterruptInformation() formats the interrupt data for display or logging:

void printEthernetInterruptInformation( int32_t interruptID, uint32_t status,
   FILE* stream, int32_t count, FIFO fifo )
{
   fprintf( stream, "Interrupt Information\n" );
   fprintf( stream, "-----------------------------------\n" );
   fprintf( stream, "\nIDR ID = %#x \n", interruptID );
   fprintf( stream, "Status = %#x \n", status );

   statusBitSet = status & AR_RX_DATA_AVAIL;
   if ( statusBitSet )
   {
      if ( count > 0 )
      {
         fprintf( stream, "\nMax FIFO Word Count: %d\n", fifo.maxDataLength );
         fprintf( stream, "Messages Received (FIFO Word Count): %d\n", fifo.length );
         for ( i = 0; i < count; i++ )
         {
            fprintf( stream, "Message Number %d:", i + 1 );
            fprintf( stream, "\nMessage Status: %#x", fifo.data[i].fifoStatus );
            fprintf( stream, "\nMessage Data: %#x", fifo.data[i].fifoData );
            fprintf( stream, "\nTime Stamp: %#x\n\n", fifo.data[i].fifoTimeStamp );
         }
      }
   }
   fprintf( stream, "\n-----------------------------------\n" );
}

The output stream is either stdout (if the user chose to display data on the console) or a file handle for AR_Interrupt_FIFO_Data.txt (if the user chose to log data). Each interrupt event prints the IDR ID, the raw status register value, and then for each FIFO message: the message status word, the 32-bit ARINC data word, and the timestamp.

Important

Common Errors

  • No IDR packets received — verify the destination IP address matches the host running the application. Check that no firewall is blocking UDP port 52802. Confirm the board has network connectivity.

  • IDR packets arrive but show status 0 — the interrupt may have already been cleared by a write command in the IDR, or the channel may not be receiving ARINC data. Verify that a transmitter is actively sending on the bus.

  • naibrd_AR_ReadFifo() returns no data — a brief delay (the sample uses naibrd_Wait(1000000)) may be needed between detecting the interrupt and reading the FIFO, especially if the data is still being transferred into the FIFO buffer.

Cleanup

When the user quits the IDR server loop, the sample performs orderly cleanup of both module and board configurations:

/***** 7. Clear Module Configurations *****/
check_status( naibrd_AR_SetRxEnable( inputARConfig.cardIndex, inputARConfig.module,
   inputARConfig.channel, FALSE ) );
enableARInterrupts( inputARConfig, FALSE );

/***** 8. Clear Board Configurations *****/
check_status( naibrd_Ether_StopIDR( inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID ) );
check_status( naibrd_Ether_ClearIDRConfig( inputIDRConfig.cardIndex, DEF_ETHERNET_AR_IDR_ID ) );

The cleanup sequence is:

  1. Disable the receiver — naibrd_AR_SetRxEnable() with FALSE stops the channel from receiving ARINC messages.

  2. Disable interrupts — enableARInterrupts() with FALSE disables the interrupt enable for the channel.

  3. Stop the IDR — naibrd_Ether_StopIDR() halts the IDR engine on the board. After this call, the board will no longer send UDP notifications for this IDR ID.

  4. Clear the IDR configuration — naibrd_Ether_ClearIDRConfig() removes the IDR command buffer and network settings from the board.

Always stop the IDR before clearing its configuration. Clearing the configuration while the IDR is still running can result in undefined behavior.

Configuration File

The sample uses the configuration file default_AR_Interrupt_Ethernet.txt to store board connection settings. This file is not included in the SSK — it is created when you save your connection settings from the board menu during the first run. The file stores the board interface type, IP address or bus address, and other connection parameters so that subsequent runs can skip the interactive menu and connect automatically.

The default IDR network settings (IP address 192.168.1.100, port 52802, UDP protocol) are hardcoded in the source as compile-time defaults. To change them, either modify the source constants or respond to the interactive prompts when the application runs.

static uint8_t DEF_RX_RESPONSE_IPv4_ADDR[] = {192,168,1,100};

#define DEF_RX_RESPONSE_PORT        52802
#define DEF_RX_RESPONSE_PROTOCOL    ETHER_GEN4_UDP_PROTOCOL
#define DEF_RX_RESPONSE_IPv4_LENGTH ETHER_GEN4_IPv4_ADDR_LEN

Troubleshooting Reference

Note
This section summarizes errors covered in the preceding sections and provides additional network-specific diagnostics. Consult your module’s manual for hardware-specific diagnostics.
Error / Symptom Possible Causes Suggested Resolution

"Generation 4 Ethernet commands currently not supported"

Board does not support Gen4 Ethernet protocol.

Use a Gen4 or later board. Check firmware version with your NAI support contact.

No IDR packets received

Destination IP address does not match the host. Firewall blocking UDP port. Board has no network connectivity. IDR not started.

Verify IP address matches the host running the application. Open UDP port 52802 in the firewall. Ping the board to confirm connectivity. Confirm naibrd_Ether_StartIDR() was called after naibrd_Ether_SetIDRConfig().

IDR packets arrive but show status 0x0

Interrupt already cleared by an embedded write command. Channel not receiving ARINC data. Wrong channel selected.

Verify a transmitter is sending ARINC data on the monitored channel. Check that the IDR read command targets the correct register address.

No FIFO data despite status showing RX Data Available

FIFO read timing issue. FIFO was drained by a previous read.

Add a brief delay before reading the FIFO (the sample uses naibrd_Wait(1000000)). Verify only one consumer is reading the FIFO.

naibrd_Ether_SetIDRConfig() returns error

Stale IDR configuration not cleared. Invalid IDR ID. Board does not support IDR.

Call naibrd_Ether_ClearIDRConfig() before naibrd_Ether_SetIDRConfig(). Verify the IDR ID is within the valid range for your board.

Interrupts fire once but do not re-arm

Latched status not cleared after processing. Missing write command in IDR or missing naibrd_AR_ClearStatus() call.

Ensure the handler calls naibrd_AR_ClearStatus() after processing each interrupt. Alternatively, include a write command in the IDR that clears the status register automatically.

No board found / Connection timeout

Board not powered or connected. Incorrect interface or address in configuration file.

Verify physical connection. Delete the configuration file and re-run to enter settings interactively.

Invalid card or module index

Zero-based card index or one-based module index mismatch.

Cards are zero-indexed, modules are one-indexed. Verify values match your hardware setup.

Module not present at selected slot

ARINC module not installed in the selected slot.

Use the board menu to verify which slots are populated with AR1, AR2, CM2, or CM5 modules.

Full Source

AR_Interrupt_Ethernet.c

Full Source — AR_Interrupt_Ethernet.c (SSK 1.x)
/**************************************************************************************************************/
/**
<summary>

The AR_Interrupt_Ethernet program demonstrates how to perform an interrupt when a single channel receives
an ar message. The purpose of this program is to demonstrate the method calls in the naibrd library for performing
the interrupt. More information on this process can be found in the naibrd SSK Quick Guide (Interrupts) file.

</summary>
*/
/**************************************************************************************************************/

/************************/
/* Include Declarations */
/************************/

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

/* Common Module Specific Sample Program include files */
#include "nai_ar_int_ether.h"
#include "nai_ar_int.h"
#include "nai_ar_cfg.h"

/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.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"

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"

/* Module Specific NAI Board Library files */
#include "functions/naibrd_ar.h"
#include "maps/nai_map_ar.h"

static uint8_t DEF_RX_RESPONSE_IPv4_ADDR[] =   {192,168,1,100};
static uint8_t COMMANDS[MAX_ETHER_IDR_CMD_CNT*MAX_ETHER_BLOCK_REG_CNT];

InterruptConfig inputInterruptConfig;
IDRConfig inputIDRConfig;
ClearInterrupt AR_ClearInterrupt;
etherIntFuncDef arEtherIntFunc;
bool_t bDisplayEtherUPR;

/* Extern Functions or Variables*/
extern ArConfig inputARConfig;
extern FILE* fifoDataFile;

/*********************************************/
/* Application Name and Revision Declaration */
/*********************************************/
static const int8_t *CONFIG_FILE = (int8_t *)"default_AR_Interrupt_Ethernet.txt";

/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_AR_Interrupt_Basic_Ethernet();

/**************************************************************************************************************/
/*****                                     Main Routine                                                   *****/
/**************************************************************************************************************/

/**************************************************************************************************************/
/**
<summary>

The main routine assists in gaining access to the board.

The following routines from the nai_sys_cfg.c file are
called to assist with accessing and configuring the board.

 - ConfigDevice
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - CheckModule

</summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t AR_Interrupt_Basic_Ethernet(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   initializeARConfigurations( 0, 0, 0, 0, 0, 0, MAX_FIFO_COUNT, DEF_AR_TIMESTAMP, FALSE);
   initializeInterruptConfigurations(FALSE,FALSE,FALSE,0,0,0,0);

   initializeIDRConfigurations(0,0,DEF_RX_RESPONSE_PROTOCOL,DEF_RX_RESPONSE_PORT,
                              DEF_RX_RESPONSE_IPv4_ADDR, DEF_RX_RESPONSE_IPv4_LENGTH,
                              COMMANDS,0,ETHERNET_OVERHEAD_FIFO_COMMAND,DEF_ETHERNET_AR_IDR_ID);

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

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            inputARConfig.module = module;
            if (stop != TRUE)
            {
               inputARConfig.modid = naibrd_GetModuleID(cardIndex, module);
               if ((inputARConfig.modid != 0))
               {
                  Run_AR_Interrupt_Basic_Ethernet();
               }
            }
         }
         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;
}

/**************************************************************************************************************/
/**
<summary>

This function is broken into the following major steps. These steps correspond with the steps provided
in the naibrd SSK Quick Guide (Interrupts) file.

2a. Ethernet Interrupt Handling - Setup IDR to handle interrupt

   API CALLS - naibrd_Ether_SetIDRConfig, naibrd_Ether_StartIDR, naibrd_Ether_ClearIDRConfig

3. Enable Module Interrupts- Configures module to interrupt when channel receives AR message.

   API CALLS - naibrd_AR_SetInterruptEdgeLevel, naibrd_AR_SetIntVector, naibrd_AR_SetInterruptSteering, naibrd_AR_SetIntEnable

4. Configure Module to Cause Rx Interrupt - sets the BAUD Rate to 1mbit/s (AR AB) or 500k bits/s (AR J1939) as defined in nai_ar_cfg.h
   It also enables the particular channel on the module to receive ARINC messages

   API CALLS - naibrd_AR_SetBitTiming , naibrd_AR_SetRxEnable

5. Show Interrupt Handling - The IDR server will listen on the boards ports for IDRs indicating an interrupt.
   These results will be decoded and displayed to the user.

6. Re-arming Interrupts - Clear the status register to allow interrupts to occur again. This is done by writing to the status register.
   In this program, the write command is included in the IDR.

   API CALLS - nai_ether_BeginWriteMessage, nai_ether_WriteMessageData, nai_ether_FinishMessage

7. Clear Module Configurations

   API CALLS - naibrd_AR_SetRxEnable, naibrd_AR_ClearStatus

8. Clear Board Configurations

   API CALLS - naibrd_Ether_StopIDR, naibrd_Ether_ClearIDRConfig

</summary>
*/
/**************************************************************************************************************/
static bool_t Run_AR_Interrupt_Basic_Ethernet()
{
   bool_t bQuit = FALSE;
   bool_t bGen4ArIDRCommands;

   inputARConfig.maxChannel = naibrd_AR_GetChannelCount( inputARConfig.modid );
   inputARConfig.minChannel = 1;

   /* check if AR module supports GEN 4 Ethernet */
   bGen4ArIDRCommands = SupportsGen4Ether( inputARConfig.cardIndex );

   if ( !bGen4ArIDRCommands )
   {
      printf( "AR Ethernet Interrupt Support Prior to Generation 4 Ethernet commands currently not supported\n" );
      bQuit = TRUE;
   }

   if (!bQuit)
   {
      bQuit = naiapp_query_ChannelNumber( inputARConfig.maxChannel, inputARConfig.minChannel, &inputARConfig.channel );
   }

   /* Query user for Trigger Status of interrupts */
   if (!bQuit)
   {
      bQuit = GetARLatchStatusTriggerMode( &inputInterruptConfig.interrupt_Edge_Trigger );
   }

   if (!bQuit)
   {
      bQuit = QueryIDRConfigInformation( &inputIDRConfig );
   }

   if (!bQuit)
   {
      bQuit = QueryUserForOnboardOffboardInterrupts( &inputInterruptConfig.bProcessOnboardInterrupts );
   }

   if (!bQuit)
   {
      bQuit = QueryUserForEtherIDRMsgDisplay( &bDisplayEtherUPR );
   }

   if (!bQuit)
   {
      bQuit = QueryUserForDisplayingData( &inputInterruptConfig.displayData );
   }

   if (!bQuit)
   {
      bQuit = QueryUserForTimeStampEnable(  &inputARConfig.timeStampEnable );
   }

   if (!bQuit)
   {
      if ( inputInterruptConfig.displayData )
         fifoDataFile = stdout;
      else
         fifoDataFile = fopen( "AR_Interrupt_FIFO_Data.txt", "w+" );

      /**** 2. Setup IDR to Handle Interrupt (also contains step 6) ****/
      if ( inputInterruptConfig.bProcessOnboardInterrupts == TRUE )
      {
         inputIDRConfig.cardIndex = inputARConfig.cardIndex;
         inputIDRConfig.boardInterface =  NAI_INTF_ONBOARD;
         inputInterruptConfig.steering = NAIBRD_INT_STEERING_ON_BOARD_1;
      }
      else /* OffBoard Interrupt */
      {
         inputIDRConfig.cardIndex = 0;
         inputIDRConfig.boardInterface = NAI_INTF_PCI;
         inputInterruptConfig.steering = NAIBRD_INT_STEERING_CPCI_APP;
      }
      setupIDRConfiguration_AR( inputARConfig, &inputIDRConfig, bGen4ArIDRCommands );
      check_status( naibrd_Ether_StartIDR( inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID ) );

      /**** 3. configure module To Interrupt ****/
      configureARToInterruptOnRx( inputInterruptConfig, inputARConfig );
      enableARInterrupts( inputARConfig, AR_RX_DATA_AVAIL );

      /**** 4. Configure AR to cause Interrupts ****/
      Cfg_Rx_AR( inputARConfig );

      /**** 5. Show Interrupt Handling ****/
      AR_ClearInterrupt = ClearInterrupt_AR;
      arEtherIntFunc = HandleAREtherInterrupt;
      bQuit = runIDRServer( inputIDRConfig );

      /***** 7. Clear Module Configurations *****/
      check_status( naibrd_AR_SetRxEnable( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, FALSE ) );
      enableARInterrupts( inputARConfig, FALSE );

      /***** 8. Clear Board Configurations *****/
      check_status( naibrd_Ether_StopIDR( inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID ) );
      check_status( naibrd_Ether_ClearIDRConfig( inputIDRConfig.cardIndex, DEF_ETHERNET_AR_IDR_ID ) );
   }
   return bQuit;
}

nai_ar_int_ether.c

Full Source — nai_ar_int_ether.c (SSK 1.x)
/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.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"

/* Common AR Sample Program include files */
#include "nai_ar_int_ether.h"
#include "nai_ar_cfg.h"

/* naibrd include files */
#include "functions/naibrd_ar.h"
#include "maps/nai_map_ar.h"
#include "advanced/nai_ether_adv.h"

int32_t command_index_interrupt_status;

/* Extern Functions or Variables*/
extern IDRConfig inputIDRConfig;
extern ArConfig inputARConfig;
extern FILE* fifoDataFile;

/**************************************************************************************************************/
/**
<summary>
Constructs the ethernet commands that are part of the IDR. Configures the IDR on the board.
</summary>
*/
/**************************************************************************************************************/
void setupIDRConfiguration_AR( ArConfig inputARConfig, IDRConfig* inputIDRConfig, bool_t bGen4ArIDRCommands )
{
   int32_t cardIndex = inputIDRConfig->cardIndex;

   uint16_t protocol = inputIDRConfig->protocol;
   uint16_t port = inputIDRConfig->port;
   uint8_t* ipAddress = inputIDRConfig->ipAddress;
   uint8_t ipLength = inputIDRConfig->ipLength;

   int32_t vector = NAI_AR_INTERRUPT_VECTOR;
   uint8_t *commands   = inputIDRConfig->commands;
   uint16_t *cmdcount  =  &inputIDRConfig->cmdcount;
   uint16_t *cmdlength =  &inputIDRConfig->cmdlength;

   check_status( naibrd_Ether_ClearIDRConfig( cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID ) );
   InitARRxIDRCommands( inputARConfig, inputIDRConfig, bGen4ArIDRCommands );
   check_status( naibrd_Ether_SetIDRConfig( cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID, protocol, ipLength, ipAddress, port, vector, *cmdcount, *cmdlength, commands ) );
}

/**************************************************************************************************************/
/**
<summary>
This function configures the IDR (Interrupt Driven Response) commands when a AR Rx interrupt occurs.
There are four Ethernet commands that will be processed by the board when a AR Rx interrupt occurs.
</summary>
*/
/**************************************************************************************************************/
void InitARRxIDRCommands( ArConfig inputARConfig, IDRConfig* inputIDRConfig, bool_t bGen4ArIDRCommands )
{
   nai_status_t status = NAI_SUCCESS;

   uint16_t msgIndex = 0;
   uint32_t boardAddress;
   uint32_t moduleOffset;
   boardAddress = 0;

   status = check_status( naibrd_GetModuleOffset( inputARConfig.cardIndex, inputARConfig.module, &moduleOffset ) );
   if ( status == NAI_SUCCESS )
      status = check_status( naibrd_GetAddress( inputARConfig.cardIndex, &boardAddress ) );

   if ( status == NAI_SUCCESS )
   {
      if ( bGen4ArIDRCommands )
      {
         msgIndex = inputIDRConfig->cmdlength;
         MakeARRxReadRegsCommand( inputARConfig, inputIDRConfig, boardAddress, moduleOffset, bGen4ArIDRCommands, msgIndex );
      }
   }
}

/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet read reg command and stores it in the IDR Configuration. The read will be performed
on the modules latched status interrupt register.
</summary>
*/
/**************************************************************************************************************/
void MakeARRxReadRegsCommand( ArConfig inputARConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex )
{
   uint32_t AR_GEN5_LatchedIntStatusAddr[] = NAI_AR_GEN5_REG_CH_LATCHED_INT_STATUS_ADD;
   uint16_t msgIndex = startIndex;
   uint16_t seqno;
   uint32_t count, stride;
   uint32_t regaddr;
   if (bGen4Ether)
   {
      seqno = 0;
      regaddr = boardAddress + moduleOffset + AR_GEN5_LatchedIntStatusAddr[inputARConfig.channel-1];
      count = 1;
      stride = 4;

      msgIndex = (uint16_t)nai_ether_MakeReadMessage( &inputIDRConfig->commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface, regaddr, stride, count, NAI_REG32 );

      inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
      command_index_interrupt_status = inputIDRConfig->cmdcount;
      inputIDRConfig->cmdcount++;
   }
}

/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet write reg command and stores it in the IDR Configuration. The write will be performed
on the modules latched status interrupt register. The purpose of this write is to clear the interrupt status register and re-arm the interrupts
after one has occurred.
</summary>
*/
/**************************************************************************************************************/
void MakeARRxWriteRegsCommand( ArConfig inputARConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex )
{
   uint32_t AR_GEN5_LatchedIntStatusAddr[] = NAI_AR_GEN5_REG_CH_LATCHED_INT_STATUS_ADD;
   uint16_t msgIndex = startIndex;
   uint16_t seqno;
   uint32_t count, stride;
   uint32_t regaddr;
   uint32_t data = 0xFFFF;   /* Clear Rx interrupt bits */

   if (bGen4Ether)
   {
      seqno = 0;
      regaddr = moduleOffset + boardAddress + AR_GEN5_LatchedIntStatusAddr[inputARConfig.channel-1];
      count = 1;
      stride = 4;

      msgIndex = (uint16_t)nai_ether_BeginWriteMessage( &inputIDRConfig->commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface, regaddr, stride, count, NAI_REG32 );
      if ( msgIndex >= 0 )
      {
         msgIndex = (uint16_t)nai_ether_WriteMessageData( &inputIDRConfig->commands[startIndex], msgIndex, NAI_REG32, &data, NAI_REG32, count );

         if ( msgIndex >= 0 )
         {
            msgIndex = (uint16_t)nai_ether_FinishMessage( &inputIDRConfig->commands[startIndex], msgIndex, NAI_ETHER_GEN4 );
         }
      }
      inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
      inputIDRConfig->cmdcount++;
   }
}

/**************************************************************************************************************/
/**
<summary>
Handles interpreting the idr response msgs received for ar data.
displays the IDR ID and status. Also displays the fifo data from the interrupting channel.
Expects to be parsing a message for a SINGLE channel interrupt only.
</summary>
*/
/**************************************************************************************************************/
void HandleAREtherInterrupt( uint16_t msglen, uint8_t msg[], uint16_t tdr_idr_id )
{
   static uint32_t status;
   static FIFO fifoToPrint;

   int32_t index;
   uint16_t seq;
   nai_ether_typecode_t typeCode;
   nai_ether_gen_t gen = NAI_ETHER_GEN4;
   int32_t size;
   int32_t commandIndex;
   int32_t outnummsgs;
   int32_t outcount;
   uint32_t mask = 0x1;
   uint32_t statusMasked;
   uint32_t stat[NAI_AR_MAX_DATA_LEN];
   uint32_t data[NAI_AR_MAX_DATA_LEN];
   uint32_t tstamp[NAI_AR_MAX_DATA_LEN];

   nai_ether_DecodeMessageHeader(msg, msglen, &seq, &typeCode, gen, &size);

   commandIndex = ( seq & ( 0x0F << 6 ) ) >> 6;
   naibrd_Wait( 1000000 );
   switch (typeCode)
   {
      /* Write REG */
      case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_WRITE_4:
         break;
      /* READ REG */
      case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4:

         if ( inputIDRConfig.cmdcount-1 == commandIndex )
         {
            status = msg[11];
            status = ( status | ( msg[10] << 8 ) );

            statusMasked = status & mask;

            if ( statusMasked == mask )
            {
               check_status( naibrd_AR_GetRxBufferCnt( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, &outcount ) );
               fifoToPrint.maxDataLength = NAI_AR_MAX_DATA_LEN;
               if ( outcount > 0 )
               {
                  check_status( naibrd_AR_ReadFifo( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, inputARConfig.timeStampEnable, outcount, stat, data, tstamp, &outnummsgs ) );
                  for ( index = 0; index < outcount; index++ )
                  {
                     fifoToPrint.data[index].fifoData = data[index];
                     fifoToPrint.data[index].fifoStatus = (uint16_t)stat[index];
                     fifoToPrint.data[index].fifoTimeStamp = tstamp[index];
                  }
                  fifoToPrint.length = outcount;
               }
            }
         }
         else if ( inputIDRConfig.cmdcount == commandIndex )
            status = msg[11];
         break;
   }
   if ( commandIndex == inputIDRConfig.cmdcount - 1 )
   {
      printf( "\nInterrupt Occurred\n" );
      printEthernetInterruptInformation( tdr_idr_id, status, fifoDataFile, fifoToPrint.length, fifoToPrint );
   }
   /* Clear Interrupt Latch */
   check_status( naibrd_AR_ClearStatus( inputARConfig.cardIndex, inputARConfig.module, inputARConfig.channel, 0xFFFF ) );
}

/**************************************************************************************************************/
/**
<summary>
Function will print the fifoData provided for each channel that has been set in the status register.
It will also print the status and idr id or vector.  This function is used for Ethernet Interrupts only.
</summary>
*/
/**************************************************************************************************************/
void printEthernetInterruptInformation( int32_t interruptID, uint32_t status, FILE* stream, int32_t count, FIFO fifo )
{
   uint8_t statusBitSet;
   uint16_t fifoElementStatus;
   uint32_t fifoElementData;
   uint32_t fifoElementTimeStamp;
   uint32_t fifoLength;
   int32_t maxFifoLength;
   int32_t i;

   fprintf( stream, "Interrupt Information\n" );
   fprintf( stream, "-----------------------------------\n" );
   fprintf( stream, "\nIDR ID = %#x \n", interruptID );
   fprintf( stream, "Status = %#x \n", status );

   statusBitSet = status & AR_RX_DATA_AVAIL;
   if ( statusBitSet )
   {
      if ( count > 0 )
      {
         fifoLength = fifo.length;
         maxFifoLength = fifo.maxDataLength;
         fprintf( stream, "\nMax FIFO Word Count: %d\n", maxFifoLength );
         fprintf( stream, "Messages Received (FIFO Word Count): %d\n", fifoLength );
         for ( i = 0; i < count; i++ )
         {
            fprintf( stream, "Message Number %d:", i + 1 );
            fifoElementStatus = fifo.data[i].fifoStatus;
            fifoElementData = fifo.data[i].fifoData;
            fifoElementTimeStamp = fifo.data[i].fifoTimeStamp;
            fprintf( stream, "\n" );
            fprintf( stream, "Message Status: %#x", fifoElementStatus );
            fprintf( stream, "\n" );
            fprintf( stream, "Message Data: %#x", fifoElementData );
            fprintf( stream, "\n" );
            fprintf( stream, "Time Stamp: %#x", fifoElementTimeStamp );
            fprintf( stream, "\n\n" );
         }
      }
      else if ( count < 0 )
      {
         fprintf( stream, "ERROR! naibrd_AR_GetRxBufferCnt returned an invalid value." );
      }
   }
   fprintf( stream, "\n-----------------------------------\n" );
}

Help Bot

X