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

IOCT BasicOps

IOCT BasicOps Sample Application (SSK 1.x)

Overview

The IOCT BasicOps sample application demonstrates how to configure and operate I/O Control and Timing (IOCT) channels using the NAI Software Support Kit (SSK 1.x). IOCT modules provide high-speed, synchronous serial communication channels designed for deterministic data transfer in embedded systems. At the hardware level, each IOCT channel implements a clocked serial interface with Start-of-Element Pulse (SEP) timing, transmit and receive FIFOs, and configurable master/slave roles — enabling tightly synchronized data exchange between boards or subsystems on a shared bus.

This sample supports the following IOCT module types:

  • PE — Multi-channel IOCT module (NAI_MODULE_ID_PE, 0x5045).

  • SC4 — Single-channel Maximillion IOCT module (NAI_MODULE_ID_SC4, 0x53433420).

The SC4 module has a reduced command set compared to the PE: it does not support slave mode, and some command bits (such as even parity and standby mode) differ from their PE equivalents. The sample detects the module type at runtime and loads the appropriate command menu automatically. It serves as a practical API reference — each menu command maps directly to one or more naibrd_IOCT_*() API calls that you can lift into your own code.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with an IOCT module installed (PE or SC4).

  • 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 IOCT_BasicOps executable from your build output directory. On startup the application looks for a configuration file (default_IOCT_BasicOps.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, a command menu lets you exercise each IOCT operation.

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 IOCT. For details on board connection configuration, see the First Time Setup Guide.

The main() function follows a standard SSK 1.x startup flow:

  1. Call naiapp_RunBoardMenu() to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_IOCT_BasicOps.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear.

  2. Query the user for a card index with naiapp_query_CardIndex().

  3. Query for a module slot with naiapp_query_ModuleNumber().

  4. Retrieve the module ID with naibrd_GetModuleID() so downstream code can adapt to the specific IOCT variant installed (PE vs. SC4).

#if defined (__VXWORKS__)
int32_t IOCT_BasicOpsMenu(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  IOCTBasicOpsMenu_run(cardIndex, module, moduleID);
               }
            }
         }

         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;
}
Important

Common connection errors you may encounter at this stage:

  • No board found — verify that the board is powered on and physically connected. Check that the configuration file lists the correct interface and address.

  • Connection timeout — confirm network settings (for Ethernet connections) or bus configuration (for PCI/PCIe). Firewalls and IP mismatches are frequent causes.

  • Invalid card or module index — indices are zero-based for cards and one-based for modules. Ensure the values you pass match your hardware setup.

  • Module not present at selected slot — the slot you selected does not contain an IOCT module. Use the board menu to verify which slots are populated.

Program Structure

Entry Point

The main() function (or IOCT_BasicOpsMenu() on VxWorks) handles board connection and module selection as described above. After the user selects a valid module, it calls IOCTBasicOpsMenu_run() to enter the command loop.

Application Parameters

Each command function receives its parameters through a p_naiapp_AppParameters_t structure. In your own code, you will track the same values directly:

  • cardIndex — identifies which board to communicate with (zero-based).

  • module — the slot number containing the IOCT module (one-based).

  • channel — the IOCT channel to operate on (one-based).

Command Loop and Module-Specific Menus

The IOCTBasicOpsMenu_run() function detects the module type and loads the appropriate command table. For SC4 modules, the slave mode command is omitted because SC4 hardware does not support slave operation. The menu system is a sample convenience — in your own code, call these API functions directly.

static bool_t IOCTBasicOpsMenu_run(int32_t cardIndex, int32_t module, uint32_t modid)
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   ioct_modid = modid;
   if (ioct_modid == NAI_MODULE_ID_SC4)
      naiapp_utils_LoadParamMenuCommands(IOCT_BASICOPS_CMD_COUNT,
                                         IOCT_SC4_BasicOpMenuCmds);
   else
      naiapp_utils_LoadParamMenuCommands(IOCT_BASICOPS_CMD_COUNT,
                                         IOCT_PE_BasicOpMenuCmds);
   DisplayIOCTConfigurations(cardIndex, module, modid);
   do
   {
      naiapp_display_ParamMenuCommands((int8_t*)"MENU_TITLE");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR,
                                           inputBuffer, &inputResponseCnt);
   } while (!bQuit);
   return bQuit;
}

