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

EtherZBlockCommands

EtherZBlockCommands

Explanation

About the Sample Application Code

This C program demonstrates how to interact with North Atlantic Industries (NAI) embedded function modules using various functions for Ethernet Z-Block commands. Below is a detailed explanation of the provided sample code.

Included Header Files

The program starts by including various standard C library headers and NAI-specific headers: - Standard C Library Headers: - stdio.h, stdlib.h, string.h, time.h, ctype.h - NAI Sample Program Headers: - naiapp_boardaccess_menu.h, naiapp_boardaccess_query.h, naiapp_boardaccess_access.h, naiapp_boardaccess_display.h, naiapp_boardaccess_utils.h - NAI Board-Specific Headers: - nai.h, naibrd.h, naibrd_ether.h, nai_ether_adv.h, naibrd_gen5.h

Constants and Data Structures

  • CONFIG_FILE: The path to the default configuration file for Ethernet Z-Block.

  • Function Prototypes: Prototypes for internal program functions that handle different Z-Block operations.

  • Enum eth_zblock_commands: Enumerates commands related to Ethernet Z-Block: Set, Get, Clear, Read, Write.

  • Command Table (ETH_ZBlockcmdMenuCmds): Holds command names, descriptions, and associated function pointers.

Memory Allocation and Definitions

  • MB_SCRATCHPAD_START_ADDRESS: Specifies the start address of the motherboard scratchpad area.

  • DEF_REGISTER_SIZE: Defines the size of a 32-bit register.

  • Global Variables:

  • g_bGen4ZBlockCommands: A flag to determine the support for Generation 4 Ethernet commands.

  • g_zblockRegCnt: An array to keep track of the register count for each Ethernet block.

  • g_writeDataCnt: A global counter for the data written to the Z-Block registers.

Main Function

The main entry point depends on the defined platform: - For VxWorks (VXWORKS), the entry function is EtherZBlockCommands. - For other platforms, such as Windows, the entry function is main.

Main Function Workflow:

  1. Initialization: Runs the board menu using naiapp_RunBoardMenu with the CONFIG_FILE.

  2. User Interaction Loop: Continuously queries the user for card index and executes Z-Block commands until the user opts to quit.

  3. Card Access Closure: Closes all open cards before exiting.

Functional Description

Run_EtherZBlockCommands

Runs the Ethernet Z-Block commands for a specified card index: - Checks if the board supports Generation 4 Ethernet commands. - Displays a command menu and waits for user input to execute corresponding functions.

QueryEthZBlockID

Queries the user for the Z-Block ID and validates the input.

InitZBlockRegisters

Initializes the list of register addresses and their flags for a specified Z-Block: - If Gen4 commands are supported, assigns address values and flags. - For unsupported generations, it displays an error message.

InitZBlockRegistersData

Initializes the data to write to the list of register addresses for the Write Z-Block command.

Command-Specific Functions

  1. SetEthZBlockConfig

    • Queries Z-Block ID and initializes register addresses.

    • Calls naibrd_Ether_SetZBlock to set the Z-Block configuration.

  2. GetEthZBlockConfig

    • Queries Z-Block ID and retrieves register addresses.

    • Calls naibrd_Ether_GetZBlock to get the Z-Block configuration.

  3. ClearEthZBlockConfig

    • Queries Z-Block ID and clears register addresses.

    • Calls naibrd_Ether_ClearZBlock for the clear command.

  4. ReadEthZBlockRegisters

    • Queries Z-Block ID and reads register data.

    • Calls naibrd_Ether_ReadZBlock to read the register values.

  5. WriteEthZBlockRegisters

    • Queries Z-Block ID, initializes data, and writes to registers.

    • Calls naibrd_Ether_WriteZBlock to write data to the registers.

This sample code effectively demonstrates configuring and interacting with NAI Ethernet Z-Block commands, enabling the user to set, get, clear, read, and write Ethernet Z-Block configurations on a specified card.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.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 "nai.h"
#include "naibrd.h"
#include "naibrd_ether.h"
#include "advanced/nai_ether_adv.h"
#include "boards/naibrd_gen5.h"

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

