SER BIT
Edit this on GitLab
SER BIT Sample Application (SSK 1.x)
Overview
The SER BIT sample application demonstrates how to run the built-in test (BIT) on a serial channel using the NAI SSK 1.x library. BIT verifies the internal loopback path of a serial channel by exercising the transmit-to-receive circuitry inside the module without requiring any external wiring or equipment. This sample serves as a practical API reference for incorporating serial BIT into your own application.
This is a short, focused sample (137 lines) that covers a single operation: initiate BIT on a selected channel and report the result.
This sample is designed to work with the following serial module types:
-
SC3 — Gen 2 Serial (paired-channel architecture)
-
CMH — Combination module with serial functionality
-
Any other serial module supported by
naibrd_SER_InitiateBIT()
Consult your module’s manual for BIT-specific behavior and supported FPGA revisions.
Prerequisites
-
NAI board with a supported serial module installed
-
SSK 1.x built and ready to run (see First Time Setup Guide)
-
No external wiring required — BIT uses the module’s internal loopback path
How to Run
Launch the compiled SER_BIT executable. The board connection menu appears on first run. After connecting, select the card index, module number, and channel number when prompted. The application disables the channel, runs BIT, reports pass or fail, and restores the channel to its original state. Press Enter to run BIT again on the same channel or type Q to exit.
Board Connection and Module Selection
This startup sequence is common to all NAI sample applications. The board connection and module selection code shown here is not specific to serial modules. For details on board connection configuration, see the First Time Setup Guide.
On launch, main() calls naiapp_RunBoardMenu() with the configuration file name default_SER_BIT.txt. This file does not ship with the SSK. It is created automatically when you save your connection settings from the board menu. On the first run the board menu always appears and prompts you for connection parameters (IP address, bus type, etc.). On subsequent runs the menu is skipped if the saved configuration file exists.
After the board connection is established, the application queries you for the card index and module number, retrieves the module ID, and passes all three to Run_SER_BIT().
static const int8_t *CONFIG_FILE = (const int8_t *)"default_SER_BIT.txt";
/* ... */
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))
{
Run_SER_BIT(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);
}
}
After Run_SER_BIT() returns, you can press Enter to select a different card/module or type Q to exit. The application calls naiapp_access_CloseAllOpenCards() before terminating.
|
Important
|
Common Connection Errors
|
Program Structure
Entry Point
The application uses main() on standard platforms and SER_BIT_Sample() on VxWorks, following the standard SSK pattern:
#if defined (__VXWORKS__)
int32_t SER_BIT_Sample(void)
#else
int32_t main(void)
#endif
Application Flow
The program has a simple linear structure — no menu system or command table. After board connection and channel selection, it enters a loop that runs BIT on the selected channel until you quit. The menu system is a sample convenience — in your own code, call the BIT API functions directly.
Running the Built-In Test
The Run_SER_BIT() function performs the complete BIT sequence: query the channel, save the channel state, disable the channel (and its pair if needed), initiate BIT, check the result, and restore the channel state.
Channel Selection
To determine how many channels your serial module supports, call naibrd_SER_GetChannelCount() with the module ID. The application then prompts you for a channel number.
channelCount = naibrd_SER_GetChannelCount(moduleID);
check_status(naiapp_query_ChannelNumber(channelCount, 1, &chanNum));
In your own application, pass the module ID (not the module number) to naibrd_SER_GetChannelCount(). The channel number is one-based.
Saving and Disabling the Channel
BIT requires the target channel to be disabled before it can run. The application saves the current enable state so it can restore it after the test completes. To read and set the channel enable state in your own application, call naibrd_SER_GetChannelEnable() and naibrd_SER_SetChannelEnable():
/* Get the state of the channel before BIT is executed. */
check_status(naibrd_SER_GetChannelEnable(cardIndex, module, chanNum, &enable));
/* Disable the channel. Channels MUST be disabled for BIT to run. */
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, chanNum, 0));
-
cardIndex— Zero-based logical card index from the board connection step. -
module— One-based module slot number. -
chanNum— One-based channel number. -
enable— Receives the current enable state (0 = disabled, non-zero = enabled).
Disabling the Paired Channel (SC3 and CMH)
On the SC3 module, serial channels are implemented in pairs (1 and 2, 3 and 4, etc.). Both channels in a pair must be disabled for BIT to run on either one. The CMH module has the same pairing requirement, except for channel 5, which has no pair.
To disable the paired channel in your own application, determine whether the target channel is even or odd and disable its partner accordingly:
/* For BIT to run on the SC3 we need to make sure the channels are
disabled in pairs (1 & 2, 3 & 4, etc.) */
/* The CMH Module only has five channels, so no need to disable its pair. */
if ((moduleID == NAI_MODULE_ID_SC3) || (moduleID == NAI_MODULE_ID_CMH) && (chanNum != 5))
{
if ((chanNum % 2) == 0) /* Even channel */
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, (chanNum - 1), 0));
else
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, (chanNum + 1), 0));
}
If you are running BIT on an SC3 or CMH channel in your own code, you must also save and restore the paired channel’s enable state to avoid disrupting its operation. The sample does not explicitly restore the partner channel — in a production application, save both channels' states before disabling them.
Initiating BIT and Checking Results
To run the built-in test, call naibrd_SER_InitiateBIT(). The NAI_SER_INITIATE_BIT_WAIT_RESULT flag tells the function to block until the test completes and return the result directly:
/* Initiate BIT and wait for results */
status = naibrd_SER_InitiateBIT(cardIndex, module, chanNum,
NAI_SER_INITIATE_BIT_WAIT_RESULT);
if (NAI_SUCCESS == status)
printf("BIT Passed.\n");
else
check_status(status);
-
cardIndex— Zero-based logical card index. -
module— One-based module slot number. -
chanNum— One-based channel number. -
NAI_SER_INITIATE_BIT_WAIT_RESULT— Synchronous mode; the call blocks until BIT completes.
A return value of NAI_SUCCESS means the internal loopback test passed. Any other status indicates a failure — check_status() prints the error code and description.
Restoring the Channel State
After BIT completes, the application restores the channel to its original enable state:
/* Restore the channel's original state. */
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, chanNum, enable));
This ensures that running BIT does not leave the channel disabled if it was previously active.
|
Important
|
Common Errors
|
Troubleshooting Reference
The following table summarizes errors and symptoms you may encounter when running the SER BIT sample. Consult your module’s manual for hardware-specific diagnostics and BIT failure registers.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found |
Board is powered off; incorrect IP address or bus configuration. |
Verify power and connection parameters. Re-run the board menu to update settings. |
Connection timeout |
Network issue (Ethernet) or missing bus driver (PCI/cPCI). |
Check cabling and network configuration. Ensure the correct bus driver is loaded. |
|
Selected slot is empty or contains an unrecognized module. |
Verify the module is seated in the correct slot and that the SSK supports the module type. |
BIT fails (non- |
Internal loopback path fault; channel or paired channel not disabled; hardware defect. |
Ensure the channel and its pair (SC3/CMH) are disabled before running BIT. If the error persists, consult the module manual for BIT diagnostic registers. |
|
Module or FPGA revision does not support |
Verify the module type is supported and update the FPGA firmware if necessary. |
BIT passes but channel does not work afterward |
Channel enable state was not restored after BIT. |
Always call |
Full Source
Full Source — SER_BIT.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_ser.h"
#include "advanced/nai_ether_adv.h"
static const int8_t *CONFIG_FILE = (const int8_t *)"default_SER_BIT.txt";
/* Function prototypes */
void Run_SER_BIT(int32_t cardIndex, int32_t module, uint32_t moduleID);
/**************************************************************************************************************/
/** \defgroup SERBIT Serial Built-In-Test
The purpose of the Serial built-in-test sample application is to illustrate the methods to call in the
naibrd library to run the built-in-test on the serial module.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SER_BIT_Sample(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))
{
Run_SER_BIT(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;
}
/**************************************************************************************************************/
/** \ingroup SERBIT
Configures a serial module, runs a built-in-test and checks the results.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param module (Input) Module Number of the module to access (1 - [max modules for board]).
\param moduleID (Input) The ID of the module.
*/
/**************************************************************************************************************/
void Run_SER_BIT(int32_t cardIndex, int32_t module, uint32_t moduleID)
{
int32_t chanNum, channelCount;
bool_t bQuit = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
channelCount = naibrd_SER_GetChannelCount(moduleID);
check_status(naiapp_query_ChannelNumber(channelCount, 1, &chanNum));
printf("\nSerial Channel # %d\n", chanNum);
do
{
bool_t enable = 0;
nai_status_t status;
/* Get the state of the channel before BIT is executed.*/
check_status(naibrd_SER_GetChannelEnable(cardIndex, module, chanNum, &enable));
/* Disable the channel. Channels MUST be disabled for BIT to run. */
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, chanNum, 0));
/* For BIT to run on the SC3 we need to make sure the channels are disabled in pairs (1 & 2, 2 & 3 etc.) */
/* The CMH Module only has five channels, so no need to disable its pair. */
if ((moduleID == NAI_MODULE_ID_SC3) || (moduleID == NAI_MODULE_ID_CMH) && (chanNum != 5))
{
if ((chanNum % 2) == 0) /* Even channel */
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, (chanNum - 1), 0));
else
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, (chanNum + 1), 0));
}
/* Initiate BIT and wait for results */
status = naibrd_SER_InitiateBIT(cardIndex, module, chanNum, NAI_SER_INITIATE_BIT_WAIT_RESULT);
if (NAI_SUCCESS == status)
printf("BIT Passed.\n");
else
check_status(status);
/* Restore the channel's original state. */
check_status(naibrd_SER_SetChannelEnable(cardIndex, module, chanNum, enable));
printf("Press ENTER to run BIT again, or '%c' to exit program : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
} while (TRUE != bQuit);
return;
}