The two command tables define the available operations. The PE command table includes all commands; the SC4 table omits the "Slave" entry:

Menu Key Description Module Support

Master

Set Master Mode

PE, SC4

SLave

Set Slave Mode

PE only

Loopback

Enable/Disable Loopback

PE, SC4

Xmt

Transmit Data

PE, SC4

RCv

Receive Data

PE, SC4

STatus

Display Channel Status

PE, SC4

IntStat

Display Interrupt Status

PE, SC4

CLRStat

Clear Interrupt Status

PE, SC4

REset

Reset Channel

PE, SC4

CLRTx

Clear Tx FIFO

PE, SC4

TXCnt

Get Tx FIFO Count

PE, SC4

RXCnt

Get Rx FIFO Count

PE, SC4

CMd

Display Command Register

PE, SC4

Channel Mode Configuration

This section covers the commands that configure the operating role of an IOCT channel: master mode, slave mode, and loopback mode.

Set Master Mode

To configure an IOCT channel as a bus master in your own application, reset the channel first, then set the transmit enable, receive enable, and channel-on bits in the command register. The CfgForIOCTMaster() utility function in nai_ioct_utils.c demonstrates this sequence:

void CfgForIOCTMaster(int32_t cardIndex, int32_t module, int32_t channel,
                      uint32_t modid)
{
   nai_ioct_cmd_t command = 0;

   ResetIOCTCfg(modid, cardIndex, module, channel);

   /* Enable transmitter and receiver and turn channel on */
   command = IOCT_CMD_TX_ENABLE | IOCT_CMD_RX_ENABLE | IOCT_CMD_CHANNEL_ON;
   check_status(naibrd_IOCT_SetCommand(cardIndex, module, channel, command));
}

The ResetIOCTCfg() utility performs a thorough channel reset before configuration: it issues IOCT_CMD_RESET_CHANNEL, verifies both FIFOs are empty, sets the permitted transmit segment map to all segments (0xFFFF), disables all interrupts, sets interrupts to edge-triggered mode, disables manual SEP mode, and clears all latched interrupt statuses. This ensures the channel starts from a known state.

API parameters:

  • cardIndex, module, channel — identify the target IOCT channel.

  • command — a bitmask of IOCT_CMD_* flags written via naibrd_IOCT_SetCommand(). For master mode, combine IOCT_CMD_TX_ENABLE | IOCT_CMD_RX_ENABLE | IOCT_CMD_CHANNEL_ON.

Set Slave Mode (PE Only)

To configure a PE channel as a bus slave, the procedure is identical to master mode except that the IOCT_CMD_SLAVE_MODE bit is also set. The SC4 module does not support slave mode — the command is not available in the SC4 menu.

void CfgForIOCTSlave(int32_t cardIndex, int32_t module, int32_t channel,
                     uint32_t modid)
{
   nai_ioct_cmd_t command = 0;

   ResetIOCTCfg(modid, cardIndex, module, channel);

   /* Enable slave mode, transmitter, receiver, and turn channel on */
   command = IOCT_CMD_SLAVE_MODE | IOCT_CMD_TX_ENABLE | IOCT_CMD_RX_ENABLE
           | IOCT_CMD_CHANNEL_ON;
   check_status(naibrd_IOCT_SetCommand(cardIndex, module, channel, command));
}

In slave mode, the channel waits for SEP timing from the bus master rather than generating it locally. The slave transmits only during its permitted transmit segments.

Set Loopback Mode

To enable internal loopback on an IOCT channel — allowing you to transmit and receive data without external cabling — set the IOCT_CMD_LOOPBACK and IOCT_CMD_RX_ALWAYS bits. The CfgForIOCTLoopback() utility reads the current command register, applies or clears the loopback bits, and writes the updated value back:

check_status(naibrd_IOCT_GetCommand(cardIndex, module, channel, &command));
if (loopbackEnabled)
{
   /* When in loopback, Rx Always must be set */
   command |= (IOCT_CMD_LOOPBACK | IOCT_CMD_RX_ALWAYS);
}
else
   command &= ~(IOCT_CMD_LOOPBACK | IOCT_CMD_RX_ALWAYS);
check_status(naibrd_IOCT_SetCommand(cardIndex, module, channel, command));

Loopback mode is useful for verifying your transmit and receive logic before connecting to external hardware. When enabling loopback, the IOCT_CMD_RX_ALWAYS bit must also be set so the receiver accepts data without an external clock source.

