SER HDLC Rx
Edit this on GitLab
SER HDLC Rx
Explanation
About the Sample Application Code
This C application interacts with North Atlantic Industries (NAI) embedded function modules using NAI’s Software Support Kit (SSK). The sample code configures a module for Serial High-Level Data Link Control (HDLC) reception. Below is an overview and a step-by-step explanation of the application.
Overview
Definitions and Enumerations: - 'CONFIG_FILE': Path to the configuration file. - 'MAX_DATA_RX', 'MAX_TIMEOUT', and 'CLEAR_FIFO_TIMEOUT': Constants for buffer size and timeout durations. - 'NAI_QUIT_CHAR': Character to terminate the application loop.
Include Files: - Standard libraries: 'stdio.h', 'stdlib.h', 'string.h', 'time.h', and 'ctype.h'. - NAI-specific headers for board access, querying, displaying, and utility functions.
Function Prototypes: - 'void Run_SER_HDLC_Rx(int32_t cardIndex, int32_t module, uint32_t modid)': Configures and runs HDLC reception.
Application Walkthrough
Main Entry Point
int32_t main(void) { 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)) { Run_SER_HDLC_Rx(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; }
Explanation: 1. Initializes multiple variables for managing user input and module details. 2. Runs a configurable board access menu ('naiapp_RunBoardMenu'). 3. Enters a loop to interact with the user for card and module selection. 4. Uses 'naiapp_query_CardIndex' to determine which card is being used. 5. Obtains the module count with 'naibrd_GetModuleCount'. 6. Queries the user for module number using 'naiapp_query_ModuleNumber'. 7. Gets the module ID using 'naibrd_GetModuleID'. 8. Calls 'Run_SER_HDLC_Rx' to configure and run the HDLC reception if a valid module ID is retrieved. 9. Prompts the user to either quit or restart the application. 10. Closes all open cards and exits when prompted.
HDLC Reception Function
void Run_SER_HDLC_Rx(int32_t cardIndex, int32_t modNum, uint32_t modid) { int32_t ch, i; int32_t channelCount; int32_t chanNum; int32_t nCntlValueLo, nConfigWordLo; int32_t nNumWordsRecv = 0; uint32_t RecvDataStatus[255]; bool_t bQuit = FALSE; int8_t inputBuffer[80]; int32_t inputResponseCnt; channelCount = naibrd_SER_GetChannelCount(modid); naiapp_query_ChannelNumber(channelCount, 1, &chanNum); naibrd_SER_ChannelReset(cardIndex, modNum, chanNum); naibrd_SER_ClearRxFifo(cardIndex, modNum, chanNum); naibrd_SER_ClearTxFifo(cardIndex, modNum, 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, modNum, 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 = getchar()) != 0x0A); return; } printf("\nSerial Channel # %d\n", chanNum); check_status(naibrd_SER_SetProtocol(cardIndex, modNum, chanNum, NAI_SER_PROTOCOL_HDLC)); check_status(naibrd_SER_SetInterfaceLevel(cardIndex, modNum, chanNum, NAI_SER_INTF_RS422)); check_status(naibrd_SER_SetClockMode(cardIndex, modNum, chanNum, TXINT_RXINT)); check_status(naibrd_SER_SetBaudrate(cardIndex, modNum, chanNum, 115200)); check_status(naibrd_SER_SetRxHdlcAddrsSyncChar(cardIndex, modNum, chanNum, 0x247A)); nConfigWordLo = (NAI_SER_CFGLO_ADDR_LEN_16 | NAI_SER_CFGLO_ADDR_REC); check_status(naibrd_SER_SetChannelConfigRaw(cardIndex, modNum, chanNum, nConfigWordLo)); if (NAI_MODULE_ID_P8 == modid || NAI_MODULE_ID_PC == modid || NAI_MODULE_ID_PD == modid || NAI_MODULE_ID_Px == modid || NAI_MODULE_ID_KB == modid) { nai_msDelay(20); } check_status(naibrd_SER_SetReceiverEnable(cardIndex, modNum, chanNum, 1)); nai_msDelay(100); printf("Please press Enter to read back data..."); while ((ch = getchar()) != 0x0A); do { check_status(naibrd_SER_GetHDLCPacket32(cardIndex, modNum, chanNum, RecvDataStatus, MAX_DATA_RX, (uint32_t*)&nNumWordsRecv, MAX_TIMEOUT)); printf(" %d words read\n", nNumWordsRecv); for (i = 0; i < nNumWordsRecv; i++) printf("Recd 0x%02X, Status= %02X\n", (RecvDataStatus[i] & 0x00FF), (RecvDataStatus[i] >> 8) & 0x00FF); 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 (TRUE != bQuit); return; }
Explanation: 1. Queries the number of channels for the given module using 'naibrd_SER_GetChannelCount'. 2. Asks the user for the channel number using 'naiapp_query_ChannelNumber'. 3. Resets, clears the RX/TX FIFO buffers, and waits for them to clear. 4. Configures the serial channel for HDLC reception with specific baud rate and protocol settings. 5. Enables the receiver and waits for the user to press Enter to start reading data. 6. Enters a loop to read HDLC packets and displays received data until the user opts to quit.
Summary
This application uses NAI’s SSK to set up a module for Serial HDLC reception, illustrating steps from configuration to data reception. It uses utility, querying, and board access functions provided by NAI’s libraries to interact with the hardware.
#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_SerHDLC_Rx.txt";
/* Function prototypes */
void Run_SER_HDLC_Rx(int32_t cardIndex, int32_t module, uint32_t modid);
#define MAX_DATA_RX 20
#define MAX_TIMEOUT 10 /* 10ms timeout */
#define CLEAR_FIFO_TIMEOUT 1000 /* 1 second */
/**************************************************************************************************************/
/** \defgroup SERHDLCRx Serial Synchronous Receive
The purpose of the Serial Synchronous Receive sample application is to illustrate the methods to call in the
naibrd library to configure a given serial channel for receiving. The SER_HDLC_Tx application can be run in
unison to this application to receive serial data.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SER_HDLC_Rx_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_HDLC_Rx(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 SERHDLCRx
Configures a serial module for synchronous receiving. The user is queried for the serial channel to receive on.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param modNum (Input) Module Number of the module to access (1 - [max modules for board]).
\param modid (Input) The ID of the module.
*/
/**************************************************************************************************************/
void Run_SER_HDLC_Rx(int32_t cardIndex, int32_t modNum, uint32_t modid)
{
int32_t ch, i;
int32_t channelCount;
int32_t chanNum;
int32_t nCntlValueLo, nConfigWordLo;
int32_t nNumWordsRecv = 0;
uint32_t RecvDataStatus[255];
bool_t bQuit = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
channelCount = naibrd_SER_GetChannelCount(modid);
naiapp_query_ChannelNumber(channelCount, 1, &chanNum);
naibrd_SER_ChannelReset(cardIndex, modNum, chanNum);
naibrd_SER_ClearRxFifo(cardIndex, modNum, chanNum);
naibrd_SER_ClearTxFifo(cardIndex, modNum, 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, modNum, 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 = getchar()) != 0x0A);
return;
}
printf("\nSerial Channel # %d\n", chanNum);
/* Configure for HDLC on the channel selected. */
check_status(naibrd_SER_SetProtocol(cardIndex, modNum, chanNum, NAI_SER_PROTOCOL_HDLC)); /* HDLC mode */
check_status(naibrd_SER_SetInterfaceLevel(cardIndex, modNum, chanNum, NAI_SER_INTF_RS422)); /* RS422 */
check_status(naibrd_SER_SetClockMode(cardIndex, modNum, chanNum, TXINT_RXINT)); /* Tx and Rx internal */
check_status(naibrd_SER_SetBaudrate(cardIndex, modNum, chanNum, 115200)); /* 115,200 baud */
check_status(naibrd_SER_SetRxHdlcAddrsSyncChar(cardIndex, modNum, chanNum, 0x247A)); /* recv sync char - must be same as xmit for loopback */
nConfigWordLo = (NAI_SER_CFGLO_ADDR_LEN_16 | NAI_SER_CFGLO_ADDR_REC); /* 16-bit HDLC addr recognition */
check_status(naibrd_SER_SetChannelConfigRaw(cardIndex, modNum, chanNum, nConfigWordLo));
if (NAI_MODULE_ID_P8 == modid || NAI_MODULE_ID_PC == modid || NAI_MODULE_ID_PD == modid ||
NAI_MODULE_ID_Px == modid || NAI_MODULE_ID_KB == modid)
{
nai_msDelay(20); /* Allow 20ms for the HW to acknowledge the configuration (GEN 2/3 only)*/
}
check_status(naibrd_SER_SetReceiverEnable(cardIndex, modNum, chanNum, 1)); /* Enable the Receiver */
/* 100 millisecond wait to ensure the receiver is on. */
nai_msDelay(100);
printf("Please press Enter to read back data...");
while ((ch = getchar()) != 0x0A);
do
{
check_status(naibrd_SER_GetHDLCPacket32(cardIndex, modNum, chanNum, RecvDataStatus, MAX_DATA_RX,
(uint32_t*)&nNumWordsRecv, MAX_TIMEOUT));
printf(" %d words read\n", nNumWordsRecv);
for (i = 0; i < nNumWordsRecv; i++)
printf("Recd 0x%02X, Status= %02X\n",
(RecvDataStatus[i] & 0x00FF), (RecvDataStatus[i] >> 8) & 0x00FF);
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 (TRUE != bQuit);
return;
}