SER Async Recv
Edit this on GitLab
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:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file or present the interactive board menu. -
Query the user for a card index and module slot.
-
Retrieve the module ID with
naibrd_GetModuleName(). -
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:
|
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 |
|
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;
}