Important

Common Errors

  • NAI_ERROR_NOT_SUPPORTED — you attempted to set slave mode on an SC4 module. The SC4 hardware does not support slave operation.

  • Channel appears unresponsive after configuration — ensure IOCT_CMD_CHANNEL_ON is set. Without this bit (PE) or IOCT_CMD_STANDBY_MODE_OFF (SC4), the channel’s transceivers remain disabled.

  • Loopback receive returns no data — verify that IOCT_CMD_RX_ALWAYS is set alongside IOCT_CMD_LOOPBACK. Without it, the receiver waits for an external SEP signal that will never arrive in loopback.

Data Transmission and Reception

This section covers the FIFO-based data path: loading transmit data, initiating transmission, and reading received data.

Transmit Data

To transmit data from an IOCT channel, load the data into the Tx FIFO with naibrd_IOCT_SetTxFIFOData(), then trigger transmission with naibrd_IOCT_StartTransmit(). The IOCTXmit() utility function demonstrates the full sequence:

void IOCTXmit(int32_t cardIndex, int32_t module, int32_t channel, int32_t datacnt)
{
   uint32_t txcount, datawritten;
   int32_t retry = 0;

   /* Load data to be transmitted */
   check_status(naibrd_IOCT_SetTxFIFOData(cardIndex, module, channel, datacnt,
                                           ioct_data, &datawritten));
   if ((int32_t)datawritten != datacnt)
   {
      printf("ERROR: Only %d elements written instead of %d\n",
             datawritten, datacnt);
      return;
   }

   /* Get the number of elements in the TX FIFO */
   check_status(naibrd_IOCT_GetFIFOCount(cardIndex, module, channel,
                                          NAI_IOCT_TX_FIFO, &txcount));

   /* Initiate Transmission */
   check_status(naibrd_IOCT_StartTransmit(cardIndex, module, channel));

   /* Wait for all the elements to be sent out */
   while ((txcount != 0) && retry < 10)
   {
      nai_msDelay(100);
      check_status(naibrd_IOCT_GetFIFOCount(cardIndex, module, channel,
                                             NAI_IOCT_TX_FIFO, &txcount));
      retry++;
   }
}

API parameters:

  • naibrd_IOCT_SetTxFIFOData() — count is the number of 32-bit words to load; data[] is the source array; outwrite returns the number of words actually written.

  • naibrd_IOCT_StartTransmit() — triggers the hardware to begin clocking data out of the Tx FIFO.

  • naibrd_IOCT_GetFIFOCount() — pass NAI_IOCT_TX_FIFO to monitor transmit progress.

The InitializeDataForIOCTXmit() utility prepares the transmit buffer. It generates either a fixed decrementing pattern or random data, then applies the IOCT_SPBITS_MASK to clear reserved protocol bits. It sets the IOCT_CONTROL_MASK bit on the first word (marking it as a control word) and the IOCT_EOB_MASK bit on the last word (marking End-of-Block). The maximum buffer size is MAX_IOCT_DATA_ELEMENTS (100 words). Consult your module’s manual for the actual FIFO depth on your hardware.

Receive Data

To read data received on an IOCT channel, first check the Rx FIFO count with naibrd_IOCT_GetFIFOCount(), then retrieve the data with naibrd_IOCT_GetRxFIFOData(). The IOCTRecv() utility reads the FIFO in chunks:

void IOCTRecv(int32_t cardIndex, int32_t module, int32_t channel)
{
   uint32_t rxcount;
   uint32_t dataleft, totaldataread, dataread;
   uint32_t data[MAX_IOCT_DATA_ELEMENTS];

   /* Get the number of elements in the RX FIFO */
   check_status(naibrd_IOCT_GetFIFOCount(cardIndex, module, channel,
                                          NAI_IOCT_RX_FIFO, &rxcount));

   /* Read elements from the RX FIFO */
   dataleft = rxcount;
   totaldataread = 0;
   while (dataleft != 0)
   {
      if (dataleft > MAX_IOCT_DATA_ELEMENTS)
         check_status(naibrd_IOCT_GetRxFIFOData(cardIndex, module, channel,
                      MAX_IOCT_DATA_ELEMENTS, &data[0], &dataread));
      else
         check_status(naibrd_IOCT_GetRxFIFOData(cardIndex, module, channel,
                      dataleft, &data[0], &dataread));
      dataleft -= dataread;
      totaldataread += dataread;
   }
}