/* Function prototypes */
static bool_t Run_EtherZBlockCommands(int32_t cardIndex);
static bool_t QueryEthZBlockID(int32_t* p_outblockid);
static void InitZBlockRegisters(uint32_t* p_outcount, uint16_t addrflag[], uint32_t address[]);
static void InitZBlockRegistersData(uint32_t count, uint32_t data[]);
static nai_status_t SetEthZBlockConfig(int32_t paramCount, int32_t* p_params);
static nai_status_t GetEthZBlockConfig(int32_t paramCount, int32_t* p_params);
static nai_status_t ClearEthZBlockConfig(int32_t paramCount, int32_t* p_params);
static nai_status_t ReadEthZBlockRegisters(int32_t paramCount, int32_t* p_params);
static nai_status_t WriteEthZBlockRegisters(int32_t paramCount, int32_t* p_params);

/****** Command Table *******/
enum eth_zblock_commands
{
   ETH_ZBLOCK_CMD_SET,
   ETH_ZBLOCK_CMD_GET,
   ETH_ZBLOCK_CMD_CLEAR,
   ETH_ZBLOCK_CMD_READ,
   ETH_ZBLOCK_CMD_WRITE,
   ETH_ZBLOCK_CMD_COUNT
};

/****** Command Tables *******/
naiapp_cmdtbl_params_t ETH_ZBlockcmdMenuCmds[] = {
   {"Set",    "Set Z-Block Configuration",    ETH_ZBLOCK_CMD_SET,    SetEthZBlockConfig},
   {"Get",    "Get Z-Block Configuration",    ETH_ZBLOCK_CMD_GET,    GetEthZBlockConfig},
   {"Clear",  "Clear Z-Block Configuration",  ETH_ZBLOCK_CMD_CLEAR,  ClearEthZBlockConfig},
   {"Read",   "Read Z-Block Registers",       ETH_ZBLOCK_CMD_READ,   ReadEthZBlockRegisters},
   {"Write",  "Write to Z-Block Registers",   ETH_ZBLOCK_CMD_WRITE,  WriteEthZBlockRegisters},
};

/* Gen 5 Motherboard Scratchpad Area (Note: for Reference only Scratchpad area may vary on different Gen 5 boards */
#define MB_SCRATCHPAD_START_ADDRESS       0x00003800    /* Motherboard Scratchpad Area: 0x00003800 - 0x00003BFF */
#define DEF_REGISTER_SIZE           4    /* Number of bytes for 32-bit Register */

static bool_t g_bGen4ZBlockCommands = FALSE;

/* ZBlock Register Count */
static uint32_t g_zblockRegCnt[MAX_ETHER_BLOCK_ID] =
{
   0, 0, 0, 0, 0, 0, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 0,
};

static int32_t g_writeDataCnt = 0;  /* Global counter to change data written to z-block */

/**************************************************************************************************************/
/**
<summary>
The purpose of the EtherZBlockCommands is to illustrate the methods to call in the naibrd library to handle the
Ethernet Z-Block Commands.

The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd Ethernet routines.
 - ConfigDevice
 - DisplayDeviceCfg
 - GetBoardSNModCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t EtherZBlockCommands(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            Run_EtherZBlockCommands(cardIndex);
         }
         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 runs the Ethernet Z-Block Commands program.
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_EtherZBlockCommands(int32_t cardIndex)
{
   bool_t bQuit = FALSE;
   bool_t bContinue = TRUE;
   bool_t bCmdFound = FALSE;
   int32_t cmd;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   naiapp_AppParameters_t zblock_params;
   p_naiapp_AppParameters_t p_eth_zblock_params = &zblock_params;
   p_eth_zblock_params->cardIndex = cardIndex;

   /* Determine if the board selected supports the Generation 4 Ethernet Commands */
   g_bGen4ZBlockCommands = SupportsGen4Ether(cardIndex);

   while (bContinue)
   {
      naiapp_utils_LoadParamMenuCommands(ETH_ZBLOCK_CMD_COUNT, ETH_ZBlockcmdMenuCmds); /* reload main menu  */
      naiapp_display_ParamMenuCommands((int8_t *)"Ethernet Z-Block Command Menu");
      printf("\nType Ethernet Z-Block command or %c to quit : ", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         if (inputResponseCnt > 0)
         {
            bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
            if (bCmdFound)
            {
               switch (cmd)
               {
               case ETH_ZBLOCK_CMD_SET:
               case ETH_ZBLOCK_CMD_GET:
               case ETH_ZBLOCK_CMD_CLEAR:
               case ETH_ZBLOCK_CMD_READ:
               case ETH_ZBLOCK_CMD_WRITE:
                  ETH_ZBlockcmdMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)p_eth_zblock_params);
                  break;
               default:
                  printf("Invalid command entered\n");
                  break;
               }
            }
            else
               printf("Invalid command entered\n");
         }
      }
      else
         bContinue = FALSE;
   }
   return bQuit;
}

