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 dsw int ether

nai dsw int ether

Explanation

About the Sample Application Code from North Atlantic Industries (NAI)

This document provides an overview of a sample C application code provided by North Atlantic Industries (NAI) for interacting with their embedded function modules using an Ethernet-based interface. The code is organized to configure and handle interrupt-driven responses (IDR) for a Data Sampling and Waveform (DSW) module. Below is a detailed walkthrough of the provided code.

Included Header 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"

#include "nai_dsw_int_ether.h"
#include "nai_dsw_cfg.h"

#include "functions/naibrd_dsw.h"
#include "maps/nai_map_dsw.h"
#include "advanced/nai_ether_adv.h"

These header files provide necessary definitions, function prototypes, and utilities for handling interrupts, accessing the board, manipulating configuration settings, and working with Ethernet communication.

Functions

1. setupIDRConfiguration_DSW

This function configures the IDR for handling DSW interrupts over Ethernet.

Parameters:

  • DswConfig inputDSWConfig: Configuration settings for the DSW.

  • IDRConfig* inputIDRConfig: Pointer to the IDR configuration structure.

  • bool_t bGen4DSWIDRCommands: Boolean flag for generation-specific commands.

Procedure:

  1. Extract Configuration Values: c 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;

  2. Initialize Interrupt Vectors: c int32_t vector1 = NAI_DSW_LOHI_INTERRUPT_VECTOR; int32_t vector2 = NAI_DSW_HILO_INTERRUPT_VECTOR;

  3. Clear Existing Configurations: c check_status(naibrd_Ether_ClearIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_DSW_LOHI_IDR_ID));

  4. Initialize and Set New IDR Commands: c InitDSWIDRCommands(inputDSWConfig, inputIDRConfig, bGen4DSWIDRCommands, addr); check_status(naibrd_Ether_SetIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_DSW_LOHI_IDR_ID, protocol, ipLength, ipAddress, port, vector1, *cmdcount, *cmdlength, commands));

  5. Repeat for an Additional Interrupt Vector: c check_status(naibrd_Ether_ClearIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_DSW_HILO_IDR_ID)); check_status(naibrd_Ether_SetIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_DSW_HILO_IDR_ID, protocol, ipLength, ipAddress, port, vector2, *cmdcount, *cmdlength, commands));

2. InitDSWIDRCommands

This function initializes IDR commands for DSW interrupts.

Procedure:

  1. Get Module Offset and Address: c status = check_status(naibrd_GetModuleOffset(inputDSWConfig.cardIndex, inputDSWConfig.module, &moduleOffset)); status = check_status(naibrd_GetAddress(inputDSWConfig.cardIndex, &boardAddress));

  2. Generate Commands: c if (bGen4DSWIDRCommands) { msgIndex = inputIDRConfig→cmdlength; MakeDSWReadRegsCommand(inputIDRConfig, boardAddress, moduleOffset, bGen4DSWIDRCommands, msgIndex, addr); }

3. MakeDSWReadRegsCommand

Constructs Ethernet read register commands stored in the IDR configuration.

Parameters:

  • IDRConfig*: Pointer to the IDR configuration.

  • uint32_t boardAddress: Address of the board.

  • int32_t moduleOffset: Offset of the module.

  • bool_t bGen4Ether: Boolean flag for generation-specific commands.

  • uint16_t startIndex: Start index for the commands.

  • uint32_t addr: Address for the register to be read.

Procedure:

  1. Adjust Command Array for Reading Registers: c msgIndex = (uint16_t)nai_ether_MakeReadMessage(&inputIDRConfig→commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig→boardInterface, addr, stride, count, NAI_REG32);

  2. Update Command Length: c inputIDRConfig→cmdlength = msgIndex; inputIDRConfig->cmdcount+;

4. HandleDSWEtherInterrupt

Handles an Ethernet message indicating a DSW Rx interrupt.

Parameters:

  • uint16_t msglen: Length of the message.

  • uint8_t msg[]: Message array.

  • uint16_t tdr_idr_id: IDR identifier.