API parameters:

  • naibrd_IOCT_GetRxFIFOData() — count is the maximum number of words to read; outdata[] receives the data; outread returns the number of words actually read. When more data is available than your buffer can hold, read in multiple passes as shown.

Important

Common Errors

  • Tx FIFO write returns fewer words than requested — the FIFO is full. Clear the Tx FIFO or wait for the current transmission to complete before loading more data.

  • Rx FIFO count is zero after transmitting in loopback — verify that both IOCT_CMD_LOOPBACK and IOCT_CMD_RX_ALWAYS are set, and that the channel is in master mode with Tx and Rx enabled.

  • Received data does not match transmitted data — check the IOCT_SPBITS_MASK, IOCT_CONTROL_MASK, and IOCT_EOB_MASK bits. Protocol bits in the data words are set by the hardware and will differ from the raw values you loaded.

  • Transmission does not complete (Tx FIFO count never reaches zero) — ensure the channel is on and in master mode, or that an external master is providing SEP timing if in slave mode.

Status and Diagnostics

This section covers commands for reading channel status, viewing interrupt status, and clearing latched interrupt flags.

Display Channel Status

To read the operational status of an IOCT channel, call naibrd_IOCT_GetStatus(). The DisplayIOCTStatus() utility iterates over all channels and decodes the status register:

nai_ioct_status_t status;
check_status(naibrd_IOCT_GetStatus(cardIndex, module, channel, &status));

The status register contains the following fields:

  • Bit 4 (IOCT_STATUS_LAST_CLK_5_MHZ) — indicates whether the last clock detected was 5 MHz (1) or 1.2 MHz (0).

  • Bits 3:0 (IOCT_STATUS_CURRENT_SEG_NUM) — the current segment number on the bus.

  • Bit 15 (IOCT_STATUS_CH_FAULT_LOCKED) — PE only; indicates the channel is fault-locked.

Display Interrupt Status

To read the interrupt status for an IOCT channel, call naibrd_IOCT_GetInterruptStatus() for each group and status type. The DisplayIOCTInterruptStatus() utility reads both realtime and latched statuses for Group A (transmit-side) and Group B (receive-side):

nai_ioct_group_interrupt_t intstatusA, intstatusB;

/* Realtime status */
check_status(naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel,
             NAI_IOCT_GROUP_A, NAI_IOCT_INTERRUPT_STATUS_REALTIME, &intstatusA));
check_status(naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel,
             NAI_IOCT_GROUP_B, NAI_IOCT_INTERRUPT_STATUS_REALTIME, &intstatusB));

/* Latched status */
check_status(naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel,
             NAI_IOCT_GROUP_A, NAI_IOCT_INTERRUPT_STATUS_LATCHED, &intstatusA));
check_status(naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel,
             NAI_IOCT_GROUP_B, NAI_IOCT_INTERRUPT_STATUS_LATCHED, &intstatusB));

Group A (Tx-side) interrupt flags include: SEP High, SEP Low, Segment 0 Active, EOB Transmitted, Word Transmitted, Tx FIFO Overrun, Tx FIFO Full, and Tx FIFO Empty.

Group B (Rx-side) interrupt flags include: Parity Error, No CLK 100, No SEP, Control Word Received, EOB Received, Word Received, Rx FIFO Overrun, Rx FIFO Full, and Rx FIFO Empty.

Realtime status reflects the current hardware state. Latched status captures events that have occurred since the last clear — use it to detect transient conditions that may no longer be active.

Clear Interrupt Status

To clear latched interrupt flags, the approach differs between PE and SC4 modules. The ClearInterruptStatus() utility handles both:

  • SC4 — call naibrd_IOCT_ClearInterruptStatus() with a bitmask specifying which flags to clear. You can selectively clear individual bits.

  • PE — latched statuses are cleared by reading them. Read the latched status register twice to ensure all latched events are consumed.

/* SC4: selective clear */
check_status(naibrd_IOCT_ClearInterruptStatus(cardIndex, module, channel,
             grouptype, clrintstatus));

/* PE: clear-on-read (read twice to catch newly latched events) */
check_status(naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel,
             grouptype, NAI_IOCT_INTERRUPT_STATUS_LATCHED, &latched));
check_status(naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel,
             grouptype, NAI_IOCT_INTERRUPT_STATUS_LATCHED, &latched));