/**************************************************************************************************************/
/**
<summary>
This function queries the user to enter the block id to apply the Set, Get, Clear, Read and Write Block
commands.
</summary>
*/
/**************************************************************************************************************/
static bool_t QueryEthZBlockID(int32_t* p_outblockid)
{
   bool_t bQuit = FALSE;
   int32_t valueread = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("Enter the Z-Block ID: (default: 1) > ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         valueread = 1;
      else
      {
         valueread = atol((const char *)inputBuffer);
         if ((valueread < 0) || (valueread > MAX_ETHER_BLOCK_ID))
         {
            printf("Error: Z-BlockID is invalid\n");
            bQuit = TRUE;
         }
      }
      *p_outblockid = valueread;
   }
   return bQuit;
}

/**************************************************************************************************************/
/**
<summary>
This function sets up the list of register addresses to included for the Set Z-Block command.
</summary>
*/
/**************************************************************************************************************/
static void InitZBlockRegisters(uint32_t* p_outcount, uint16_t addrflag[], uint32_t address[])
{
   int32_t index = 0;
   int32_t flgindex = 0;
   int32_t boardindex;
   uint16_t inf;
   uint32_t baseaddr;

   if (g_bGen4ZBlockCommands)
   {
      /* Note: the address specified below is for the Motherboard Scratchpad Area.
               For addrflag settings: 0 = Onboard, 1 = Offboard.
      */
      for (boardindex = 0; boardindex < naiapp_GetBoardCnt(); boardindex++)
      {
         if (boardindex == 0)
         {
            inf = ETHER_GEN4_ONBOARD;  /* Onboard */
            baseaddr = 0;
         }
         else
         {
            inf = ETHER_GEN4_OFFBOARD;  /* Offboard */
            if (g_NAISysCfgAccess[boardindex].comm == NAIBRD_COMM_VME)
               baseaddr = g_NAISysCfgAccess[boardindex].vmeCfg.boardAddress;
            else if (g_NAISysCfgAccess[boardindex].comm == NAIBRD_COMM_PCI)
               baseaddr = g_NAISysCfgAccess[boardindex].pciCfg.boardAddress;
            else
               baseaddr = 0;
         }
         /* Motherboard Common area */
         address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0000;       /*  1 */
         addrflag[flgindex++] = inf;
         address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0010;       /*  2 */
         addrflag[flgindex++] = inf;
         address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0050;       /*  3 */
         addrflag[flgindex++] = inf;
         address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0100;       /*  4 */
         addrflag[flgindex++] = inf;
         address[index++] = baseaddr + MB_SCRATCHPAD_START_ADDRESS + 0x0110;       /*  5 */
         addrflag[flgindex++] = inf;
      }

      *p_outcount = index;
   }
   else
   {
      printf("Ethernet Z-Block Command Support Prior to Generation 4 Ethernet commands currently not supported\n");
   }
}

/**************************************************************************************************************/
/**
<summary>
This function sets up the data to write to list of register addresses for the Write Z-Block command.
</summary>
*/
/**************************************************************************************************************/
static void InitZBlockRegistersData(uint32_t count, uint32_t data[])
{
   uint32_t index = 0;
   for (index = 0; index < count; index++)
   {
      if (g_bGen4ZBlockCommands)
      {
         data[index] = g_writeDataCnt++;
      }
   }
}

