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

AR429 Interrupt

AR429 Interrupt Sample Application (SSK 2.x)

Overview

The AR429 Interrupt sample application demonstrates how to configure and handle hardware interrupts on ARINC 429 transmit modules using the NAI Software Support Kit (SSK 2.x). It covers configuring an ARINC 429 channel for triggered FIFO transmission, setting up an interrupt on the Tx FIFO Full status, connecting an ISR callback, configuring interrupt steering and vector, loading data into the transmit FIFO, and handling the interrupt when the FIFO reaches its threshold. The sample provides an interactive loop where the user loads words into the Tx FIFO until the full threshold is reached and the interrupt fires.

This sample supports the following ARINC 429 module types: AR1 and AR2. The Tx FIFO threshold is set to 32 messages, and the interrupt fires when the FIFO contains at least 32 entries. The sample uses triggered transmission mode (NAIBRD_AR_TX_SENDMODE_TRGF) so that data accumulates in the FIFO rather than being sent immediately, allowing the threshold to be reached.

For the SSK 1.x version, see AR Interrupt Basic (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 an ARINC 429 module installed (AR1, AR2).

  • 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 ar429_interrupt executable from your build output directory. On startup the application looks for a configuration file (default_ARXmit.txt). On the first run, this file will not exist — the application will present an interactive board menu. After connecting, select a card, module, channel, and data rate. The application configures the ARINC 429 channel for triggered FIFO transmission with interrupt-on-full, then enters an interactive loop where you load data words into the Tx FIFO. When the FIFO reaches the 32-word threshold, the interrupt fires and the status is displayed.

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 ARINC 429.

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.

  2. Enter a loop that calls AR_Interrupt_run() for each iteration.

#ifdef NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS
int32_t ar429_interrupt(void)
#else
int32_t main(void)
#endif
{
   bool_t bQuit = NAI_FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == (bool_t)NAI_TRUE)
   {
      while (!bQuit)
      {
         bQuit = AR_Interrupt_run();
      }
   }

   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.

  • Connection timeout — confirm network settings or bus configuration.

  • Invalid card or module index — indices are zero-based for cards and one-based for modules.

  • Module not present at selected slot — the slot you selected does not contain an ARINC 429 module.

Program Structure

Entry Point

On standard platforms (Petalinux) the entry point is main(). On VxWorks the entry point is ar429_interrupt(). The main function handles board connection, then enters a loop calling AR_Interrupt_run() which performs channel selection, configuration, interrupt setup, and the interactive FIFO loading loop.

Configuration Flow

AR_Interrupt_run() queries for card, module, and channel via GetARCfg(), then queries for the data rate via GetARINCDataRate(). After configuration, it calls AR_TxFIFO() to enter the interactive data loading loop.

Channel Configuration

The ARINC 429 channel is configured with the following parameters:

/* Reset the channel */
check_status(naibrd_AR_ChannelReset(cardIndex, module, archan));

/* Set the transmission speed */
check_status(naibrd_AR_SetBaudRate(cardIndex, module, archan, datarate));

/* Set the Tx FIFO Threshold to 32 */
check_status(naibrd_AR_SetTxFifoThreshold(cardIndex, module, archan, 32));

/* Set parity to odd parity checking */
check_status(naibrd_AR_SetParityBitUsage(cardIndex, module, archan,
   NAIBRD_AR_PAR_ODD));

/* Set inter-message gap time */
check_status(naibrd_AR_SetTxGapTime(cardIndex, module, archan, 6));
  • Tx FIFO Threshold — set to 32. When the number of messages in the Tx FIFO reaches 32, the Tx FIFO Full status is set and the interrupt fires.

  • Transmission mode — set to NAIBRD_AR_TX_SENDMODE_TRGF (triggered mode) in AR_TxFIFO(), so data accumulates in the FIFO until explicitly triggered.

Interrupt Configuration

The interrupt is configured using the "EventMapped" interrupt pattern for ARINC 429 modules:

/* Set Interrupt Trigger Type to edge */
check_status(naibrd_AR_SetEventMappedInterruptTriggerType(cardIndex, module,
   archan, NAIBRD_AR_EVENT_STATUS_GENERAL_TX_FIFO_FULL_LATCHED,
   NAIBRD_INT_TRIGGER_TYPE_EDGE));

/* Set Interrupt Vector */
check_status(naibrd_AR_SetEventMappedInterruptVector(cardIndex, module,
   archan, NAIBRD_AR_EVENT_MAP_GENERAL, INTERRUPT_VECTOR));

/* Set Interrupt Steering to PCIe */
check_status(naibrd_AR_SetEventMappedInterruptSteering(cardIndex, module,
   archan, NAIBRD_AR_EVENT_MAP_GENERAL, NAIBRD_INT_STEERING_PCIE));

/* Install the ISR */
check_status(naibrd_ConnectISR(cardIndex, myIsr));
  • naibrd_AR_SetEventMappedInterruptTriggerType() — configures edge triggering on the Tx FIFO Full latched status.

  • naibrd_AR_SetEventMappedInterruptVector() — assigns vector 0xF5 to the general event map for this channel.

  • naibrd_AR_SetEventMappedInterruptSteering() — routes the interrupt to the PCIe bus. Change to NAIBRD_INT_STEERING_ONBOARD_ARM for ARM-based processing.

  • naibrd_ConnectISR() — registers the ISR callback once per card.

FIFO Loading and Interrupt Handling

Enabling the Interrupt

After channel configuration, the interrupt is enabled and all latched statuses are cleared:

/* Enable Interrupt for Tx FIFO Full events */
check_status(naibrd_AR_SetEventMappedInterruptEnable(cardIndex, module, channel,
   NAIBRD_AR_EVENT_STATUS_GENERAL_TX_FIFO_FULL_LATCHED, NAI_TRUE));

/* Clear All Latched Status Bits */
check_status(naibrd_AR_ClearEventMappedStatusRaw(cardIndex, module, channel,
   NAIBRD_AR_EVENT_MAP_GENERAL, 0xFFFFFFFF));

Interactive Data Loading

The AR_TxFIFO() function enters a loop where the user specifies how many words to load. Data is loaded with naibrd_AR_LoadTxFifo(). After each load, the code checks irqFlag to see if the threshold interrupt fired:

if (irqFlag)
{
   irqFlag = 0;

   naiif_printf("\r\nReceived Vector: 0x%08X", receivedVector);

   switch (receivedVector)
   {
      case INTERRUPT_VECTOR:
         /* Read channel status */
         check_status(naibrd_AR_GetEventMappedStatusRaw(cardIndex, module,
            channel, NAI_STATUS_LATCHED, NAIBRD_AR_EVENT_MAP_GENERAL,
            &outStatusWord));

         /* Optionally clear the Tx FIFO */
         /* Clear Latched Status Bits */
         check_status(naibrd_AR_ClearEventMappedStatusRaw(cardIndex, module,
            channel, NAIBRD_AR_EVENT_MAP_GENERAL, outStatusWord));
         break;
      default:
         naiif_printf("\r\nReceived Vector is not mine.\r\n");
   }
}

ISR Callback

The ISR is minimal — it stores the received vector, sets a global flag, and increments a counter:

static void myIsr(uint32_t vector)
{
   receivedVector = vector;
   irqFlag = 1;
   irqCount++;
}

Troubleshooting Reference

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

Error / Symptom Possible Causes Suggested Resolution

No board found or connection timeout

Board not powered, incorrect configuration file, network issue

Verify hardware is powered and connected. Check that default_ARXmit.txt has correct settings.

Module not recognized as ARINC 429

Selected slot contains a non-AR module

Verify the slot contains an AR1 or AR2 module

naibrd_ConnectISR returns NAI_ERROR_NOT_SUPPORTED

Platform does not support hardware interrupts

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

Interrupt never fires

FIFO threshold not reached, wrong steering, or interrupt not enabled

Load at least 32 words into the Tx FIFO. Verify steering matches your platform (PCIe vs. ARM).

NAI_ERROR_FULL from naibrd_AR_LoadTxFifo()

Tx FIFO is full

Clear the Tx FIFO with naibrd_AR_ClearTxFifo() before loading more data

Interrupt fires but vector does not match

Multiple interrupt sources active

Verify the vector assigned with naibrd_AR_SetEventMappedInterruptVector() matches INTERRUPT_VECTOR

Data not transmitted after loading

Triggered mode requires explicit trigger signal

The sample uses triggered mode to accumulate data. Send a trigger or switch to immediate mode if you want data sent immediately.

Full Source

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

Full Source — ar429_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"

/* 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"

/* AD Sample App include files */
#include "nai_sample_apps/naiapp_src/board_modules/ar429/ar429_common_utils/ar429_common_utils.h"

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

/* Function prototypes */
static bool_t AR_Interrupt_run();
static void myIsr(uint32_t vector);
static bool_t AR_TxFIFO( int32_t cardIndex, int32_t module, int32_t channel, naibrd_ar_tx_mode_t txmode );

/* Default channel selection */
#define DEF_AR_CARD_INDEX                 0
#define DEF_AR_MODULE                     1
#define DEF_AR_XMIT_CHANNEL               1

/* Default channel configuration settings */
#define DEF_AR_DATA_RATE                  NAIBRD_AR_SPEED_LOW
#define DEF_AR_TX_MODE                    NAIBRD_AR_TX_SENDMODE_IMMED
#define DEF_AR_XMIT_DATA_COUNT            1

/* Interrupt Configuration */
#define INTERRUPT_VECTOR                  0xF5

/* Global Variables */
static volatile int32_t irqFlag;
static int32_t irqCount;
static uint32_t receivedVector;

/**************************************************************************************************************/
/**
 * <summary>
 * The purpose of the ar429_interrupt is to illustrate the methods to call in the naibrd library to configure
 * the ARINC channel to run in Tx mode and generate an interrupt when the Tx FIFO is full.
 * </summary>
 */
/**************************************************************************************************************/
#ifdef NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS
int32_t ar429_interrupt(void)
#else
int32_t main(void)
#endif
{
   bool_t bQuit = NAI_FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == (bool_t)NAI_TRUE)
   {
      while (!bQuit)
      {
         bQuit = AR_Interrupt_run();
      }

      naiif_printf("Type the Enter key to exit the program: ");
      naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   }

   naiapp_access_CloseAllOpenCards();

   return 0;
}

