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

nai ar int ether

nai ar int ether

Explanation

About the Sample Application Code

This sample application code from North Atlantic Industries demonstrates how to interact with their embedded function modules, specifically focusing on configuring and handling Ethernet-based Interrupt Driven Responses (IDR) for AR (Asynchronous Received) data. Here’s a detailed breakdown of what each part of the code does and some important definitions and enumerations to understand:

1. Include Files The code starts by including various header files which are essential for the functionality:

#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"

#include "nai_ar_int_ether.h"
#include "nai_ar_cfg.h"

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

These headers bring in necessary definitions, declarations, and utilities for handling interrupts, Ethernet communications, board access, and specific functions related to AR handling.

2. Function Definitions

a. setupIDRConfiguration_AR This function configures the IDR (Interrupt Driven Response) settings for Ethernet-based operations.

void setupIDRConfiguration_AR(ArConfig inputARConfig, IDRConfig* inputIDRConfig, bool_t bGen4ArIDRCommands)
  • ArConfig inputARConfig: Configuration data for the AR.

  • IDRConfig* inputIDRConfig: Configuration data for the IDR.

  • bool_t bGen4ArIDRCommands: A flag indicating whether to use Gen4 AR IDR commands.

The function first clears any existing IDR configuration using naibrd_Ether_ClearIDRConfig, then initializes the AR Rx IDR commands using InitARRxIDRCommands. Lastly, it sets the IDR configuration using naibrd_Ether_SetIDRConfig.

b. InitARRxIDRCommands This function initializes the Ethernet commands for AR Rx interrupts.

void InitARRxIDRCommands(ArConfig inputARConfig, IDRConfig* inputIDRConfig, bool_t bGen4ArIDRCommands)
  • It retrieves the module offset and board address.

  • Depending on the flag bGen4ArIDRCommands, it constructs AR Rx read register commands using MakeARRxReadRegsCommand.

c. MakeARRxReadRegsCommand Constructs Ethernet read register commands and stores them in the IDR configuration.

void MakeARRxReadRegsCommand(ArConfig inputARConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex)
  • It constructs messages for reading from interrupt status registers and stores these messages in the IDR configuration.

  • Uses the function nai_ether_MakeReadMessage to generate the read message.

d. MakeARRxWriteRegsCommand This function constructs Ethernet write register commands to clear the interrupt status register.

void MakeARRxWriteRegsCommand(ArConfig inputARConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex)
  • Constructs the messages needed to write to the interrupt status register, effectively clearing it.

  • Uses nai_ether_BeginWriteMessage, nai_ether_WriteMessageData, and nai_ether_FinishMessage for detailed construction steps.

e. HandleAREtherInterrupt Handles the interpretation of IDR response messages received for AR data.

void HandleAREtherInterrupt(uint16_t msglen, uint8_t msg[], uint16_t tdr_idr_id)
  • Parses the message, processes it, and checks the status.

  • Retrieves the count of data in the FIFO buffer.

  • Reads data from the FIFO buffer if available and prints it using printEthernetInterruptInformation.

f. printEthernetInterruptInformation Prints out the details of the interrupt including status and FIFO data.

void printEthernetInterruptInformation(int32_t interruptID, uint32_t status, FILE* stream, int32_t count, FIFO fifo)
  • Prints the interrupt ID and status.

  • If data is available in FIFO, prints the details of each data item including status, data, and timestamp.

Important Definitions and Enumerations

  • ArConfig: Structure containing configuration settings for the AR.

  • IDRConfig: Structure containing configuration settings for the IDR.

  • bool_t: Boolean type typically defined as typedef int bool_t; with values TRUE (1) and FALSE (0).

  • FIFO: Structure representing a FIFO buffer for holding data, status, and timestamps.

  • NAI_SUCCESS: Status code indicating success.

  • NAI_AR_INTERRUPT_VECTOR: Constant representing the interrupt vector for AR.

  • NAI_ETHER_GEN4: Constant for generation 4 Ethernet.

  • NAI_AR_MAX_DATA_LEN: Maximum data length for AR.

By carefully analyzing and understanding the sample code, users can modify and use it as a template to handle Ethernet-based AR interrupts and IDR setups in their specific applications involving North Atlantic Industries modules.

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

/**************************************************************************************************************/
/**
<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;          /* Stores the ethernet commands that are going to be executed as part of the IDR */
   uint16_t *cmdcount  =  &inputIDRConfig->cmdcount;
   uint16_t *cmdlength =  &inputIDRConfig->cmdlength;

   check_status( naibrd_Ether_ClearIDRConfig( cardIndex, (uint16_t)DEF_ETHERNET_AR_IDR_ID ) );    /* clear IDR config */
   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