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 LOOPBACK

SER ASync LOOPBACK

Explanation

About the Serial Loopback - Asynchronous Sample Code

This sample application is provided by North Atlantic Industries (NAI) for use with their Serial Loopback Asynchronous configuration. The purpose of this application is to interact with NAI’s embedded function modules, specifically configuring a serial channel for loopback transmission, where data sent on a channel is looped back and received on the same channel.

File Inclusions and Definitions

The application includes several headers essential for its functionality: - Standard libraries: stdio.h, stdlib.h, string.h, time.h, ctype.h. - Common Sample Program headers: For accessing and querying board configurations such as "naiapp_boardaccess_menu.h", "naiapp_boardaccess_query.h", "naiapp_boardaccess_access.h", "naiapp_boardaccess_display.h", and "naiapp_boardaccess_utils.h". - NAI Board: For accessing NAI specific board functions, "nai.h" and "naibrd.h". - Serial function handling: "naibrd_ser.h". - Advanced ethernet functions: "nai_ether_adv.h".

The static constant CONFIG_FILE points to a configuration file named "default_SerAsync_LOOPBACK.txt".

Function Prototypes

The Run_SER_ASYNC function is declared as a prototype and it will later be defined to handle the actual loopback transmission on a specific serial module.

Main Function and Loopback Process

Main Function Overview

The main function serves as the entry point to the application: 1. It starts by declaring several variables that will control the flow of the program. 2. If naiapp_RunBoardMenu with the configuration file succeeds, it enters a loop where it: - Queries the user for a card index. - Fetches the module count for the selected card. - Queries the user for a module number. - Fetches the module ID and calls Run_SER_ASYNC with the provided card index, module number, and module ID. - Prompts the user to either restart the application or quit. 3. Once the user quits, it cleans up by closing all open card connections.

Run_SER_ASYNC Function

The Run_SER_ASYNC function sets up and performs the loopback test on the specified serial module: 1. Configuration: - It queries for the number of channels available and the specific channel number to use. - Clears the receive and transmit FIFOs on the serial channel using repeated attempts until a timeout is reached. - Configures the channel for asynchronous mode, sets the interface level to loopback, adjusts parity, data bits, stop bits, baud rate, and enables transmission and reception. 2. Data Preparation and Transmission: - Prepares an array of incremental data to be sent. - Transmits the data to the configured serial channel. 3. Data Reception and Display: - Reads back the data from the channel. - Displays the sent and received data values for verification.

Detailed Code Walkthrough

main Function

#if defined (__VXWORKS__)
int32_t SER_ASYNC_Sample(void)
#else
int32_t main(void)
#endif

This section shows the main entry point, conditional on the OS environment.

Run Board Menu

if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)

Initializes the board using the provided configuration file.

Loop Structure

while (stop != TRUE)

Main loop where card index and module number are queried and loopback configuration is initiated.

Querying User Inputs

stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);

Queries the user to enter a card index.

Module Count and ID Fetch

check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

Gets the count of modules on the card and fetches the module ID for configuration.

Run_SER_ASYNC Function

void Run_SER_ASYNC(int32_t cardIndex, int32_t module, uint32_t moduleID)

Configures and tests the asynchronous serial loopback on the specified module.

Channel Configuration

int32_t channelCount = naibrd_SER_GetChannelCount(moduleID);

Fetches the number of channels available for the module.

Clearing FIFOs

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

Clears the receive and transmit FIFOs before starting transmission.

Setting Protocol and Parameters

check_status(naibrd_SER_SetProtocol(cardIndex, module, chanNum, NAI_SER_PROTOCOL_ASYNC));
// Other settings: Loopback, no parity, 8 data bits, 1 stop bit, baud rate.

Sets various parameters for the serial channel.

Data Transmission and Reception

naibrd_SER_TransmitBuffer(cardIndex, module, chanNum, sizeof(SendData[0]), SendData, nNumWordsSend, (uint32_t*)&nNumWordsSend);
naibrd_SER_ReceiveBuffer32(cardIndex, module, chanNum, RecvDataStatus, nNumWordsSend, (uint32_t*)&nNumWordsRecv);

Transmits and receives data to verify loopback operation.

Conclusion

This code demonstrates the use of NAI’s Board Access Library for configuring and testing serial communication modules in loopback mode, specifically asynchronous serial communication. This involves querying user inputs, setting up the correct serial communication parameters, transmitting data, and verifying the loopback by receiving the same data.

#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_SerAsync_LOOPBACK.txt";

/* Function prototypes */
void Run_SER_ASYNC(int32_t cardIndex, int32_t module, uint32_t moduleID);

#define NUM_DATA_TX  8
#define MAX_DATA_RX  20
#define CLEAR_FIFO_TIMEOUT 1000  /* 1 second */