/**************************************************************************************************************/
/**
<summary>
AR_Interrupt_run queries the user for the card, module and channel to configure as the ARINC transmitter
as well as the data rate (high (100KHz) or low (12.5KHz)). Methods in the naibrd library are invoked to configure
the ARINC channel. The user-specified ARINC channel is configured with the Tx FIFO Threshold set to 32 messages,
which means that the Tx FIFO Full status bit will be set and, if enabled, an interrupt will be generated when the
Tx FIFO reaches 32 messages at any point in time. In order to be able to accumulate messages in the Tx FIFO, the
Tx FIFO send mode is set to Triggered Mode, which requires the user to send a Trigger signal in order for the
contents of the Tx FIFO to get sent out. This code demonstrates how to program the ARINC module to generate an
interrupt when the Tx FIFO Full event occurs.
</summary>
*/
/**************************************************************************************************************/
static bool_t AR_Interrupt_run()
{
   int32_t archan;
   naibrd_ar_datarate_t datarate;
   bool_t bQuit = NAI_FALSE;
   int32_t cardIndex, module;

   bQuit = GetARCfg( DEF_AR_CARD_INDEX, DEF_AR_MODULE, DEF_AR_XMIT_CHANNEL, &cardIndex, &module, &archan );
   if (!bQuit)
   {
      /* Get Data Rate */
      bQuit = GetARINCDataRate( DEF_AR_DATA_RATE, &datarate );
      if (!bQuit)
      {
         /* Reset the channel */
         check_status( naibrd_AR_ChannelReset( cardIndex, module, archan ) );

         /* Set the transmission speed */
         check_status( naibrd_AR_SetBaudRate( cardIndex, module, archan, datarate ) );

         /* Set the Tx Fifo Threshold to 32 (max is 255). If the number of messages in the Tx FIFO falls under 32, the Tx FIFO Almost Empty Status will be set */
         check_status( naibrd_AR_SetTxFifoThreshold( cardIndex, module, archan, 32 ) );

         /* Set the Parity Bit Usage to treat ARINC bit 32 as an odd parity bit and perform parity checking */
         check_status( naibrd_AR_SetParityBitUsage( cardIndex, module, archan, NAIBRD_AR_PAR_ODD ) );

         /* Set the inter-message transmission gap time (interval rate) */
         check_status( naibrd_AR_SetTxGapTime( cardIndex, module, archan, 6 ) );     /* 6 bit-times */

         /* Set Interrupt Trigger Type (NAIBRD_INT_TRIGGER_TYPE_EDGE or NAIBRD_INT_TRIGGER_TYPE_LEVEL) */
         check_status( naibrd_AR_SetEventMappedInterruptTriggerType( cardIndex, module, archan, NAIBRD_AR_EVENT_STATUS_GENERAL_TX_FIFO_FULL_LATCHED, NAIBRD_INT_TRIGGER_TYPE_EDGE ) );

         /* Set Interrupt Vector for this channel */
         check_status( naibrd_AR_SetEventMappedInterruptVector( cardIndex, module, archan, NAIBRD_AR_EVENT_MAP_GENERAL, INTERRUPT_VECTOR ) );

         /* Select Interrupt Steering from the following enums */
         /* Direct interrupt to VME Bus                                    = NAIBRD_INT_STEERING_VME         */
         /* Interrupt to the Custom App on ARM / NAI Ethernet Listener App = NAIBRD_INT_STEERING_ONBOARD_ARM */
         /* Interrupt to PCIe Bus                                          = NAIBRD_INT_STEERING_PCIE        */
         /* Interrupt to CPCI Bus                                          = NAIBRD_INT_STEERING_CPCI        */
         check_status( naibrd_AR_SetEventMappedInterruptSteering( cardIndex, module, archan, NAIBRD_AR_EVENT_MAP_GENERAL, NAIBRD_INT_STEERING_PCIE ) );

         /* Install the ISR */
         check_status( naibrd_ConnectISR( cardIndex, myIsr ) );

         /* Set transmit mode and start transmission */
         bQuit = AR_TxFIFO( cardIndex, module, archan, NAIBRD_AR_TX_SENDMODE_TRGF );
      }
   }
   return bQuit;
}

