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

ETC BasicOps

ETC BasicOps Sample Application (SSK 1.x)

Overview

The ETC BasicOps sample application demonstrates how to read the Elapsed Time Counter (ETC) on an NAI SIU chassis using the NAI Software Support Kit (SSK 1.x). The ETC is a device-level feature — not a module-level feature — that tracks the total operational hours of the chassis. It is useful for maintenance scheduling, warranty tracking, and general fleet management.

This sample covers the two ETC read operations available in the naibrd_DevEtc.h API:

  • Get Total Seconds — retrieve the cumulative power-on time as a single raw count.

  • Get Elapsed Time — retrieve the same counter broken down into years, days, hours, minutes, and seconds.

Because the ETC is a device-level feature, you do not select a module slot. Instead, you open a direct connection to the chassis using naibrd_ETC_Open() and read the counter with naibrd_ETC_GetTotalSeconds() or naibrd_ETC_GetElapsedTime(). The sample serves as a practical API reference — each operation maps directly to a naibrd_ETC_*() API call that you can lift into your own code.

Prerequisites

Before running this sample, make sure you have:

  • An NAI SIU chassis that supports the Elapsed Time Counter feature (e.g., 75G5, 75INT2, 75PPC1, 75ARM1).

  • 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.

How to Run

Launch the ETC_BasicOps executable from your build output directory. The application does not use a configuration file. On startup it prompts you to choose Ethernet or I2C communication:

  • Ethernet — use this when running externally from the SIU chassis. The NAI Ethernet Listener Server must be running on the chassis main processor.

  • I2C — use this when running directly on the chassis main processor.

On Linux, you can optionally pass an iteration count as a command-line argument (e.g., ./ETC_BasicOps 20). The default is 10 iterations.

Board Connection

Note
The ETC is a device-level feature, so the connection sequence differs from module-level samples. There is no module selection step — you connect directly to the chassis and open the ETC device.

The main() function follows this startup flow:

  1. Prompt the user to select Ethernet or I2C communication.

  2. If Ethernet is selected, query for protocol (TCP/UDP), port, and IP address using naiapp_query_EthernetCfg().

  3. Set the IP address with naibrd_SetIPAddress() and open the ETC device with naibrd_ETC_Open(), passing the appropriate communication type.

  4. If I2C is selected, open the ETC device directly with naibrd_ETC_Open() using NAIBRD_COMM_I2C.

/* Check where this application is running */
printf("Is this application running externally and communicating to the SIU\n");
printf("via Ethernet? (default: Y) : ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
   if ((inputResponseCnt == 0) || (toupper(inputBuffer[0]) == 'Y'))
   {
      bEthernet = TRUE;
      bQuit = naiapp_query_EthernetCfg(maximillionBrd, &Protocol, &Port, &szIPAddress[0]);
      if (!bQuit)
      {
         sprintf((char*)&szPort[0], "%d", Port);
      }
   }
}

To open the ETC device in your own application, call naibrd_ETC_Open() with the card index and the communication type that matches your connection:

if (bEthernet)
{
   check_status(naibrd_SetIPAddress(g_etc_cardIndex, (const char *)&szIPAddress[0], (const char *)&szPort[0]));
   if (Protocol == NAI_TCP_PROTOCOL)
   {
      status = check_status(naibrd_ETC_Open(g_etc_cardIndex, NAIBRD_COMM_ETHER_TCP));
   }
   else
   {
      status = check_status(naibrd_ETC_Open(g_etc_cardIndex, NAIBRD_COMM_ETHER_UDP));
   }
}
else
{
   status = check_status(naibrd_ETC_Open(g_etc_cardIndex, NAIBRD_COMM_I2C));
}

API parameters for naibrd_ETC_Open():

  • cardIndex — a logical reference to the ETC device. This can be any value between 0 and NAI_MAX_CARDS - 1. The sample uses 1.

  • comm — the communication method. Valid values are NAIBRD_COMM_ETHER_TCP, NAIBRD_COMM_ETHER_UDP, and NAIBRD_COMM_I2C.

Important

Common connection errors you may encounter at this stage:

  • No response from chassis — verify that the SIU chassis is powered on and reachable. For Ethernet connections, confirm the IP address and port are correct and that the NAI Ethernet Listener Server is running on the chassis main processor.

  • Connection timeout — check firewall settings and network routing between your development host and the chassis.

  • I2C failure — I2C communication is only available when the application runs directly on the chassis main processor (e.g., 75INT2, 75PPC1, 75ARM1). If you are running externally, use Ethernet.

  • Invalid card index — the card index is a logical identifier. Ensure you have not exceeded NAI_MAX_CARDS - 1.

Program Structure

Entry Point

The application entry point is main() on standard platforms and ETC_BasicOps() on VxWorks:

#if defined (__VXWORKS__)
int32_t ETC_BasicOps(void)
#else
int32_t main(int argc, char** argv)
#endif