The QueryForIntStatusClr() utility prompts the user for a channel number and, on SC4, a hex bitmask of bits to clear. On PE modules, all latched statuses are cleared at once.

Display Command Register

To view the current command register configuration for all channels, call naibrd_IOCT_GetCommand() for each channel. The DisplayIOCTConfigurations() utility decodes the individual command bits into a tabular display showing the state of each flag: Manual SEP, 1.2 MHz Clock, Ignore Tx Flow Control, Delay Tx, Inhibit Rx Ready, Omit Tx Parity, Rx Always, No RS485 Termination, Loopback, Tx Enable, Rx Enable, Slave Mode, and Channel On.

nai_ioct_cmd_t command;
check_status(naibrd_IOCT_GetCommand(cardIndex, module, channel, &command));
Important

Common Errors

  • Interrupt status shows unexpected flags after reset — after a channel reset, TX_FIFO_EMPTY and RX_FIFO_EMPTY are expected to be set (the FIFOs are empty). SEP-related flags (SEP_HIGH, SEP_LOW, SEGMENT0_ACTIVE) may be in either state depending on external bus conditions.

  • PE latched status does not clear — PE modules use clear-on-read. You must read the latched status register to clear it. If new events occur between reads, a second read is needed.

  • SC4 clear has no effect — verify you are writing a 1 to the bits you want to clear, not a 0. Only bits with a 1 in the clear mask are affected.

FIFO Management and Channel Reset

This section covers commands for managing the transmit and receive FIFOs and resetting channels.

Get Tx FIFO Count

To check how many elements are queued in the transmit FIFO, call naibrd_IOCT_GetFIFOCount() with NAI_IOCT_TX_FIFO:

uint32_t fifocount;
check_status(naibrd_IOCT_GetFIFOCount(cardIndex, module, channel,
                                       NAI_IOCT_TX_FIFO, &fifocount));

Get Rx FIFO Count

To check how many elements are available in the receive FIFO, call naibrd_IOCT_GetFIFOCount() with NAI_IOCT_RX_FIFO:

uint32_t fifocount;
check_status(naibrd_IOCT_GetFIFOCount(cardIndex, module, channel,
                                       NAI_IOCT_RX_FIFO, &fifocount));

Clear Tx FIFO

To discard all data in the transmit FIFO without resetting the entire channel, read the current command register and set the IOCT_CMD_CLEAR_TX_FIFO bit:

nai_ioct_cmd_t command = 0;
check_status(naibrd_IOCT_GetCommand(cardIndex, module, channel, &command));
command |= IOCT_CMD_CLEAR_TX_FIFO;
check_status(naibrd_IOCT_SetCommand(cardIndex, module, channel, command));

This preserves all other channel settings (mode, enables, loopback) while clearing only the Tx FIFO contents.

Reset Channel

To perform a full channel reset — clearing both Tx and Rx FIFOs and any partially received or transmitted data — read the current command register and set the IOCT_CMD_RESET_CHANNEL bit:

nai_ioct_cmd_t command = 0;
check_status(naibrd_IOCT_GetCommand(cardIndex, module, channel, &command));
command |= IOCT_CMD_RESET_CHANNEL;
check_status(naibrd_IOCT_SetCommand(cardIndex, module, channel, command));

After a reset, you will need to reconfigure the channel (master/slave mode, enables, etc.) before resuming operation.

Important

Common Errors

  • FIFO count is non-zero after reset — allow a brief delay (the sample uses nai_msDelay(2)) after issuing the reset command before checking FIFO counts. The hardware needs time to complete the reset.

  • Channel stops working after Clear Tx FIFO — the IOCT_CMD_CLEAR_TX_FIFO bit is self-clearing on some modules but may persist on others. Read back the command register and verify the bit has cleared before loading new data.

Troubleshooting Reference

The following table summarizes the errors and symptoms covered in the preceding sections. Consult your module’s manual for hardware-specific diagnostics and FPGA revision requirements.

Error / Symptom Possible Causes Suggested Resolution

No board found

Board not powered, cable disconnected, incorrect interface/address in config file.

Verify physical connections and configuration file settings.

Connection timeout

Network misconfiguration, firewall blocking traffic, incorrect bus settings.

Check IP addresses, firewall rules, and PCI/PCIe bus configuration.

NAI_ERROR_NOT_SUPPORTED

