AR CAN Recv
Edit this on GitLab
AR CAN Recv Sample Application (SSK 2.x)
Overview
The AR CAN Recv sample application demonstrates how to receive CAN messages from all channels of an AR CAN module using the NAI Software Support Kit (SSK 2.x). The application supports both standard CAN (A/B) and CAN FD protocols. It queries the user for the protocol type, mode (Mode A with 11-bit identifiers or Mode B with 29-bit identifiers for CAN FD), and baud rate, then iterates through all channels checking for waiting messages. When a message is found, the application reads all frames from the channel’s FIFO and displays the message ID, timestamp, and payload data.
This sample supports AR CAN module types. It is designed to work with the AR CAN Transmit sample application for transmit testing.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an AR CAN module installed.
-
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 CAN transmitter connected to the module (use the AR CAN Transmit sample or external equipment).
Board Connection and Module Selection
|
Note
|
This startup sequence is common to all NAI sample applications. |
The main() function follows a standard SSK 2.x startup flow. After connecting, it retrieves the module ID and verifies the channel count is non-zero using naibrd_AR_CAN_GetChannelCount().
Program Structure
Application Flow
-
Query for protocol (CAN A/B or CAN FD).
-
If CAN FD, query for Mode A (11-bit) or Mode B (29-bit) identifier length.
-
Query for baud rate and data rate.
-
Set baud rates on all channels.
-
Iterate through all channels, checking for waiting messages.
-
For each channel with messages, read all frames from the FIFO and display them.
Channel Configuration
The application sets the baud rate on all channels:
for (channelIndex = 1; channelIndex <= maxChannel; channelIndex++)
{
check_status(naibrd_AR_CAN_SetBaudRate(cardIndex, module, channelIndex,
(naibrd_ar_can_low_rate_type_t)baudBaseRate, (naibrd_ar_can_high_rate_type_t)baudDataRate));
}
Message Reception
The application checks each channel for waiting messages, then reads all frames:
check_status(naibrd_AR_CAN_GetRxFIFOMessageWaiting(cardIndex, module, channelIndex, &msgWaiting));
if (msgWaiting)
{
check_status(naibrd_AR_CAN_GetRxFIFOFrameCount(cardIndex, module, channelIndex, &numFrames));
for (frmIdx = 0; frmIdx < numFrames; frmIdx++)
{
status = (nai_status_t)naibrd_AR_CAN_Receive(cardIndex, module, channelIndex, bufferLength,
&messageId, &timeStamp, data, &length);
}
}
The buffer length depends on the protocol: CAN_FD_MAX_PAYLOAD for CAN FD or STANDARD_CAN_MAX_PAYLOAD for CAN A/B.
Troubleshooting Reference
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No message waiting on any channel |
Transmitter not running, cable not connected, baud rate mismatch |
Ensure the AR CAN Transmit sample is running. Verify cabling and baud rate settings. |
Module selection not recognized |
Not an AR CAN module |
Verify the module type supports AR CAN. |
Unable to receive FIFO data |
Protocol mismatch, mode mismatch |
Ensure both transmitter and receiver use the same protocol and mode. |
No board found or connection timeout |
Board not powered, incorrect configuration file |
Verify hardware is powered and connected. |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — ar_can_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_ar_can.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_utils.h"
/* Common ARCAN Sample Program include files */
#include "../../ar_can_common_utils/ar_can_common_utils.h"
static const int8_t* DEF_CONFIG_FILE = (int8_t*)"default_AR_CANReceive.txt";
/* Internal function prototypes */
static void Run_ARCAN_Receive(int32_t cardIndex, int32_t module, uint32_t modId);
static void printAllChannelFIFOdata(int32_t channel, naibrd_ar_can_protocol_type_t protocol, ARCANDataFrame* ar_can_fifoData);
/**************************************************************************************************************/
/**
* <summary>
*
* The main routine assists in gaining access to the board.
*
* The following routines from the nai_sys_cfg.c file are
* called to assist with accessing and configuring the board.
*
* - ConfigDevice
* - DisplayDeviceCfg
* - GetBoardSNModCfg
* - CheckModule
*
* </summary>
*/
/*****************************************************************************/
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t AR_CAN_Receive(void)
#else
int32_t main(void)
#endif
{
bool_t stop = NAI_FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t moduleNumber;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
uint32_t modId;
int32_t channelCount;
if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == NAI_TRUE)
{
while (stop != NAI_TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Query the user for the module number */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &moduleNumber);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleName(cardIndex, moduleNumber, &modId));
channelCount = naibrd_AR_CAN_GetChannelCount(modId);
if (channelCount != 0)
{
Run_ARCAN_Receive(cardIndex, moduleNumber, modId);
}
else
{
naiif_printf(" *** Module selection not recognized as valid module type for this application. ***\r\n\r\n");
}
}
}
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;
}
/**************************************************************************************************************/
/**
* <summary>
* AR_CAN recieve lets you configure and receive messages stored in all channel's FIFO
*
* </summary>
*/
/**************************************************************************************************************/
static void Run_ARCAN_Receive(int32_t cardIndex, int32_t module, uint32_t modId)
{
int32_t maxChannel;
bool_t bQuit = NAI_FALSE;
naibrd_ar_can_protocol_type_t protocol;
bool_t isModeA = NAI_TRUE;
int32_t baudBaseRate;
int32_t baudDataRate;
bool_t bContinue = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
bool_t msgWaiting = NAI_FALSE;
int channelIndex;
maxChannel = naibrd_AR_CAN_GetChannelCount(modId);
if (!bQuit)
{
/*Query the user for protocol*/
bQuit = naiapp_query_ARCAN_Protocol(&protocol);
if (!bQuit)
{
/*Default is Mode A, the FD protocol lets user choose between Mode A (11 bits) or Mode B (29 bits) for message identifier length*/
if (protocol == NAIBRD_AR_CAN_PROTOCOL_FD)
{
/*Query user for mode A or B*/
bQuit = naiapp_query_ARCAN_isModeA(&isModeA);
}
}
}
if (!bQuit)
{
/* Query user for baud rate and data rate */
bQuit = naiapp_query_ARCAN_BaudRate(&baudBaseRate, &baudDataRate);
if (!bQuit)
{
for (channelIndex = 1; channelIndex <= maxChannel; channelIndex++)
{
/* Set baud rate and data rate */
check_status(naibrd_AR_CAN_SetBaudRate(cardIndex, module, channelIndex,
(naibrd_ar_can_low_rate_type_t)baudBaseRate, (naibrd_ar_can_high_rate_type_t)baudDataRate));
}
}
}
/* Iterate through all channels until max channel is reached or user quits */
for (channelIndex = 1; (!bContinue && channelIndex <= maxChannel); channelIndex++)
{
/* Determine if there is a message waiting in the FIFO for the specific channel */
check_status(naibrd_AR_CAN_GetRxFIFOMessageWaiting(cardIndex, module, channelIndex, &msgWaiting));
if (msgWaiting)
{
naiif_printf("\r\nMessage Waiting on Channel %d, Press 'Enter' to recieve or Q to quit: \r\n", channelIndex);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
int frmIdx;
int32_t numFrames;
nai_status_t status;
/* Get the number of frames on the FIFO */
check_status(naibrd_AR_CAN_GetRxFIFOFrameCount(cardIndex, module, channelIndex, &numFrames));
ar_can_fifoData[channelIndex - 1].numOfFramesOnFifo = numFrames;
/* Allocate space for data based on number of frames and protocol */
for (frmIdx = 0; frmIdx < ar_can_fifoData[channelIndex - 1].numOfFramesOnFifo; frmIdx++)
{
if (protocol == NAIBRD_AR_CAN_PROTOCOL_FD)
{
memset(ar_can_fifoData[channelIndex - 1].data[frmIdx].dataFD, 0, sizeof(ar_can_fifoData[channelIndex - 1].data[frmIdx].dataFD));
}
else
{
memset(ar_can_fifoData[channelIndex - 1].data[frmIdx].dataAB, 0, sizeof(ar_can_fifoData[channelIndex - 1].data[frmIdx].dataAB));
}
}
/* Call naibrd_AR_CAN_Receive for every frame in the FIFO to recieve all messages for a specific channel */
if (protocol == NAIBRD_AR_CAN_PROTOCOL_FD)
{
int frmIdx;
int32_t bufferLength = CAN_FD_MAX_PAYLOAD;
for (frmIdx = 0; frmIdx < ar_can_fifoData[channelIndex - 1].numOfFramesOnFifo; frmIdx++)
{
status = (nai_status_t)naibrd_AR_CAN_Receive(cardIndex, module, channelIndex, bufferLength,
&(ar_can_fifoData[channelIndex - 1].data[frmIdx].messageId),
&(ar_can_fifoData[channelIndex - 1].data[frmIdx].timeStamp),
ar_can_fifoData[channelIndex - 1].data[frmIdx].dataFD,
&(ar_can_fifoData[channelIndex - 1].data[frmIdx].length));
}
}
else
{
int frmIdx;
int32_t bufferLength = STANDARD_CAN_MAX_PAYLOAD;
for (frmIdx = 0; frmIdx < ar_can_fifoData[channelIndex - 1].numOfFramesOnFifo; frmIdx++)
{
status = (nai_status_t)naibrd_AR_CAN_Receive(cardIndex, module, channelIndex, bufferLength,
&(ar_can_fifoData[channelIndex - 1].data[frmIdx].messageId),
&(ar_can_fifoData[channelIndex - 1].data[frmIdx].timeStamp),
ar_can_fifoData[channelIndex - 1].data[frmIdx].dataAB,
&(ar_can_fifoData[channelIndex - 1].data[frmIdx].length));
}
}
/* If FIFO data recieved successfully then display the data */
if (NAI_SUCCESS == status)
{
printAllChannelFIFOdata(channelIndex, protocol, ar_can_fifoData);
}
else
{
naiif_printf("\r\nERROR : Unable to receive FIFO data, returning with status code : %d\r\n", status);
}
}
}
else
{
naiif_printf("\r\nNo message waiting on Channel %d\r\n", channelIndex);
}
naiif_printf("\r\nPress 'Enter' to continue reading channel messages or Q to quit : \r\n");
bContinue = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
void printAllChannelFIFOdata(int32_t channel, naibrd_ar_can_protocol_type_t protocol, ARCANDataFrame *ar_can_fifoData)
{
int frmIdx;
naiif_printf("\r\n----------- Channel [%d] Messages -----------\r\n", channel);
for (frmIdx = 0; frmIdx < ar_can_fifoData[channel - 1].numOfFramesOnFifo; frmIdx++)
{
int i;
int32_t messageId = ar_can_fifoData[channel - 1].data[frmIdx].messageId;
int32_t timeStamp = ar_can_fifoData[channel - 1].data[frmIdx].timeStamp;
naiif_printf("\r\nFrame[%d] Message ID:%x | Time Stamp:%x", frmIdx, messageId, timeStamp);
naiif_printf("\r\nData >>");
for (i = 0; i < ar_can_fifoData[channel - 1].data[frmIdx].length; i++)
{
if (protocol == NAIBRD_AR_CAN_PROTOCOL_FD)
{
naiif_printf(" ");
naiif_printf("%x", ar_can_fifoData[channel - 1].data[frmIdx].dataFD[i]);
}
else
{
naiif_printf(" ");
naiif_printf("%x", ar_can_fifoData[channel - 1].data[frmIdx].dataAB[i]);
}
}
naiif_printf("\r\n");
}
naiif_printf("\r\n---------------------------------------------\r\n");
naiif_printf("\r\n");
}