Application Flow

Unlike module-level samples that use a menu-driven command loop, ETC BasicOps runs a simple timed loop. After opening the ETC device, the application reads the counter a fixed number of times (default 10, configurable on Linux via command-line argument), sleeping one second between reads. There is no interactive menu — the two read operations execute sequentially in each iteration.

In your own code, you do not need a loop. Call naibrd_ETC_GetTotalSeconds() or naibrd_ETC_GetElapsedTime() whenever you need to check the operational time.

Reading the Elapsed Time Counter

The ETC API provides two ways to read the same underlying counter. Use whichever format is more convenient for your application.

Get Total Seconds

To retrieve the cumulative power-on time as a single value in seconds, call naibrd_ETC_GetTotalSeconds():

if (check_status(naibrd_ETC_GetTotalSeconds(g_etc_cardIndex, &sec)) == NAI_SUCCESS)
{
   printf("<%d/%d>total seconds: 0x%08X\n", i+1, tst_cnt, sec);
}

API parameters for naibrd_ETC_GetTotalSeconds():

  • cardIndex — the logical card index used when opening the ETC device.

  • outtotal_seconds — pointer to a uint32_t that receives the total elapsed seconds. The value is returned in hexadecimal format in the sample output, but it is a standard unsigned integer you can use in arithmetic.

This call is useful when you need a single comparable value — for example, to check whether a chassis has exceeded a maintenance threshold.

Get Elapsed Time (Broken Down)

To retrieve the power-on time broken down into human-readable components, call naibrd_ETC_GetElapsedTime():

if (check_status(naibrd_ETC_GetElapsedTime(g_etc_cardIndex, &year, &day, &hour, &min, &sec)) == NAI_SUCCESS)
{
   printf("<%d/%d>year=%u,day=%u,hour=%u,min=%u,sec=%u\n\n", i+1, tst_cnt, year, day, hour, min, sec);
}

API parameters for naibrd_ETC_GetElapsedTime():

  • cardIndex — the logical card index used when opening the ETC device.

  • outyear — pointer to a uint32_t that receives the number of complete years.

  • outday — pointer to a uint32_t that receives the remaining days (after full years).

  • outhour — pointer to a uint32_t that receives the remaining hours (after full days).

  • outmin — pointer to a uint32_t that receives the remaining minutes (after full hours).

  • outsec — pointer to a uint32_t that receives the remaining seconds (after full minutes).

This call is useful for display and logging purposes where a human-readable breakdown is more informative than a raw second count.

Polling Loop and Delay

The sample reads the counter in a loop with a one-second delay between iterations:

for (i = 0; i < tst_cnt; i++)
{
   /* ... read total seconds and elapsed time ... */
   nai_msDelay(1000);
}

The nai_msDelay() utility function pauses execution for the specified number of milliseconds. In your own application, you do not need to poll in a tight loop — read the ETC on demand whenever you need the current operational time.

Important

Common Errors

  • NAI_ERROR_NOT_SUPPORTED — the chassis does not support the ETC feature, or the ETC device was not opened successfully before calling a read function. Verify that your chassis model supports ETC and that naibrd_ETC_Open() returned NAI_SUCCESS.

  • Stale or unchanging values — if the elapsed time does not increment between reads, confirm the chassis is not in a low-power or standby state. The ETC only counts time while the chassis is fully powered on.

  • Hexadecimal total seconds appears very large — this is expected for a chassis with significant operational history. A uint32_t can represent over 136 years of seconds, so overflow is unlikely in practice.

Closing the Device

When your application is finished reading the ETC, close the device to release resources:

naibrd_Close(g_etc_cardIndex);

Always call naibrd_Close() before exiting, even if earlier operations returned errors. This ensures the communication channel is properly released.

Troubleshooting Reference

Note
This section summarizes errors covered in the preceding sections. Consult your chassis documentation for hardware-specific diagnostics.
Error / Symptom Possible Causes Suggested Resolution

No response from chassis

Chassis powered off; incorrect IP address or port; Ethernet Listener Server not running

Verify power, network settings, and that the listener server is active on the chassis main processor.

Connection timeout

Firewall blocking traffic; IP mismatch; network routing issue

Check firewall rules, verify IP address matches the chassis, and confirm network connectivity with a ping test.

I2C communication failure

Application running externally instead of on the chassis main processor

I2C is only available when running on the chassis processor. Switch to Ethernet for external communication.

NAI_ERROR_NOT_SUPPORTED

Chassis does not support ETC; ETC device not opened before read

Confirm your chassis model supports ETC. Ensure naibrd_ETC_Open() succeeded before calling read functions.

Elapsed time does not increment

Chassis in standby or low-power state

Confirm the chassis is fully powered on and operational.

naibrd_ETC_Open() returns failure

Invalid card index; communication type mismatch

Verify the card index is within range (0 to NAI_MAX_CARDS - 1) and that the communication type matches your connection method.