static void myIsr(uint32_t vector)
{
   receivedVector = vector;

   /* Set the global interrupt flag */
   irqFlag = 1;
   irqCount++;
}

static bool_t AR_TxFIFO( int32_t cardIndex, int32_t module, int32_t channel, naibrd_ar_tx_mode_t txmode )
{
   bool_t bQuit = NAI_FALSE;
   int32_t nNumWordsToLoad = 1;
   int32_t nNumWordsLoaded;
   int32_t i;
   int32_t increment = 0x33333333;
   uint32_t SendData[255];
   nai_status_t status;
   bool_t outenable;
   uint32_t outStatusWord;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   /* Set FIFO Transmission mode */
   check_status( naibrd_AR_SetTransmitSendMode( cardIndex, module, channel, txmode ) );

   /* Enable transmitter */
   check_status( naibrd_AR_SetTxEnable( cardIndex, module, channel, NAI_TRUE ) );

   /* Enable Interrupt for Tx FIFO Full events */
   check_status( naibrd_AR_SetEventMappedInterruptEnable( cardIndex, module, channel, NAIBRD_AR_EVENT_STATUS_GENERAL_TX_FIFO_FULL_LATCHED, NAI_TRUE ) );

   /* Clear All Latched Status Bits */
   check_status( naibrd_AR_ClearEventMappedStatusRaw( cardIndex, module, channel, NAIBRD_AR_EVENT_MAP_GENERAL, 0xFFFFFFFF ) );

   while (!bQuit)
   {
      /* Query for the number of data words to load into Tx Buffer */
      bQuit = GetARTransmitDataCount( DEF_AR_XMIT_DATA_COUNT, &nNumWordsToLoad );
      if (!bQuit)
      {
         if (nNumWordsToLoad > 255)
         {
            nNumWordsToLoad = 255;
         }

         naiif_printf( "\r\nLoading %d words ...\r\n", nNumWordsToLoad );
         for (i = 0; i < nNumWordsToLoad; i++)
         {
            SendData[i] = (uint32_t)increment++;
            naiif_printf( "0x%08X\r\n", SendData[i] );
         }
         status = naibrd_AR_LoadTxFifo( cardIndex, module, channel, nNumWordsToLoad, SendData, &nNumWordsLoaded );
         if (status == NAI_SUCCESS)
         {
            naiif_printf( "Load success - %d words loaded.\r\n", nNumWordsLoaded );
            check_status( naibrd_AR_GetTxFifoCnt( cardIndex, module, channel, &nNumWordsLoaded ) );
            naiif_printf( "Tx FIFO count: %d\r\n", nNumWordsLoaded );

            if (irqFlag)
            {
               irqFlag = 0;

               /* Display the Interrupt Vector */
               naiif_printf("\r\nReceived Vector: 0x%08X", receivedVector);

               switch (receivedVector)
               {
                  case INTERRUPT_VECTOR:  /* mine */
                     /* Read off channel status */
                     check_status( naibrd_AR_GetEventMappedStatusRaw( cardIndex, module, channel, NAI_STATUS_LATCHED, NAIBRD_AR_EVENT_MAP_GENERAL, &outStatusWord ) );
                     naiif_printf("\r\nStatus Word: 0x%08X\r\n");

                     /* Query user to clear Tx FIFO */
                     bQuit = naiapp_query_ForBinaryResponse( sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt, (int8_t *)"Clear Tx FIFO? ", (int8_t *)"Invalid response. Please enter y or n. ", NAI_TRUE, &outenable);
                     if (bQuit == NAI_TRUE)
                     {
                        break;
                     }
                     else
                     {
                        if (outenable == NAI_TRUE)
                        {
                           /* Clear Tx Buffer */
                           check_status( naibrd_AR_ClearTxFifo( cardIndex, module, channel ) );
                        }
                     }

                     /* Clear Latched Status Bits */
                     check_status( naibrd_AR_ClearEventMappedStatusRaw( cardIndex, module, channel, NAIBRD_AR_EVENT_MAP_GENERAL, outStatusWord ) );
                     break;
                  default:    /* not mine */
                     naiif_printf("\r\nReceived Vector is not mine.\r\n");
               }
            }
         }
         else if (status == NAI_ERROR_FULL)
         {
            naiif_printf( "Load fail - Not enough space in Tx Buffer. Space available: %d words.\r\n", nNumWordsLoaded );
         }
         else
         {
            naiif_printf( "Load fail - Error status: %d.\r\n", status );
         }
      }
   }

   /* Disable transmitter */
   check_status( naibrd_AR_SetTxEnable( cardIndex, module, channel, NAI_FALSE ) );

   return bQuit;
}

Help Bot

X