Procedure:

  1. Decode and Parse the Message: c offset = nai_ether_DecodeMessageHeader(msg, msglen, &seq, &tc, gen, &size);

  2. Process Message Based on Typecode: c case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4: datacnt = (msglen - 10) / NAI_REG32; for (i = 0; i < datacnt; i) { data = msg[offset] << 24 | msg[offset] << 16 | msg[offset] << 8 | msg[offset++]; dswstatus_int[i] = data; } break;

  3. Output and Clear Interrupt Status: c check_status(naibrd_DSW_ClearGroupStatusRaw(inputDSWConfig.cardIndex, inputDSWConfig.module, 1, dsw_status_type, dswstatus_int[i])); printf("Cleared DSW %s Interrupt: 0x%08X\n", status_text, dswstatus_int[i]);

5. MakeDSWWriteRegsCommand

Constructs an Ethernet write command for clearing interrupt status.

Parameters:

  • DswConfig inputDSWConfig: Configuration settings for the DSW.

  • IDRConfig* inputIDRConfig: Pointer to the IDR configuration.

  • uint32_t boardAddress: Address of the board.

  • int32_t moduleOffset: Offset of the module.

  • bool_t bGen4Ether: Boolean flag for generation-specific commands.

  • uint16_t startIndex: Start index for the commands.

Procedure:

  1. Prepare Write Message: c msgIndex = (uint16_t)nai_ether_BeginWriteMessage(&inputIDRConfig→commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig→boardInterface, regaddr, stride, count, NAI_REG32);

  2. Add Data and Finish Message: c 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);

    With these functions in place, the sample application effectively manages the configuration and handling of DSW interrupts over an Ethernet interface for North Atlantic Industries embedded function 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 DSW Sample Program include files */
#include "nai_dsw_int_ether.h"
#include "nai_dsw_cfg.h"