Full Source

Full Source — ETC_BasicOps.c (SSK 1.x)
#include <stdio.h>  /* for printf(),getchar() */
#include <string.h> /* for void *memcpy(void *dest, const void *src, size_t n); */
#include <stdlib.h>
#include <ctype.h>

/* Common Sample Program include files */
#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 "naibrd.h"
#include "advanced/nai_ether_adv.h"
#include "devices/naibrd_DevEtc.h"

static void DisplayETCApplicationDescription()
{
   printf("                        ETC Application Description\n");
   printf("---------------------------------------------------------------------------------\n");
   printf("This application is intended to run with the SIU Chassis that supports\n");
   printf("the Elapsed Time Counter (ETC) feature.\n\n");

   printf("When this application is running externally from the SIU Chassis,\n");
   printf("the NAI Ethernet Listener Server must be running in the main processor\n");
   printf("in the NIU SIU Chassis (ex. 75G5, 75INT2, 75PPC1, 75ARM1, etc.),\n");
   printf("and the communication method must be Ethernet.\n\n");

   printf("When this application is running on the main processor in the NIU SIU Chassis\n");
   printf("(ex. 75INT2, 75PPC1, 75ARM1, etc.), the communication method must be I2C.\n\n");

   printf("\n");
}

/**************************************************************************************************************/
/**
<summary>
The purpose of the PS_BasicOps is to illustrate the methods to call in the naibrd library to perform basic
 monitor operations with the PS4 Power Supply.

</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t ETC_BasicOps(void)
#else
int32_t main(int argc,char** argv)
#endif
{
   nai_status_t status = NAI_SUCCESS;
   int32_t g_etc_cardIndex = 1; /* Note, the g_etc_cardIndex is a logical reference to the Elasped Time Counter device - can be any value between (0 - NAI_MAX_CARDS-1) */
   bool_t bQuit = FALSE;

   uint32_t year;
   uint32_t day;
   uint32_t hour;
   uint32_t min;
   uint32_t sec;

   bool_t bEthernet = FALSE;
   bool_t maximillionBrd = TRUE;
   int32_t Protocol = 0;
   int8_t Port = 0;
   int8_t szPort[NAI_MAX_PORT_LEN];
   int8_t szIPAddress[NAI_MAX_IP_LEN];
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   int i,tst_cnt=10;

#if defined (LINUX)
   if ( argc == 2 )
   {
      tst_cnt=atoi(argv[1]);
   }
#elif WIN32
   UNREFERENCED_PARAMETER(argc);
   UNREFERENCED_PARAMETER(argv);
#endif

   DisplayETCApplicationDescription();

   /* Check where this application is running */
   printf("Is this application running externally and communicating to the SIU\n");
   printf("via Ethernet? (default: Y) : ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if ((inputResponseCnt == 0) || (toupper(inputBuffer[0]) == 'Y'))
      {
         bEthernet = TRUE;
         /* Get the IP Address for the NAI board */
         bQuit = naiapp_query_EthernetCfg(maximillionBrd, &Protocol, &Port, &szIPAddress[0]);
         if (!bQuit)
         {
            sprintf((char*)&szPort[0], "%d", Port);
         }
      }
   }

   if (!bQuit)
   {
      if (bEthernet)
      {
         check_status(naibrd_SetIPAddress(g_etc_cardIndex, (const char *)&szIPAddress[0], (const char *)&szPort[0]));
         if (Protocol == NAI_TCP_PROTOCOL)
         {
            status = check_status(naibrd_ETC_Open(g_etc_cardIndex, NAIBRD_COMM_ETHER_TCP));
         }
         else
         {
            status = check_status(naibrd_ETC_Open(g_etc_cardIndex, NAIBRD_COMM_ETHER_UDP));
         }
      }
      else
      {
         status = check_status(naibrd_ETC_Open( g_etc_cardIndex, NAIBRD_COMM_I2C));
      }

      if (status == NAI_SUCCESS)
      {
         for ( i = 0; i < tst_cnt; i++ )
         {
            if ( check_status(naibrd_ETC_GetTotalSeconds(g_etc_cardIndex, &sec)) == NAI_SUCCESS  )
            {
                printf("<%d/%d>total seconds: 0x%08X\n", i+1, tst_cnt, sec);
            }

            if ( check_status(naibrd_ETC_GetElapsedTime(g_etc_cardIndex, &year, &day, &hour, &min, &sec) ) == NAI_SUCCESS  )
            {
               printf("<%d/%d>year=%u,day=%u,hour=%u,min=%u,sec=%u\n\n", i+1, tst_cnt, year, day, hour, min, sec);
            }
            nai_msDelay(1000);
         }
      }

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

      /* Close the board */
      naibrd_Close(g_etc_cardIndex);

      return 0;
   }
   else
   {
      return -1;
   }
}

Help Bot

X