/**************************************************************************************************************/
/**
<summary>
This function calls InitZBlockRegisters() to sets up the list of register addresses for the Set Z-Block command
and calls naibrd_Ether_SetZBlock() to send the SetZBlock command to the board for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t SetEthZBlockConfig(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   nai_status_t status;
   uint16_t addrflag[MAX_ETHER_BLOCK_REG_CNT];
   uint32_t address[MAX_ETHER_BLOCK_REG_CNT];
   p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ether_params->cardIndex;
   int32_t blockid = 0;
   int32_t regwidth = DEF_REGISTER_SIZE;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   bQuit = QueryEthZBlockID(&blockid);
   if (!bQuit)
   {
      InitZBlockRegisters(&g_zblockRegCnt[blockid-1], &addrflag[0], &address[0]);
      status = check_status(naibrd_Ether_SetZBlock(cardIndex, (uint16_t)blockid, (uint32_t)regwidth, g_zblockRegCnt[blockid-1], addrflag, address));
      if (status == NAI_SUCCESS)
      {
         printf("Block ID = %d configured.\n", blockid);
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
This function calls naibrd_Ether_GetZBlock() to send the GetZBlock command to the board to retrieve the list of
register addresses specified for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t GetEthZBlockConfig(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   nai_status_t status;
   uint32_t arraysize = MAX_ETHER_BLOCK_REG_CNT;
   uint16_t addrflag[MAX_ETHER_BLOCK_REG_CNT];
   uint32_t address[MAX_ETHER_BLOCK_REG_CNT];
   int32_t i;
   p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ether_params->cardIndex;
   int32_t blockid = 0;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   bQuit = QueryEthZBlockID(&blockid);
   if (!bQuit)
   {
      status = check_status(naibrd_Ether_GetZBlock(cardIndex, (uint16_t)blockid, arraysize, addrflag, address, &g_zblockRegCnt[blockid-1]));

      if (status == NAI_SUCCESS)
      {
         if (g_zblockRegCnt[blockid-1] > 0)
         {
            printf("\n\nBlock ID = %d - %d Registers with Addresses:\n", blockid, g_zblockRegCnt[blockid-1]);
            for (i = 0; i < (int32_t)g_zblockRegCnt[blockid-1]; i++)
            {
               printf("%3d:  0x%08X", i+1, address[i]);
               if (addrflag[i] == 0)
                  printf("  Onboard\n");
               else
                  printf("  Offboard\n");
            }
         }
         else
            printf("\n\nNo Registers configured for Block ID = %d\n", blockid);
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
This function calls naibrd_Ether_ClearZBlock() to send the ClearZBlock command to the board to remove the list of
register addresses specified for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t ClearEthZBlockConfig(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   nai_status_t status;
   p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ether_params->cardIndex;
   int32_t blockid = 0;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   bQuit = QueryEthZBlockID(&blockid);
   if (!bQuit)
   {
      status = check_status(naibrd_Ether_ClearZBlock(cardIndex, (uint16_t)blockid));

      if (status == NAI_SUCCESS)
      {
         printf("Block ID = %d cleared\n", blockid);
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
This function calls naibrd_Ether_ReadZBlock() to send the ReadZBlock command to the board to retrieve the data
for the list of register addresses specified for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t ReadEthZBlockRegisters(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   nai_status_t status;
   uint32_t arraysize = MAX_ETHER_BLOCK_REG_CNT;
   uint32_t data[MAX_ETHER_BLOCK_REG_CNT];
   uint32_t datacount = 0;
   int32_t i;
   p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ether_params->cardIndex;
   int32_t blockid = 0;
   int32_t regwidth = DEF_REGISTER_SIZE;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   bQuit = QueryEthZBlockID(&blockid);
   if (!bQuit)
   {
      status = check_status(naibrd_Ether_ReadZBlock(cardIndex, (uint16_t)blockid, (uint32_t)regwidth, arraysize, data, &datacount));

      if (status == NAI_SUCCESS)
      {
         if (datacount > 0)
         {
            printf("\n\nBlock ID = %d - %d Register Values:\n", blockid, datacount);
            for (i = 0; i < (int32_t)datacount; i++)
            {
               printf("%3d:  0x%08X\n", i+1, data[i]);
            }
         }
         else
            printf("\n\nNo Registers read for Block ID = %d\n", blockid);
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
This function calls InitZBlockRegistersData() to set up the data to write to the list of registers and calls
naibrd_Ether_WriteZBlock() to send the WriteZBlock command to the board to write the data to the list of register
addresses specified for the Block ID specified.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t WriteEthZBlockRegisters(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   nai_status_t status;
   uint32_t data[MAX_ETHER_BLOCK_REG_CNT];
   p_naiapp_AppParameters_t p_ether_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ether_params->cardIndex;
   int32_t blockid = 0;
   int32_t regwidth = DEF_REGISTER_SIZE;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   bQuit = QueryEthZBlockID(&blockid);
   if (!bQuit)
   {
      InitZBlockRegistersData(g_zblockRegCnt[blockid-1], &data[0]);
      status = check_status(naibrd_Ether_WriteZBlock(cardIndex, (uint16_t)blockid, (uint32_t)regwidth, g_zblockRegCnt[blockid-1], data));
      if (status == NAI_SUCCESS)
      {
         printf("Block ID = %d Data written.\n", blockid);
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

Help Bot

X