Attempted slave mode on SC4, or used a PE-only command on SC4.

Check the module type with naibrd_GetModuleID() and use the appropriate command set.

Channel unresponsive after configuration

IOCT_CMD_CHANNEL_ON (PE) or IOCT_CMD_STANDBY_MODE_OFF (SC4) not set.

Ensure the channel-on/standby-off bit is included in the command register write.

Loopback receive returns no data

IOCT_CMD_RX_ALWAYS not set alongside IOCT_CMD_LOOPBACK.

Set both IOCT_CMD_LOOPBACK and IOCT_CMD_RX_ALWAYS when enabling loopback.

Tx FIFO write returns fewer words than requested

FIFO is full.

Wait for current transmission to complete or clear the Tx FIFO first.

Transmission never completes

Channel not in master mode, or slave mode with no external master providing SEP.

Verify mode configuration. In slave mode, an external master must be active.

Received data does not match transmitted data

Protocol bits (IOCT_CONTROL_MASK, IOCT_EOB_MASK, IOCT_PARITY_BIT) set by hardware.

Mask received data with IOCT_SPBITS_MASK before comparing to transmitted values.

FIFO count non-zero after reset

Reset not yet complete.

Add a brief delay (nai_msDelay(2)) after issuing IOCT_CMD_RESET_CHANNEL.

PE latched interrupt status does not clear

Clear-on-read semantics; new events latched between reads.

Read the latched status register twice to consume all pending events.

SC4 interrupt clear has no effect

Wrote 0 to bits intended for clearing.

Write a 1 to each bit you want to clear in the naibrd_IOCT_ClearInterruptStatus() mask.

Full Source

Full Source — IOCT_BasicOps.c (SSK 1.x)
#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 "functions/naibrd_ioct.h"
#include "advanced/nai_ether_adv.h"

#include "nai_ioct_utils.h"

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

/* Function prototypes */
static bool_t IOCTBasicOpsMenu_run(int32_t cardIndex, int32_t module, uint32_t modid);