/**************************************************************************************************************/
/** \defgroup SERLoopbackAsync Serial Loopback - Asynchronous
The purpose of the Serial Loopback Asynchronous Sample Application is to illustrate the methods to call in the
naibrd library to configure a given serial channel for loopback transmission. The application will write data to
the selected serial channel's transmit buffer, transmit it via an internal loopback, and receive and print the
data.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SER_ASYNC_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 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);
               Run_SER_ASYNC(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 SERLoopbackAsync
Configures a serial module for asynchronous internal loopback transmission. The user is queried for the
serial channel to perform this transmission on.
\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_ASYNC(int32_t cardIndex, int32_t module, uint32_t moduleID)
{
   int32_t i;
   int32_t channelCount;
   int32_t chanNum;
   int32_t nNumWordsSend, nNumWordsRecv;
   int32_t nCntlValueLo;
   uint8_t ch;
   uint32_t SendData[NUM_DATA_TX], RecvDataStatus[MAX_DATA_RX];

   channelCount = naibrd_SER_GetChannelCount(moduleID);
   naiapp_query_ChannelNumber(channelCount, 1, &chanNum);

   naibrd_SER_ClearRxFifo(cardIndex, module, chanNum);
   naibrd_SER_ClearTxFifo(cardIndex, module, chanNum);
   nCntlValueLo = NAI_SER_CTRLLO_CLEAR_RX_FIFO | NAI_SER_CTRLLO_CLEAR_TX_FIFO;
   for (i = 0; i < CLEAR_FIFO_TIMEOUT && (nCntlValueLo & (NAI_SER_CTRLLO_CLEAR_RX_FIFO | NAI_SER_CTRLLO_CLEAR_TX_FIFO)); i++)
   {
      nai_ser_chanctrl chanCtrlRaw;
      naibrd_SER_GetChannelControlRaw(cardIndex, module, chanNum, &chanCtrlRaw);
      nCntlValueLo = chanCtrlRaw & 0x0000FFFF;
      nai_msDelay(1);
   }
   if (i == CLEAR_FIFO_TIMEOUT)
   {
      printf("Unable to clear FIFOs %d\n", chanNum);
      printf("Please press Enter to exit...");
      while ((ch = (int8_t)getchar()) != 0x0A);
      return;
   }

   printf("\nSerial Channel # %d\n", chanNum);
   check_status(naibrd_SER_SetProtocol(cardIndex, module, chanNum, NAI_SER_PROTOCOL_ASYNC));       /* Async mode */
   check_status(naibrd_SER_SetInterfaceLevel(cardIndex, module, chanNum, NAI_SER_INTF_LOOPBACK));  /* Loopback */
   check_status(naibrd_SER_SetParity(cardIndex, module, chanNum, NAI_SER_PARITY_NONE));            /* No Parity */
   check_status(naibrd_SER_SetDataBits(cardIndex, module, chanNum, 8));                            /* 8 Data Bits */
   check_status(naibrd_SER_SetStopBits(cardIndex, module, chanNum, 1));                            /* 1 Stop Bit */
   check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600));                         /* 9600 baud */
   check_status(naibrd_SER_AsyncTransmitControl(cardIndex, module, chanNum, 1));                   /* Enable Transmit */
   if (NAI_MODULE_ID_P8 == moduleID || NAI_MODULE_ID_PC == moduleID || NAI_MODULE_ID_PD == moduleID ||
      NAI_MODULE_ID_Px == moduleID || NAI_MODULE_ID_KB == moduleID)
   {
      nai_msDelay(20);     /* Allow 20ms for the HW to acknowledge the configuration (GEN 2/3 only)*/
   }
   check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1));                      /* Enable Receiver */

   for (i = 0; i < NUM_DATA_TX; i++)
      SendData[i] = (uint8_t)i;           /* incremental data */

   /* Add a delay here for receiver to be ready */
   nai_msDelay(50);

   /* Send data */
   nNumWordsSend = i;
   printf("\nSending %d words ...", nNumWordsSend);
   naibrd_SER_TransmitBuffer(cardIndex, module, chanNum, sizeof(SendData[0]), SendData, nNumWordsSend, (uint32_t*)&nNumWordsSend);
   printf(" %d words sent\n", nNumWordsSend);

   printf("Please press Enter to read back data...");
   while ((ch = (int8_t)getchar()) != 0x0A);

   /* Read back data */
   naibrd_SER_GetRxBufferCnt(cardIndex, module, chanNum, (uint32_t*)&nNumWordsRecv);
   printf("\nReading back %d words ...", nNumWordsRecv);
   naibrd_SER_ReceiveBuffer32(cardIndex, module, chanNum, RecvDataStatus, nNumWordsSend, (uint32_t*)&nNumWordsRecv);
   printf(" %d words read\n", nNumWordsRecv);

   for (i = 0; i < nNumWordsRecv; i++)
      printf("Sent 0x%02X; Recd 0x%02X, Status= %02X\n",
         SendData[i], (RecvDataStatus[i] & 0x00FF), (RecvDataStatus[i] >> 8) & 0x00FF);
}

Help Bot

X