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

SER Async Recv

SER Async Recv Sample Application (SSK 2.x)

Overview

The SER Async Recv sample application demonstrates how to configure a serial channel for asynchronous reception using the NAI Software Support Kit (SSK 2.x). The application configures a channel for async mode with an RS-422 interface and continuously reads data from the receive FIFO. It is designed to work as the receiving half of a two-application pair — run the SER Async Xmit sample on a separate channel to transmit data that this application will receive.

This sample supports SER module types including SC1-SC7 and newer SER variants. The receive channel is hard-coded to channel 2, matching the transmit channel of the companion application (hard-coded to channel 1). A physical RS-422 connection between channels 1 and 2 is required.

For the SSK 1.x version, see SER ASync Rx (SSK 1.x).

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a SER module installed (SC1-SC7 or newer SER variant).

  • SSK 2.x installed on your development host.

  • The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.

  • A physical RS-422 cable connecting channel 1 to channel 2 on the SER module.

  • The SER Async Xmit sample running on the same board to provide data.

How to Run

Launch the ser_async_recv executable from your build output directory. On startup the application looks for a configuration file (default_SerAsync_Rx.txt). On the first run, this file will not exist — the application will present an interactive board menu. Once connected, the application immediately configures channel 2 for RS-422 async reception and enters a read loop.

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

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

  1. Call naiapp_RunBoardMenu() to load a saved configuration file or present the interactive board menu.

  2. Query the user for a card index and module slot.

  3. Retrieve the module ID with naibrd_GetModuleName().

  4. Call Run_SER_ASync_Rx(cardIndex, module) to configure channel 2 and begin receiving.

#ifdef __VXWORKS__
int32_t SER_ASync_Rx_Sample(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = NAI_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) == NAI_TRUE)
   {
      while (stop != NAI_TRUE)
      {
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != NAI_TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != NAI_TRUE)
            {
               check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
               if ((moduleID != 0))
               {
                  Run_SER_ASync_Rx(cardIndex, module);
               }
            }
         }

         naiif_printf("\r\nType Q to quit or Enter key to restart application:\r\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   naiif_printf("\r\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.

  • Connection timeout — confirm network settings or bus configuration.

  • Module not present at selected slot — verify which slots are populated using the board menu.

Program Structure

Entry Point

The entry point is main() on most platforms, or SER_ASync_Rx_Sample() on VxWorks.

Application Flow

  1. Reset channel 2 and clear both FIFOs.

  2. Configure channel 2 for async RS-422 reception (9600 baud, 8N1, no parity, receiver enabled).

  3. Wait for the user to press Enter.

  4. Enter a receive loop that reads and displays data until the user quits.

Channel Configuration

The application hard-codes the receive channel to channel 2 and configures it for async RS-422:

chanNum = 2;

naibrd_SER_ChannelReset(cardIndex, module, chanNum);
naibrd_SER_ClearRxFifo(cardIndex, module, chanNum);
naibrd_SER_ClearTxFifo(cardIndex, module, chanNum);

check_status(naibrd_SER_SetCommProtocol(cardIndex, module, chanNum, NAIBRD_SER_PROTOCOL_ASYNC));
check_status(naibrd_SER_SetInterface(cardIndex, module, chanNum, NAIBRD_SER_INTF_RS422));
check_status(naibrd_SER_SetParityType(cardIndex, module, chanNum, NAIBRD_SER_PARITY_NONE));
check_status(naibrd_SER_SetNumDataBits(cardIndex, module, chanNum, NAIBRD_SER_DATA_BITS_8));
check_status(naibrd_SER_SetNumStopBits(cardIndex, module, chanNum, NAIBRD_SER_STOP_BITS_1));
check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600));
check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1));

Note that the interface is set to NAIBRD_SER_INTF_RS422 (not loopback) because this application expects data from an external source (the companion transmit application running on channel 1).

Data Reception Loop

After a 100 ms configuration settling delay, the application enters a loop that reads from the receive FIFO each time the user presses Enter:

do
{
   naibrd_SER_GetRxBufferCnt(cardIndex, module, chanNum, (uint32_t*)&numWordsToRead);
   naiif_printf("\r\nReading back %d words ...", numWordsToRead);

   check_status(naibrd_SER_ReceiveBufferWithTimeOut32(cardIndex, module, chanNum, RecvDataBuffer, MAX_DATA_RX, numWordsToRead, NAIBRD_FIFO_TIMEOUT_NONE,
      &numWordsToRead));
   naiif_printf(" %d words read\r\n", numWordsToRead);

   for (i = 0; i < numWordsToRead; i++)
   {
      naiif_printf("Recd 0x%02X, Status= 0x%02X\r\n", (RecvDataBuffer[i] & 0x00FF), (RecvDataBuffer[i] >> 8) & 0x00FF);
   }
   naiif_printf("Press ENTER to receive again, or '%c' to exit program : ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

} while ( NAI_TRUE != bQuit );

Each received word contains the data byte in the lower 8 bits and a per-word status byte in the upper 8 bits. A status of 0x00 indicates no errors.

Troubleshooting Reference

Error / Symptom Possible Causes Suggested Resolution

No board found or connection timeout

Board not powered, incorrect configuration file, network issue

Verify hardware is powered and connected.

No data received (count is zero)

Transmit application not running, cable not connected, baud rate mismatch

Ensure the SER Async Xmit sample is running on channel 1. Verify RS-422 cable between channels 1 and 2. Confirm both channels use 9600 baud.

Status byte indicates error

Parity or framing error, baud rate mismatch between TX and RX

Verify both the transmit and receive channels use identical async parameters (baud rate, parity, data bits, stop bits).

Partial data received

Data not fully transmitted yet, FIFO read before all data arrived

Press Enter again to read any remaining data. Increase the delay before reading.

Module not present at selected slot

No SER module installed at the specified slot

Verify hardware configuration.

Receiver not enabled error

naibrd_SER_SetReceiverEnable() not called or failed

Check the return status of the receiver enable call.

Full Source

The complete source for this sample is provided below for reference.

Full Source — ser_async_recv.c (SSK 2.x)
/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"

/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_ser.h"

/* naiif include files */
#include "nai_libs/naiif/include/naiif_stdio.h"

/* Common Sample Program include files */
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_menu.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_query.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_access.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_display.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_utils.h"

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

/* Function prototypes */
void Run_SER_ASync_Rx(int32_t cardIndex, int32_t module);

#define MAX_DATA_RX  100              /* Maximum number words to receive in one fifo read */

/**************************************************************************************************************/
/** \defgroup SERAsyncRx

\brief This sample application demonstrates how to configure and use a serial channel for asynchronous receiving.

The Serial Asynchronous Receive sample application illustrates the methods to call in the naibrd library to configure a given serial channel
for receiving RS422. The \ref SERAsyncTx application can be run in unison with this application to transmit data.

\note A physical RS-422 connection between channel 1 and channel 2 is required for data transmission.

The main steps include:
- Querying the user for the card index and module number.
- Configuring the serial channel for asynchronous communication with RS422.
- Receiving data through the serial channel.
- Displaying the received data.
*/
/**************************************************************************************************************/
#ifdef __VXWORKS__
int32_t SER_ASync_Rx_Sample(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = NAI_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) == NAI_TRUE)
   {
      while (stop != NAI_TRUE)
      {
         /* Query user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != NAI_TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != NAI_TRUE)
            {
               check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
               if ((moduleID != 0))
               {
                  Run_SER_ASync_Rx(cardIndex, module);
               }
            }
         }

         naiif_printf("\r\nType Q to quit or Enter key to restart application:\r\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   naiif_printf("\r\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();
   return 0;
}

/**************************************************************************************************************/
/** \ingroup SERAsyncRx
Configures a serial module for asynchronous receiving. The receiving channel is hard-coded to channel #2.
\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]).
*/
/**************************************************************************************************************/
void Run_SER_ASync_Rx(int32_t cardIndex, int32_t module)
{
   int32_t i;
   int32_t chanNum;
   int32_t numWordsToRead;
   uint32_t RecvDataBuffer[MAX_DATA_RX];
   bool_t bQuit = NAI_FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   /* channelCount = naibrd_SER_GetChannelCount(moduleID); */
   /* naiapp_query_ChannelNumber(channelCount, 1, &chanNum); */
   /* Hard Code channel to ch 2 */
   chanNum = 2;

   naibrd_SER_ChannelReset(cardIndex, module, chanNum);
   naibrd_SER_ClearRxFifo(cardIndex, module, chanNum);
   naibrd_SER_ClearTxFifo(cardIndex, module, chanNum);

   naiif_printf ("\r\nSerial Channel # %d\r\n", chanNum);

   /* Configure for ASync on the channel selected. */
   check_status(naibrd_SER_SetCommProtocol(cardIndex, module, chanNum, NAIBRD_SER_PROTOCOL_ASYNC));   /* Async mode  */
   check_status(naibrd_SER_SetInterface(cardIndex, module, chanNum, NAIBRD_SER_INTF_RS422));          /* RS422       */
   check_status(naibrd_SER_SetParityType(cardIndex, module, chanNum, NAIBRD_SER_PARITY_NONE));        /* No Parity   */
   check_status(naibrd_SER_SetNumDataBits(cardIndex, module, chanNum, NAIBRD_SER_DATA_BITS_8));       /* 8 Data Bits */
   check_status(naibrd_SER_SetNumStopBits(cardIndex, module, chanNum, NAIBRD_SER_STOP_BITS_1));       /* 1 Stop Bits */
   check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600));                            /* 9600 baud   */
   check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1));                         /* Enable the Receiver */

   /* Wait for configuration to be ready */
   naibrd_msDelay(100);

   naiif_printf ("Please press Enter to read back data...");
   while (naiapp_query_ForQuitResponse(sizeof(inputBuffer), 0x0A, inputBuffer, &inputResponseCnt));

   /* Receive data */
   do
   {
      /* Check how many words we have waiting in the RX buffer */
      naibrd_SER_GetRxBufferCnt(cardIndex, module, chanNum, (uint32_t*)&numWordsToRead);
      naiif_printf ("\r\nReading back %d words ...", numWordsToRead);

      /* Read data stored in RX buffer */
      check_status(naibrd_SER_ReceiveBufferWithTimeOut32(cardIndex, module, chanNum, RecvDataBuffer, MAX_DATA_RX, numWordsToRead, NAIBRD_FIFO_TIMEOUT_NONE,
         &numWordsToRead));
      naiif_printf (" %d words read\r\n", numWordsToRead);

      /* Print buffer contents - First 8 bits are for data, last 8 bits are status */
      for (i = 0; i < numWordsToRead; i++)
      {
         naiif_printf("Recd 0x%02X, Status= 0x%02X\r\n", (RecvDataBuffer[i] & 0x00FF), (RecvDataBuffer[i] >> 8) & 0x00FF);
      }
      naiif_printf("Press ENTER to receive again, or '%c' to exit program : ", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

   } while ( NAI_TRUE != bQuit );

   return;
}

Help Bot

X