/* IOCT Command Functions */
static nai_status_t IOCTBasicOpsMenu_commandCfg(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_setMaster(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_setSlave(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_setLoopback(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_xmit(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_recv(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_status(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_interruptstatus(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_clrinterruptstatus(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_reset(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_clearTxFifo(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_TxFifoCnt(int32_t paramCount, int32_t* p_params);
static nai_status_t IOCTBasicOpsMenu_RxFifoCnt(int32_t paramCount, int32_t* p_params);

/****** Command Table *******/
/* Invariant: enumeration of cmd table starts from 0 and increments by 1 */
enum ioct_BasicOpsMenu_commands
{
   IOCT_BASICOPS_CMD_MASTER,
   IOCT_BASICOPS_CMD_SLAVE,
   IOCT_BASICOPS_CMD_LOOPBACK,
   IOCT_BASICOPS_CMD_XMIT,
   IOCT_BASICOPS_CMD_RECV,
   IOCT_BASICOPS_CMD_STATUS,
   IOCT_BASICOPS_CMD_INTSTATUS,
   IOCT_BASICOPS_CMD_RESET,
   IOCT_BASICOPS_CMD_CLEAR_TX_FIFO,
   IOCT_BASICOPS_CMD_TX_FIFO_CNT,
   IOCT_BASICOPS_CMD_RX_FIFO_CNT,
   IOCT_BASICOPS_CMD_COMMAND_CFG,
   IOCT_BASICOPS_CMD_COUNT
};

naiapp_cmdtbl_params_t IOCT_PE_BasicOpMenuCmds[] = {
   {"Master",     "Set Master Mode",        IOCT_BASICOPS_CMD_MASTER,            IOCTBasicOpsMenu_setMaster},
   {"SLave",      "Set Slave Mode",         IOCT_BASICOPS_CMD_SLAVE,             IOCTBasicOpsMenu_setSlave},
   {"Loopback",   "Loopback Mode",          IOCT_BASICOPS_CMD_LOOPBACK,          IOCTBasicOpsMenu_setLoopback},
   {"Xmt",        "Transmit Data",          IOCT_BASICOPS_CMD_XMIT,              IOCTBasicOpsMenu_xmit},
   {"RCv",        "Receive Data",           IOCT_BASICOPS_CMD_RECV,              IOCTBasicOpsMenu_recv},
   {"STatus",     "IOCT Status",            IOCT_BASICOPS_CMD_STATUS,            IOCTBasicOpsMenu_status},
   {"IntStat",    "Interrupt Status",       IOCT_BASICOPS_CMD_INTSTATUS,         IOCTBasicOpsMenu_interruptstatus},
   {"CLRStat",    "Interrupt Status",       IOCT_BASICOPS_CMD_INTSTATUS,         IOCTBasicOpsMenu_clrinterruptstatus},
   {"REset",      "Reset Channel",          IOCT_BASICOPS_CMD_RESET,             IOCTBasicOpsMenu_reset},
   {"CLRTx",      "Clear Tx Fifo",          IOCT_BASICOPS_CMD_CLEAR_TX_FIFO,     IOCTBasicOpsMenu_clearTxFifo},
   {"TXCnt",      "Tx Fifo Count",          IOCT_BASICOPS_CMD_TX_FIFO_CNT,       IOCTBasicOpsMenu_TxFifoCnt},
   {"RXCnt",      "Rx Fifo Count",          IOCT_BASICOPS_CMD_RX_FIFO_CNT,       IOCTBasicOpsMenu_RxFifoCnt},
   {"CMd",        "Display Command",        IOCT_BASICOPS_CMD_COMMAND_CFG,       IOCTBasicOpsMenu_commandCfg},
};

/* Note, SC4 cannot be configured as a Slave */
naiapp_cmdtbl_params_t IOCT_SC4_BasicOpMenuCmds[] = {
   {"Master",     "Set Master Mode",        IOCT_BASICOPS_CMD_MASTER,            IOCTBasicOpsMenu_setMaster},
   {"Loopback",   "Loopback Mode",          IOCT_BASICOPS_CMD_LOOPBACK,          IOCTBasicOpsMenu_setLoopback},
   {"Xmt",        "Transmit Data",          IOCT_BASICOPS_CMD_XMIT,              IOCTBasicOpsMenu_xmit},
   {"RCv",        "Receive Data",           IOCT_BASICOPS_CMD_RECV,              IOCTBasicOpsMenu_recv},
   {"STatus",     "IOCT Status",            IOCT_BASICOPS_CMD_STATUS,            IOCTBasicOpsMenu_status},
   {"IntStat",    "Interrupt Status",       IOCT_BASICOPS_CMD_INTSTATUS,         IOCTBasicOpsMenu_interruptstatus},
   {"CLRStat",    "Interrupt Status",       IOCT_BASICOPS_CMD_INTSTATUS,         IOCTBasicOpsMenu_clrinterruptstatus},
   {"REset",      "Reset Channel",          IOCT_BASICOPS_CMD_RESET,             IOCTBasicOpsMenu_reset},
   {"CLRTx",      "Clear Tx Fifo",          IOCT_BASICOPS_CMD_CLEAR_TX_FIFO,     IOCTBasicOpsMenu_clearTxFifo},
   {"TXCnt",      "Tx Fifo Count",          IOCT_BASICOPS_CMD_TX_FIFO_CNT,       IOCTBasicOpsMenu_TxFifoCnt},
   {"RXCnt",      "Rx Fifo Count",          IOCT_BASICOPS_CMD_RX_FIFO_CNT,       IOCTBasicOpsMenu_RxFifoCnt},
   {"CMd",        "Display Command",        IOCT_BASICOPS_CMD_COMMAND_CFG,       IOCTBasicOpsMenu_commandCfg},
};

static uint32_t ioct_modid = 0;

/*****************************************************************************/
/**
<summary>
The purpose of the IOCT_BasicOpsMenu is to illustrate the methods to call in the
naibrd library to perform basic operations with the IOCT modules for
configuration setup and reading the channels.

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 IOCT routines.
 - ConfigDevice
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - CheckModule
</summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t IOCT_BasicOpsMenu(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   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)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  IOCTBasicOpsMenu_run(cardIndex, module, moduleID);
               }
            }
         }

         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>
IOCTBasicOpsMenu_run illustrates the channel configuration and prepares the menu
which will handle user command requests. Returns TRUE if the user enters
the Quit Command at any point within its scope.
</summary>
*/
/*****************************************************************************/
static bool_t IOCTBasicOpsMenu_run(int32_t cardIndex, int32_t module, uint32_t modid)
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   /* int32_t MAX_CHANNELS = naibrd_IOCT_GetChannelCount(modid); */

   ioct_modid = modid;
   if (ioct_modid == NAI_MODULE_ID_SC4)
      naiapp_utils_LoadParamMenuCommands(IOCT_BASICOPS_CMD_COUNT, IOCT_SC4_BasicOpMenuCmds);
   else
      naiapp_utils_LoadParamMenuCommands(IOCT_BASICOPS_CMD_COUNT, IOCT_PE_BasicOpMenuCmds);
   DisplayIOCTConfigurations(cardIndex, module, modid);
   do
   {
      naiapp_display_ParamMenuCommands((int8_t*)"MENU_TITLE");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   } while (!bQuit);
   return bQuit;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_commandCfg displays the contents in the command register.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_commandCfg(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   DisplayIOCTConfigurations(cardIndex, module, ioct_modid);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_setMaster calls CfgForMaster to configure IOCT channel for
Master mode.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_setMaster(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   CfgForIOCTMaster(cardIndex, module, channel, ioct_modid);
   DisplayIOCTConfigurations(cardIndex, module, ioct_modid);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_setSlave calls CfgForMaster to configure IOCT channel for
Slave mode.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_setSlave(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   CfgForIOCTSlave(cardIndex, module, channel, ioct_modid);
   DisplayIOCTConfigurations(cardIndex, module, ioct_modid);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_setLoopback calls CfgForIOCTLoopback to query the user on
whether to enable or disable IOCT loopback.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_setLoopback(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   bool_t loopbackEnabled = FALSE;
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   bQuit = CfgForIOCTLoopback(cardIndex, module, channel, &loopbackEnabled);
   if (!bQuit)
   {
      DisplayIOCTConfigurations(cardIndex, module, ioct_modid);
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_xmit handles the user request to transmit data from the IOCT
channel.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_xmit(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   bool_t bGenRandomData = FALSE;
   int32_t datacnt = 0;
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;

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

   bQuit = QueryForIOCTXmitDataCount(&datacnt, &bGenRandomData);
   if (!bQuit)
   {
      InitializeDataForIOCTXmit(datacnt, bGenRandomData);
      IOCTXmit(cardIndex, module, channel, datacnt);
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_recv handles the user request to read the data received on
the IOCT channel.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_recv(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   IOCTRecv(cardIndex, module, channel);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_status handles showing the status information for the IOCT channel.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_status(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   DisplayIOCTStatus(cardIndex, module, ioct_modid);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_interruptstatus handles showing the status information for the IOCT channel.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_interruptstatus(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   DisplayIOCTInterruptStatus(cardIndex, module, ioct_modid);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_clrinterruptstatus handles queries the user on which interrupt
status to clear.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_clrinterruptstatus(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   DisplayIOCTInterruptStatus(cardIndex, module, ioct_modid);
   QueryForIntStatusClr(ioct_modid, cardIndex, module);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_reset calls IOCTResetChannel to reset the IOCT channel.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_reset(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   IOCTResetChannel(cardIndex, module, channel);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_clearTxFifo calls IOCTClearTxFifo to clear the Tx FIFO on
the IOCT channel.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_clearTxFifo(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   IOCTClearTxFifo(cardIndex, module, channel);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_TxFifoCnt retrieves the number of elements in the Tx FIFO on
the IOCT channel.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_TxFifoCnt(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;
   uint32_t fifocount;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   check_status(naibrd_IOCT_GetFIFOCount(cardIndex, module, channel, NAI_IOCT_TX_FIFO, &fifocount));
   printf("Tx FIFO Element Count = %d\n", fifocount);
   return NAI_ERROR_UNKNOWN;
}

/*****************************************************************************/
/**
<summary>
IOCTBasicOpsMenu_RxFifoCnt retrieves the number of elements in the Rx FIFO on
the IOCT channel.
</summary>
*/
/*****************************************************************************/
static nai_status_t IOCTBasicOpsMenu_RxFifoCnt(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ioct_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ioct_params->cardIndex;
   int32_t module = p_ioct_params->module;
   int32_t channel = p_ioct_params->channel;
   uint32_t fifocount;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   check_status(naibrd_IOCT_GetFIFOCount(cardIndex, module, channel, NAI_IOCT_RX_FIFO, &fifocount));
   printf("Rx FIFO Element Count = %d\n", fifocount);
   return NAI_ERROR_UNKNOWN;
}

Help Bot

X