/* naibrd include files */
#include "functions/naibrd_dsw.h"
#include "maps/nai_map_dsw.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_DSW(DswConfig inputDSWConfig, IDRConfig* inputIDRConfig, bool_t bGen4DSWIDRCommands) {

   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 vector1 = NAI_DSW_LOHI_INTERRUPT_VECTOR;
   int32_t vector2 = NAI_DSW_HILO_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;

   uint32_t addr = NAI_DSW_GEN5_REG_LO_HI_TRANS_LATCHED_STATUS_ADD;

   check_status(naibrd_Ether_ClearIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_DSW_LOHI_IDR_ID));/* clear IDR config */
   InitDSWIDRCommands(inputDSWConfig, inputIDRConfig, bGen4DSWIDRCommands, addr);
   check_status(naibrd_Ether_SetIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_DSW_LOHI_IDR_ID, protocol, ipLength, ipAddress, port, vector1, *cmdcount, *cmdlength, commands));
   check_status(naibrd_Ether_ClearIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_DSW_HILO_IDR_ID));/* clear IDR config */
   check_status(naibrd_Ether_SetIDRConfig(cardIndex, (uint16_t)DEF_ETHERNET_DSW_HILO_IDR_ID, protocol, ipLength, ipAddress, port, vector2, *cmdcount, *cmdlength, commands));

}
/**************************************************************************************************************/
/**
<summary>
This function configures the IDR (Interrupt Driven Response) commands when a DSW Rx interrupt occurs.
There are four Ethernet commands that will be processed by the board when a DSW Rx interrupt occurs.

</summary>
*/
/**************************************************************************************************************/
void InitDSWIDRCommands(DswConfig inputDSWConfig, IDRConfig* inputIDRConfig, bool_t bGen4DSWIDRCommands, uint32_t addr)
{
   nai_status_t status = NAI_SUCCESS;

   uint16_t msgIndex = 0;
   uint32_t boardAddress;
   uint32_t moduleOffset;

   boardAddress = 0;

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

   if (status == NAI_SUCCESS)
   {
      if (bGen4DSWIDRCommands)
      {
         msgIndex = inputIDRConfig->cmdlength;
         MakeDSWReadRegsCommand(inputIDRConfig, boardAddress, moduleOffset, bGen4DSWIDRCommands, msgIndex, addr);
      }
   }
}
/**************************************************************************************************************/
/**
<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. This function will read two registers based on the stride being set to
16 and addr being set to the first register that needs to be read
</summary>
*/
/**************************************************************************************************************/
void MakeDSWReadRegsCommand(IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex, uint32_t addr)
{

   uint16_t msgIndex = startIndex;
   uint16_t seqno;
   uint32_t count, stride;

   if (bGen4Ether)
   {
      /* By setting the stride to 16 and base addr sat to Lo-Hi latched status, */
      /* two registers will be read using the command array, the Lo-hi and Hi-Lo latched status registers */
      seqno = 0;
      addr = boardAddress + moduleOffset + addr;
      count = DSW_INTERRUPT_RESPONSE_REG_COUNT;
      stride = 16;

      msgIndex = (uint16_t)nai_ether_MakeReadMessage(&inputIDRConfig->commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface, addr, stride, count, NAI_REG32);
      inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndex;
      command_index_interrupt_status = inputIDRConfig->cmdcount;
      inputIDRConfig->cmdcount++;
   }
}
/**************************************************************************************************************/
/**
<summary>
HandleDSWEtherInterrupt is called by the decodeUPRIDRMessages() routine in nai_sys_int_ether.c when an
unprompted (UPR) Ethernet message is received with the TDR/IDR Index equal to DEF_ETHERNET_DT_IDR_ID.
This routine will parse the message to retrieve the information requested in the SetupDTEtherIDRconfig()
routine.
</summary>
*/
/**************************************************************************************************************/
void HandleDSWEtherInterrupt(uint16_t msglen, uint8_t msg[], uint16_t tdr_idr_id)
{
   uint16_t seq;
   nai_ether_typecode_t tc;
   nai_ether_gen_t gen = NAI_ETHER_GEN4;
   int32_t size;
   int32_t offset;
   uint16_t datacnt = 0;
   uint32_t data;
   uint32_t dswstatus_int[DSW_INTERRUPT_RESPONSE_REG_COUNT];
   nai_dsw_status_type_t dsw_status_type = NAI_DSW_STATUS_BIT_LATCHED;
   int32_t i;
   offset = nai_ether_DecodeMessageHeader(msg, msglen, &seq, &tc, gen, &size);

   switch (tc)
   {
      case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4:
         datacnt = (msglen - 10) / NAI_REG32;
         for (i = 0; i < datacnt; i++)
         {
            data = 0;
            data = msg[offset++] << 24;
            data |= msg[offset++] << 16;
            data |= msg[offset++] << 8;
            data |= msg[offset++];
            if (i < DSW_INTERRUPT_RESPONSE_REG_COUNT)
               dswstatus_int[i] = data;
         }
         break;
   }
   printf("\n\n");
   printf("IDR ID : %d\n", tdr_idr_id);

  /* Check to make sure we got all 4 status elements (BIT, Lo-Hi, Hi-Lo, Overcurrent) */
   if (datacnt == DSW_INTERRUPT_RESPONSE_REG_COUNT)
   {

      for (i = 0; i < DSW_INTERRUPT_RESPONSE_REG_COUNT; i++)
      {
         switch (i)
         {
            case 0:
               dsw_status_type = NAI_DSW_STATUS_LO_HI_TRANS_LATCHED;
               break;
            case 1:
               dsw_status_type = NAI_DSW_STATUS_HI_LO_TRANS_LATCHED;
               break;
         }
         if (dswstatus_int[i] != 0)
         {
            switch (i)
            {
               case 0:
                  printf("Received DSW Lo-Hi Interrupt: (Interrupt_status) 0x%08X\n", dswstatus_int[i]);
                  break;
               case 1:
                  printf("Received DSW Hi-Lo Interrupt: (Interrupt_status) 0x%08X\n", dswstatus_int[i]);
                  break;
            }

            check_status(naibrd_DSW_ClearGroupStatusRaw(inputDSWConfig.cardIndex, inputDSWConfig.module, 1, dsw_status_type, dswstatus_int[i]));
            switch (i)
            {
               case 0:
                  printf("Cleared DSW Lo-Hi Interrupt: 0x%08X\n", dswstatus_int[i]);
                  break;
               case 1:
                  printf("Cleared DSW Hi-Lo Interrupt: 0x%08X\n", dswstatus_int[i]);
                  break;
            }
         }
      }
   }
}

/**************************************************************************************************************/
/**
<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 MakeDSWWriteRegsCommand(DswConfig inputDSWConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex)
{

   uint16_t msgIndex = startIndex;
   uint16_t seqno;
   uint32_t count, stride;
   uint32_t regaddr;
   uint32_t data = 0x1 << (inputDSWConfig.channel - 1);   /* Clear Rx interrupt bits */
   uint32_t addr = NAI_DSW_GEN5_REG_BIT_LATCHED_STATUS_ADD;

   if (bGen4Ether)
   {

      seqno = 0;
      regaddr = boardAddress + moduleOffset + addr;
      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++;
   }
}

Help Bot

X