AR CAN BasicOps
Edit this on GitLab
AR CAN BasicOps Sample Application (SSK 2.x)
Overview
The AR CAN BasicOps sample application demonstrates how to perform ARINC/CAN bus operations using the NAI Software Support Kit (SSK 2.x). It provides a comprehensive interactive menu for configuring channels, setting protocols (CAN A/B and CAN FD), configuring baud rates, managing interrupts, querying statuses, transmitting and receiving messages, scheduling transmissions, and managing FIFO filters. This sample covers the full range of AR CAN module functionality.
This sample supports ARINC/CAN combination modules. It features a multi-level menu system with separate sub-menus for interrupt configuration, status queries, and main operations. Refer to the CB1-CB3 Manual for detailed module specifications.
For the SSK 1.x version, see AR CAN BasicOps (SSK 1.x).
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an ARINC/CAN combination 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.
How to Run
Launch the ar_can_basic_ops executable from your build output directory. On startup the application looks for a configuration file (default_AR_CANBasicOps.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, a comprehensive command menu lets you exercise all AR CAN operations.
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 AR CAN. |
The main() function follows a standard SSK 2.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_AR_CANBasicOps.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear. -
Query the user for a card index with
naiapp_query_CardIndex(). -
Query for a module slot with
naiapp_query_ModuleNumber(). -
Enter the CAN operations menu via
Run_CAN_DisplayCANChoices().
#if defined (__VXWORKS__)
int32_t naiapp_AR_CAN_BasicOps(void)
#else
int32_t main(void)
#endif
{
bool_t stop = NAI_FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
Init_UserParams();
if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == NAI_TRUE)
{
while (stop != NAI_TRUE)
{
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
userInput.nCardIdx = cardIndex;
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
g_moduleCount = moduleCnt;
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &userInput.nModuleNumber);
if (stop != NAI_TRUE)
{
Run_CAN_DisplayCANChoices();
}
}
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;
}
|
Note
|
This source file uses the older __VXWORKS__ preprocessor guard rather than the SSK 2.x standard NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS.
|
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
Entry Point
On standard platforms (Petalinux, DEOS) the entry point is main(). On VxWorks the entry point is naiapp_AR_CAN_BasicOps().
Command Loop
The Run_CAN_DisplayCANChoices() function presents the main menu and dispatches to individual operation functions based on user input. The menu is organized into logical groups separated by dividers.
| Command | Description |
|---|---|
1 - Set Channel |
Select the active CAN channel |
2 - Set Protocol |
Choose CAN A/B or CAN FD protocol |
3 - Set Baud |
Configure base and data baud rates |
4 - Reset Channel |
Reset channel to default state |
5/6 - Termination |
Enable or disable bus termination |
7 - Get/Clear LEC |
Read and clear Last Error Code |
8 - Set Interrupts |
Configure interrupt steering, trigger type, and enable/disable |
9 - Get Statuses |
Query channel and event mapped statuses |
A/B - Xmit |
Single 8-byte or 64-byte (CAN FD) transmission |
C/D - Receive |
Receive single message or message pump |
E/F/G - Schedule |
Schedule message, start schedule, stop schedule |
I-O - Filters |
Set/get/remove filters and masks, enable/disable filtering |
U-Z - FIFO |
Reset Tx/Rx FIFO, enable/disable Tx, reset drop count, display counts |
Channel and Protocol Configuration
The channel configuration functions allow selecting the active channel, setting the protocol (CAN A/B at index 0, CAN FD at index 1), and configuring baud rates. The application tracks per-channel settings in a ChannelConfig struct so that switching channels restores the previously configured protocol, baud rate, and interrupt settings automatically.
Set Channel
To select the active CAN channel, the application prompts for a channel number, validates it against the module’s channel count using naibrd_AR_CAN_GetChannelCountForModule(), and saves the current channel’s configuration before switching. In your own code you would simply track which channel index you want to operate on.
/* Validate the channel number is within range */
if (chan < 1 || chan > naibrd_AR_CAN_GetChannelCountForModule(card, mod))
{
validChannel = NAI_FALSE;
}
Set Protocol
To select the CAN protocol for a channel, pass 0 for CAN A/B or 1 for CAN FD. The sample stores this in userInput.nProtocolIndex and uses it for all subsequent transmit and baud-rate operations. Protocol must be set before attempting any data transfer.
/* Protocol index: 0 = CAN AB, 1 = CAN FD */
if (inputResponseCnt == 0)
userInput.nProtocolIndex = 1;
else
userInput.nProtocolIndex = atoi((const char *)inputBuffer);
if (userInput.nProtocolIndex > 1 || userInput.nProtocolIndex < 0)
{
naiif_printf("Invalid protocol index detected. Defaulting to CAN-FD - protocol index 1\r\n");
userInput.nProtocolIndex = 1;
}
Set Baud Rate
To configure baud rates, call naibrd_AR_CAN_SetBaudRate() with a base rate index and a data rate index. The base rate controls the arbitration phase speed and the data rate controls the CAN FD data phase speed. The sample first reads the current rates with naibrd_AR_CAN_GetBaudRate() so the user can confirm the change.
/* Read current baud rates */
status = naibrd_AR_CAN_GetBaudRate(userInput.nCardIdx, userInput.nModuleNumber,
userInput.nChannelNumber, &origBaseRate, &origDataRate);
/* Set new base and data baud rates */
status = naibrd_AR_CAN_SetBaudRate(userInput.nCardIdx, userInput.nModuleNumber,
userInput.nChannelNumber,
(naibrd_ar_can_low_rate_type_t)userInput.nBaudBaseRate,
(naibrd_ar_can_high_rate_type_t)userInput.nBaudDataRate);
-
cardIndex— identifies the board. -
module— the slot containing the AR CAN module. -
channel— the channel to configure. -
Base rate indices: 0 = 1000K, 1 = 500K, 3 = 250K.
-
Data rate indices: 6 = 4000K, 7 = 3000K, 8 = 2000K, 9 = 1000K.
Reset Channel
To reset a channel back to its default state, call naibrd_AR_CAN_ChannelReset(). This is useful when you want to clear all configuration and start fresh, for example before switching protocols.
status = naibrd_AR_CAN_ChannelReset(userInput.nCardIdx, userInput.nModuleNumber,
userInput.nChannelNumber);
Set Termination
To enable or disable the internal 120-ohm CAN bus termination resistor on a channel, call naibrd_AR_CAN_SetTermination(). Bus termination is required at both physical ends of a CAN bus to prevent signal reflections.
/* Enable termination */
status = naibrd_AR_CAN_SetTermination(userInput.nCardIdx, userInput.nModuleNumber,
userInput.nChannelNumber, NAI_TRUE);
/* Disable termination */
status = naibrd_AR_CAN_SetTermination(userInput.nCardIdx, userInput.nModuleNumber,
userInput.nChannelNumber, NAI_FALSE);
-
cardIndex— identifies the board. -
module— the slot containing the AR CAN module. -
channel— the channel to configure. -
The fourth parameter —
NAI_TRUEto enable the internal termination resistor,NAI_FALSEto disable it.
Get/Clear Last Error Code (LEC)
To read the Last Error Code from the CAN controller, call naibrd_AR_CAN_GetEnhancedLastError() (or naibrd_AR_CAN_GetLastError() for the basic variant). The LEC indicates bus-level errors such as bit errors, stuff errors, or form errors. After diagnosing the issue, clear the LEC with naibrd_AR_CAN_ResetLastError().
uint8_t outbusError = 0;
uint16_t outlastError = 0;
/* Read the enhanced LEC with bus error information */
status = naibrd_AR_CAN_GetEnhancedLastError(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
&outlastError, &outbusError);
/* Clear the LEC after reading */
naibrd_AR_CAN_ResetLastError(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber);
Interrupt Configuration
The interrupt sub-menu allows configuring interrupt steering (VME, onboard ARM, PCIe, cPCI), trigger type (edge or level), and selecting channel-mapped or event-mapped interrupts. An ISR callback (myIsr()) handles interrupt events and reads the appropriate status registers. The application supports both channel-mapped interrupts (BIT status, new Rx data) and event-mapped interrupts (FIFO level events such as Rx full, Tx empty).
Interrupt Sub-Menu Commands
| Command | Description |
|---|---|
1 |
Set interrupt steering (VME, Onboard ARM, PCIe, cPCI) |
2 |
Set interrupt trigger type (edge or level) |
3 |
Set channel-mapped interrupt (BIT status or new Rx data) |
4 |
Set event-mapped interrupt (FIFO Rx/Tx level events) |
5 |
Enable interrupt for the current channel |
6 |
Disable interrupt for the current channel |
Set Interrupt Steering
Interrupt steering determines which processor or bus receives the interrupt signal. You must set the steering before enabling interrupts.
interruptSteering = (naibrd_int_steering_t)userInput.nInterruptSteering;
/* For event-mapped interrupts */
check_status(naibrd_AR_CAN_SetEventMappedInterruptSteering(cardIndex,
module, chanNum, categoryType, interruptSteering));
/* For channel-mapped interrupts */
check_status(naibrd_AR_CAN_SetChanMappedInterruptSteering(cardIndex,
module, chanMapInterruptStatus, interruptSteering));
-
Steering values: 1 = VME, 2 = Onboard ARM, 5 = PCIe, 6 = cPCI.
Set Interrupt Trigger Type
The trigger type controls whether the interrupt fires on a signal edge transition or on a sustained level.
interruptTriggerType = (naibrd_int_trigger_type_t)userInput.nInterruptTriggerType;
/* For event-mapped interrupts */
check_status(naibrd_AR_CAN_SetEventMappedInterruptTriggerType(cardIndex,
module, chanNum, eventMapInterruptStatus, interruptTriggerType));
/* For channel-mapped interrupts */
check_status(naibrd_AR_CAN_SetChanMappedInterruptTriggerType(cardIndex,
module, chanNum, chanMapInterruptStatus, interruptTriggerType));
-
Trigger type values: 0 = Edge, 1 = Level.
Enable and Connect ISR
Enabling an interrupt requires several steps: set the steering, trigger type, and vector, clear any pending status, connect the ISR callback, and then enable the interrupt. The sample assigns interrupt vectors based on the channel number (0xA1 for channel 1 through 0xA8 for channel 8).
/* Connect the ISR callback (once, shared across all channels) */
status = naibrd_ConnectISR(cardIndex, myIsr);
/* Clear any pending status before enabling */
check_status(naibrd_AR_CAN_ClearEventMappedStatusBit(cardIndex, module,
chanNum, eventMapInterruptStatus));
/* Set vector, steering, trigger type, then enable */
check_status(naibrd_AR_CAN_SetEventMappedInterruptVector(cardIndex,
module, chanNum, categoryType, interruptVector));
check_status(naibrd_AR_CAN_SetEventMappedInterruptSteering(cardIndex,
module, chanNum, categoryType, interruptSteering));
check_status(naibrd_AR_CAN_SetEventMappedInterruptTriggerType(cardIndex,
module, chanNum, eventMapInterruptStatus, interruptTriggerType));
check_status(naibrd_AR_CAN_SetEventMappedInterruptEnable(cardIndex,
module, chanNum, eventMapInterruptStatus, NAI_TRUE));
ISR Callback
The ISR callback receives the interrupt vector, identifies the channel from the vector value, and reads the appropriate status register. Channel-mapped interrupts read naibrd_AR_CAN_GetChanMappedStatusRaw(), while event-mapped interrupts read naibrd_AR_CAN_GetEventMappedStatusRaw().
static void myIsr(uint32_t vector)
{
int32_t chanIndex = -1;
uint32_t outStatusRaw = 0u;
receivedVector = vector;
irqCount++;
/* Map vector 0xA1-0xA8 to channel 1-8 */
if (receivedVector >= 0xA1 && receivedVector <= 0xA8) {
chanIndex = (receivedVector - 0xA1); /* 0-based index */
}
if (chanConfig[chanIndex].interruptLabel == CAN_CHANNEL_MAPPED_INTERRUPT_SET)
{
check_status(naibrd_AR_CAN_GetChanMappedStatusRaw(userInput.nCardIdx,
userInput.nModuleNumber,
(naibrd_ar_can_chan_mapped_status_type_t)chanConfig[chanIndex].nInterrupt,
&outStatusRaw));
}
else if (chanConfig[chanIndex].interruptLabel == CAN_EVENT_MAPPED_INTERRUPT_SET)
{
check_status(naibrd_AR_CAN_GetEventMappedStatusRaw(userInput.nCardIdx,
userInput.nModuleNumber, chanIndex + 1,
NAI_STATUS_LATCHED, NAIBRD_AR_CAN_EVENT_MAP_FIFO, &outStatusRaw));
}
}
Disable Interrupt
To disable an interrupt, call the corresponding enable function with NAI_FALSE. When the last channel’s interrupt is disabled, the sample disconnects the ISR with naibrd_DisconnectISR().
/* Disable an event-mapped interrupt */
status = naibrd_AR_CAN_SetEventMappedInterruptEnable(cardIndex, module,
chanNum, (naibrd_ar_can_fifo_event_mapped_status_type_t)userInput.nInterrupt,
NAI_FALSE);
/* Disconnect ISR when no more active interrupts */
if (activeChannelCount == 0 && isIsrConnected)
{
status = naibrd_DisconnectISR(cardIndex);
}
Status Read and Clear
The status sub-menu provides access to both channel-mapped and event-mapped status registers. Channel-mapped statuses include BIT status and new Rx data indicators, each available in realtime and latched variants. Event-mapped statuses cover FIFO level conditions (empty, almost empty, almost full, full) for both Rx and Tx FIFOs. Latched statuses must be explicitly cleared after reading.
Status Sub-Menu Commands
| Command | Description |
|---|---|
1 |
Get channel-mapped status (per-bit query) |
2 |
Get channel-mapped status raw (full register) |
3 |
Clear channel-mapped status (latched only) |
4 |
Clear channel-mapped status raw (full register) |
5 |
Get event-mapped status (per-bit query) |
6 |
Get event-mapped status raw (full register) |
7 |
Clear event-mapped status (latched only) |
8 |
Clear event-mapped status raw (full register) |
Read Channel-Mapped Status
To read a channel-mapped status bit, call naibrd_AR_CAN_GetChanMappedStatusBit() for a single-bit result, or naibrd_AR_CAN_GetChanMappedStatusRaw() for the full raw register value. The status type selects which register to read.
nai_status_bit_t outstatusBit;
uint32_t outstatusRaw = 0u;
/* Read a single status bit */
check_status(naibrd_AR_CAN_GetChanMappedStatusBit(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
(naibrd_ar_can_chan_mapped_status_type_t)statusType, &outstatusBit));
/* Read the full raw status register */
check_status(naibrd_AR_CAN_GetChanMappedStatusRaw(userInput.nCardIdx,
userInput.nModuleNumber,
(naibrd_ar_can_chan_mapped_status_type_t)statusType, &outstatusRaw));
-
Status type indices: 0 = BIT Latched, 1 = BIT Realtime, 2 = New Rx Data Latched, 3 = New Rx Data Realtime.
Clear Channel-Mapped Status
To clear a latched channel-mapped status, call naibrd_AR_CAN_ClearChanMappedStatusBit() for a per-channel clear or naibrd_AR_CAN_ClearChanMappedStatusRaw() for a raw register write. Only latched statuses (indices 0 and 2) can be cleared.
/* Clear a single channel's latched status bit */
check_status(naibrd_AR_CAN_ClearChanMappedStatusBit(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
(naibrd_ar_can_chan_mapped_status_type_t)statusType));
/* Clear raw latched status register */
check_status(naibrd_AR_CAN_ClearChanMappedStatusRaw(userInput.nCardIdx,
userInput.nModuleNumber,
(naibrd_ar_can_chan_mapped_status_type_t)statusType, 0xFFu));
Read and Clear Event-Mapped Status
Event-mapped statuses track FIFO level conditions. The sample supports reading per-bit and raw register values, and clearing latched event statuses.
/* Read event-mapped status bit */
check_status(naibrd_AR_CAN_GetEventMappedStatusBit(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
(nai_status_access_type_t)accessType,
(naibrd_ar_can_fifo_event_mapped_status_type_t)statusType,
&outstatusBit));
/* Read event-mapped status raw */
check_status(naibrd_AR_CAN_GetEventMappedStatusRaw(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
(nai_status_access_type_t)accessType,
NAIBRD_AR_CAN_EVENT_MAP_FIFO, &outstatusRaw));
/* Clear a latched event-mapped status bit */
check_status(naibrd_AR_CAN_ClearEventMappedStatusBit(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
(naibrd_ar_can_fifo_event_mapped_status_type_t)statusType));
Transmit and Receive
Transmission functions support both standard 8-byte CAN and 64-byte CAN FD frames. The receive functions read from the Rx FIFO, with a message pump option for continuous reception. Before transmitting, ensure that the protocol is set, the channel is valid, and Tx is enabled.
Single 8-Byte Transmit
To transmit a standard CAN frame, call naibrd_AR_CAN_QueueTransmit() with the protocol type, message ID, payload buffer, and payload length (up to 8 bytes). The message is placed into the Tx FIFO and transmitted when Tx is enabled.
uint8_t u8Buffer[8];
uint32_t msgId = 0x111444u;
bool_t isModeA = NAI_FALSE; /* Extended ID */
u8Buffer[0] = 0x00; u8Buffer[1] = 0x11;
u8Buffer[2] = 0x22; u8Buffer[3] = 0x33;
u8Buffer[4] = 0x44; u8Buffer[5] = 0x55;
u8Buffer[6] = 0x66; u8Buffer[7] = 0x77;
/* Queue the message for transmission */
status = naibrd_AR_CAN_QueueTransmit(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
(naibrd_ar_can_protocol_type_t)userInput.nProtocolIndex,
isModeA, msgId, &u8Buffer[0], STANDARD_CAN_MAX_PAYLOAD);
-
isModeA—NAI_TRUEfor standard 11-bit IDs,NAI_FALSEfor extended 29-bit IDs. -
msgId— the CAN message identifier. -
The last parameter is the payload byte count (8 for standard CAN).
Single 64-Byte Transmit (CAN FD)
For CAN FD frames, the payload can be up to 64 bytes. The protocol is forced to NAIBRD_AR_CAN_PROTOCOL_FD regardless of the current protocol setting.
uint8_t u8Buffer[CAN_FD_MAX_PAYLOAD];
uint32_t msgId = 0x17778888u;
uint32_t i;
/* Fill 64-byte payload */
for (i = 0; i < CAN_FD_MAX_PAYLOAD; i++)
u8Buffer[i] = (i & 0x000000FFu);
/* Queue the CAN FD message */
status = naibrd_AR_CAN_QueueTransmit(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
NAIBRD_AR_CAN_PROTOCOL_FD, isModeA, msgId,
&u8Buffer[0], CAN_FD_MAX_PAYLOAD);
Receive Message
To receive a single CAN frame, first check whether a message is waiting with naibrd_AR_CAN_GetRxFIFOMessageWaiting(), then call naibrd_AR_CAN_Receive() to read the message ID, timestamp, and payload from the Rx FIFO.
uint8_t u8Buffer[SINGLE_MSG_BUFFER_LEN];
uint32_t msgId = 0u;
uint32_t timestamp;
int32_t outRxCount = 0;
bool_t msgWaiting = NAI_FALSE;
/* Check for a waiting message */
status = naibrd_AR_CAN_GetRxFIFOMessageWaiting(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, &msgWaiting);
if (NAI_SUCCESS == status && msgWaiting)
{
/* Read the message */
status = naibrd_AR_CAN_Receive(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
SINGLE_MSG_BUFFER_LEN, &msgId, ×tamp,
&u8Buffer[0], &outRxCount);
}
-
msgId— receives the CAN message identifier. -
timestamp— receives the hardware timestamp of the received frame. -
outRxCount— receives the number of payload bytes read.
Receive Message Pump
The message pump continuously polls for incoming messages in a loop, calling naibrd_AR_CAN_GetRxFIFOMessageWaiting() and naibrd_AR_CAN_Receive() until the user quits. This is useful for monitoring bus traffic or testing continuous reception.
Schedule, Start, and Stop
To schedule a periodic CAN message, call naibrd_AR_CAN_ScheduleMsg() with an entry index, rate, skew, and the message parameters. Then call naibrd_AR_CAN_StartScheduler() to begin transmission and naibrd_AR_CAN_StopScheduler() to halt it.
int16_t entryIndex = 1;
int16_t rate = 5;
int16_t skew = 5;
/* Schedule a periodic CAN FD message */
status = naibrd_AR_CAN_ScheduleMsg(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
entryIndex, rate, skew, NAIBRD_AR_CAN_PROTOCOL_FD,
isModeA, msgId, &u8Buffer[0], CAN_FD_MAX_PAYLOAD);
/* Start the scheduler */
status = naibrd_AR_CAN_StartScheduler(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber);
/* Stop the scheduler */
status = naibrd_AR_CAN_StopScheduler(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber);
-
entryIndex— identifies the schedule slot (1-based). -
rate— transmission rate in scheduler ticks. -
skew— timing offset in scheduler ticks.
Filtering
Acceptance filters control which incoming CAN messages are delivered to the Rx FIFO. Each filter matches against the message ID and optionally the first two payload bytes. A companion filter mask specifies which bits of the filter are significant during comparison.
Set and Get Filter
To configure an acceptance filter, call naibrd_AR_CAN_SetAcceptFilter(). To read the current filter settings, call naibrd_AR_CAN_GetAcceptFilter().
int32_t filterIndex = 0;
uint32_t msgId = 0x17778889u;
bool_t isModeA = NAI_FALSE;
uint8_t firstTwoBytes[2] = {0x00, 0x00};
/* Set acceptance filter */
status = naibrd_AR_CAN_SetAcceptFilter(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
filterIndex, msgId, isModeA, &firstTwoBytes[0]);
/* Read acceptance filter */
status = naibrd_AR_CAN_GetAcceptFilter(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
filterIndex, &msgId, &isModeA, &firstTwoBytes[0]);
Set and Get Filter Mask
The filter mask determines which bits of the acceptance filter are compared against incoming messages. A mask bit of 1 means that bit must match; a mask bit of 0 means that bit is ignored.
int32_t maskIndex = 0;
uint32_t msgId = 0x1FFFFFFFu; /* All ID bits must match */
bool_t isModeA = NAI_FALSE;
uint8_t firstTwoBytes[2] = {0x00, 0x00}; /* Ignore payload bytes */
/* Set acceptance mask */
status = naibrd_AR_CAN_SetAcceptMask(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber,
maskIndex, msgId, isModeA, &firstTwoBytes[0]);
Enable/Disable Filters and Remove Filter
Filters must be explicitly enabled after configuration. You can also remove individual filters or disable all filtering.
/* Enable acceptance filtering */
status = naibrd_AR_CAN_EnableAcceptFilters(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, NAI_TRUE);
/* Disable acceptance filtering */
status = naibrd_AR_CAN_EnableAcceptFilters(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, NAI_FALSE);
/* Remove a specific filter */
status = naibrd_AR_CAN_RemoveAcceptFilter(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, filterIndex);
FIFO Management
The FIFO management commands allow resetting Tx and Rx FIFOs, enabling or disabling transmission, resetting the drop count, and displaying FIFO statistics.
Reset Tx/Rx FIFO
Resetting a FIFO clears all queued messages. The sample reads the FIFO count before and after the reset to confirm the operation.
int32_t fifoCount = 0;
/* Reset the Tx FIFO */
status = naibrd_AR_CAN_ResetTxFifo(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber);
/* Reset the Rx FIFO */
status = naibrd_AR_CAN_ResetRxFifo(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber);
Enable/Disable Tx
Tx must be enabled for queued messages to be transmitted onto the bus. If Tx is disabled, messages accumulate in the Tx FIFO but are not sent.
/* Enable Tx */
status = naibrd_AR_CAN_SetTxEnable(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, NAI_TRUE);
/* Disable Tx */
status = naibrd_AR_CAN_SetTxEnable(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, NAI_FALSE);
Display Counts
The display counts function reads Tx FIFO count, Tx FIFO frame count, Rx FIFO count, Rx FIFO frame count, and drop count for the selected channel. The drop count tracks messages that were lost because the Rx FIFO was full.
int32_t txFIFOCount, txFIFOFrameCount, rxFIFOCount, rxFIFOFrameCount, dropCount;
status = naibrd_AR_CAN_GetTxFIFOCount(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, &txFIFOCount);
status = naibrd_AR_CAN_GetTxFIFOFrameCount(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, &txFIFOFrameCount);
status = naibrd_AR_CAN_GetRxFIFOCount(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, &rxFIFOCount);
status = naibrd_AR_CAN_GetRxFIFOFrameCount(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, &rxFIFOFrameCount);
status = naibrd_AR_CAN_GetDropCount(userInput.nCardIdx,
userInput.nModuleNumber, userInput.nChannelNumber, &dropCount);
Troubleshooting Reference
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found |
Board not powered or not connected |
Verify power and physical connections; check configuration file |
Invalid channel number |
Channel out of range for this module |
Check module channel count; channels are 1-based |
Protocol set fails |
Channel not properly initialized |
Reset the channel first, then set protocol |
Baud rate rejected |
Invalid rate index for the selected protocol |
Use valid base rate (0,1,3) and data rate (6-9) indices |
No data received |
Tx and Rx not on same bus or baud mismatch |
Verify physical connection and matching baud rates on both channels |
Interrupt not firing |
Steering or enable not configured |
Set interrupt steering, trigger type, and enable in sequence |
LEC shows errors |
Bus errors due to cabling or termination |
Check bus termination and cable quality; clear LEC after fixing |
FIFO overflow |
Receive FIFO full before data is read |
Increase read frequency or reset Rx FIFO |
Filter not working |
Filters not enabled after configuration |
Call Enable Filters after setting filter values |
Scheduled message not transmitting |
Schedule not started |
Call Start Schedule after scheduling the message |
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_basic_ops.c (SSK 2.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined (LINUX)
#include <ctype.h>
#include <pthread.h>
/*for ethernet code*/
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#endif
#if defined (__VXWORKS__)
#include "inetLib.h"
#include <netdb.h>
#endif
#include <math.h>
/* 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"
/* naibrd include files */
/*
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ar_can.h"
#include "naibrd_ether.h"
#include "advanced/nai_ether_adv.h"
*/
static const int8_t *DEF_CONFIG_FILE = (int8_t *)"default_AR_CANBasicOps.txt";
#define SINGLE_MSG_BUFFER_LEN 80u
#define STANDARD_CAN_MAX_PAYLOAD 8u
#define CAN_FD_MAX_PAYLOAD 64u
#define MAX_AR_CAN_CHANNEL_COUNT 8u
/* Function prototypes */
#define DEF_CAN_CARD_INDEX 0u
#define DEF_CAN_MODULE 1u
#define DEF_CAN_TX_CHANNEL 1u
#define CAN_DEFAULT_MODULE 1u
#define CAN_DATA_LENGTH_ZERO 0u
#define CAN_MAX_MODE_AB_DATA_LENGTH 8u
#define ENHANCED_LEC 1u
static struct _userInput
{
int32_t nCardIdx;
int32_t nModuleNumber;
int32_t nChannelNumber;
int32_t nProtocolIndex;
int32_t nBaudBaseRate;
int32_t nBaudDataRate;
int32_t nInterruptSteering;
int32_t nInterruptTriggerType;
int32_t nInterrupt;
int32_t interruptLabel;
}userInput;
typedef struct {
int32_t nProtocolIndex;
int32_t nBaudBaseRate;
int32_t nBaudDataRate;
int32_t nInterruptSteering;
int32_t nInterruptTriggerType;
int32_t nInterrupt;
int32_t interruptLabel;
} ChannelConfig;
static ChannelConfig chanConfig[MAX_AR_CAN_CHANNEL_COUNT];
/****** static function *******/
static bool_t checkChannelNumber(int32_t card, int32_t mod, int32_t chan);
static void Init_UserParams();
static void Run_CAN_DisplayCANChoices();
static void Show_CanDemoFunc_Commands();
static void Show_CanInterruptFunc_Commands();
static void Show_CanStatusFunc_Commands();
static void myIsr(uint32_t vector);
static void CAN_SetChan();
static void CAN_SetProtocol();
static void CAN_SetBaud();
static void CAN_ResetChannel();
static void CAN_SetTermination(bool_t enableTermination);
static void CAN_GET_ClearLEC(void);
static nai_status_t CAN_SetInterrupts();
static void CAN_GetStatuses();
static void CAN_Single8ByteXmit();
static void CAN_Single64ByteXmit();
static void CAN_ReceiveMsg();
static void CAN_ReceiveMsgPump();
static void CAN_ScheduleMsg();
static void CAN_StartSchedule();
static void CAN_StopSchedule();
static void CAN_SetFilter();
static void CAN_GetFilter();
static void CAN_SetFilterMask();
static void CAN_GetFilterMask();
static void CAN_RemoveFilter();
static void CAN_EnableFilters();
static void CAN_DisableFilters();
static void CAN_ResetTxFIFO();
static void CAN_ResetRxFIFO();
static void CAN_EnableTx();
static void CAN_DisableTx();
static void CAN_ResetDropCount();
static void CAN_DisplayCounts();
/****** Command Table *******/
enum canFunc_MainMenuCommands
{
CAN_FUNC_CMD_SELECT_CHANNEL_MMENU,
CAN_FUNC_CMD_SELECT_PROTOCOL_MMENU,
CAN_FUNC_CMD_SELECT_BAUD_MMENU,
CAN_FUNC_CMD_RESET_CHANNEL_MMENU,
CAN_FUNC_CMD_ENABLE_TERMINATION_MMENU,
CAN_FUNC_CMD_DISABLE_TERMINATION_MMENU,
CAN_FUNC_CMD_SINGLE_LEC_MMENU,
SEPARATOR1,
CAN_FUNC_CMD_INTERRUPT_MMENU,
SEPARATOR2,
CAN_FUNC_CMD_STATUS_MMENU,
SEPARATOR3,
CAN_FUNC_CMD_SINGLE_8BYTE_XMIT_MMENU,
CAN_FUNC_CMD_SINGLE_64BYTE_XMIT_MMENU,
CAN_FUNC_CMD_RECEIVE_MMENU,
CAN_FUNC_CMD_RECEIVE_MSG_PUMP_MMENU,
SEPARATOR4,
CAN_FUNC_CMD_SCHEDULE_MSG_XMIT_MMENU,
CAN_FUNC_CMD_START_SCHEDULE_MMENU,
CAN_FUNC_CMD_STOP_SCHEDULE_MMENU,
SEPARATOR5,
CAN_FUNC_CMD_SET_FILTER_MMENU,
CAN_FUNC_CMD_GET_FILTER_MMENU,
CAN_FUNC_CMD_SET_FILTER_MASK_MMENU,
CAN_FUNC_CMD_GET_FILTER_MASK_MMENU,
CAN_FUNC_CMD_REMOVE_FILTER_MMENU,
CAN_FUNC_CMD_ENABLE_FILTERS_MMENU,
CAN_FUNC_CMD_DISABLE_FILTERS_MMENU,
SEPARATOR6,
CAN_FUNC_CMD_RESET_TX_FIFO_MMENU,
CAN_FUNC_CMD_RESET_RX_FIFO_MMENU,
CAN_FUNC_CMD_ENABLE_TX_MMENU,
CAN_FUNC_CMD_DISABLE_TX_MMENU,
CAN_FUNC_CMD_RESET_DROP_COUNT_MMENU,
CAN_FUNC_CMD_DISPLAY_COUNTS_MMENU,
SEPARATOR7,
CAN_FUNC_CMD_COUNT
};
/****** Interrupt Command Table *******/
enum canFunc_InterruptMenuCommands
{
CAN_FUNC_CMD_SET_INT_STEERING_IMENU,
CAN_FUNC_CMD_SET_INT_TRIG_TYPE_IMENU,
CAN_FUNC_CMD_SET_CHAN_INT_IMENU,
CAN_FUNC_CMD_SET_EVENT_INT_IMENU,
CAN_FUNC_CMD_SET_INT_ENABLE_IMENU,
CAN_FUNC_CMD_SET_INT_DISABLE_IMENU,
SEPARATOR_INT,
CAN_INT_FUNC_CMD_COUNT
};
/****** Status Command Table *******/
enum canFunc_StatusMenuCommands
{
CAN_FUNC_CMD_GET_CHAN_STATUS_SMENU,
CAN_FUNC_CMD_GET_CHAN_STATUS_RAW_SMENU,
CAN_FUNC_CMD_CLEAR_CHAN_STATUS_SMENU,
CAN_FUNC_CMD_CLEAR_CHAN_STATUS_RAW_SMENU,
CAN_FUNC_CMD_GET_EVENT_STATUS_SMENU,
CAN_FUNC_CMD_GET_EVENT_STATUS_RAW_SMENU,
CAN_FUNC_CMD_CLEAR_EVENT_STATUS_SMENU,
CAN_FUNC_CMD_CLEAR_EVENT_STATUS_RAW_SMENU,
SEPARATOR_STATUS,
CAN_STATUS_FUNC_CMD_COUNT
};
enum canInterruptLabels
{
CAN_EVENT_MAPPED_INTERRUPT_SET,
CAN_CHANNEL_MAPPED_INTERRUPT_SET,
CAN_INTERRUPT_LABEL_COUNT
};
struct canDemofunc_cmdtbl {
int8_t *cmdstr;
int8_t *menustr;
int32_t cmdnum;
/* void(*func)();*/
};
/****** Command Tables *******/
static struct canDemofunc_cmdtbl CAN_DemoFuncMenuCmds[] = {
{(int8_t *)"1", (int8_t *)"Set Channel", CAN_FUNC_CMD_SELECT_CHANNEL_MMENU, },\
{(int8_t *)"2", (int8_t *)"Set Protocol", CAN_FUNC_CMD_SELECT_PROTOCOL_MMENU, },\
{(int8_t *)"3", (int8_t *)"Set Baud", CAN_FUNC_CMD_SELECT_BAUD_MMENU, },\
{(int8_t *)"4", (int8_t *)"Reset Channel", CAN_FUNC_CMD_RESET_CHANNEL_MMENU, },\
{(int8_t *)"5", (int8_t *)"Enable Termination", CAN_FUNC_CMD_ENABLE_TERMINATION_MMENU, },\
{(int8_t *)"6", (int8_t *)"Disable Termination", CAN_FUNC_CMD_DISABLE_TERMINATION_MMENU,},\
{(int8_t *)"7", (int8_t *)"Get/Clear LEC", CAN_FUNC_CMD_SINGLE_LEC_MMENU, },\
{(int8_t *)"-", (int8_t *)"---------------------------",SEPARATOR1, },\
{(int8_t *)"8", (int8_t *)"Set Interrupts", CAN_FUNC_CMD_INTERRUPT_MMENU, },\
{(int8_t *)"-", (int8_t *)"---------------------------",SEPARATOR2, },\
{(int8_t *)"9", (int8_t *)"Get Statuses", CAN_FUNC_CMD_STATUS_MMENU, },\
{(int8_t *)"-", (int8_t *)"---------------------------",SEPARATOR3, },\
{(int8_t *)"A", (int8_t *)"Single 8byte Xmit", CAN_FUNC_CMD_SINGLE_8BYTE_XMIT_MMENU, },\
{(int8_t *)"B", (int8_t *)"Single 64byte Xmit", CAN_FUNC_CMD_SINGLE_64BYTE_XMIT_MMENU, },\
{(int8_t *)"C", (int8_t *)"Receive Single Msg", CAN_FUNC_CMD_RECEIVE_MMENU, },\
{(int8_t *)"D", (int8_t *)"Receive Msg Pump", CAN_FUNC_CMD_RECEIVE_MSG_PUMP_MMENU },\
{(int8_t *)"-", (int8_t *)"---------------------------",SEPARATOR4, },\
{(int8_t *)"E", (int8_t *)"Schedule Msg", CAN_FUNC_CMD_SCHEDULE_MSG_XMIT_MMENU, },\
{(int8_t *)"F", (int8_t *)"Start Schedule", CAN_FUNC_CMD_START_SCHEDULE_MMENU, },\
{(int8_t *)"G", (int8_t *)"Stop Schedule", CAN_FUNC_CMD_STOP_SCHEDULE_MMENU, },\
{(int8_t *)"-", (int8_t *)"---------------------------",SEPARATOR5, },\
{(int8_t *)"I", (int8_t *)"Set Filter", CAN_FUNC_CMD_SET_FILTER_MMENU, },\
{(int8_t *)"J", (int8_t *)"Get Filter", CAN_FUNC_CMD_GET_FILTER_MMENU, },\
{(int8_t *)"K", (int8_t *)"Set Filter Mask", CAN_FUNC_CMD_SET_FILTER_MASK_MMENU, },\
{(int8_t *)"L", (int8_t *)"Get Filter Mask", CAN_FUNC_CMD_GET_FILTER_MASK_MMENU, },\
{(int8_t *)"M", (int8_t *)"Remove Filter", CAN_FUNC_CMD_REMOVE_FILTER_MMENU, },\
{(int8_t *)"N", (int8_t *)"Enable Filters", CAN_FUNC_CMD_ENABLE_FILTERS_MMENU, },\
{(int8_t *)"O", (int8_t *)"Disable Filters", CAN_FUNC_CMD_DISABLE_FILTERS_MMENU, },\
{(int8_t *)"-", (int8_t *)"---------------------------",SEPARATOR6, },\
{(int8_t *)"U", (int8_t *)"Reset Tx FIFO", CAN_FUNC_CMD_RESET_TX_FIFO_MMENU, },\
{(int8_t *)"V", (int8_t *)"Reset Rx FIFO", CAN_FUNC_CMD_RESET_RX_FIFO_MMENU, },\
{(int8_t *)"W", (int8_t *)"Enable Tx FIFO", CAN_FUNC_CMD_ENABLE_TX_MMENU, },\
{(int8_t *)"X", (int8_t *)"Disable Tx FIFO", CAN_FUNC_CMD_DISABLE_TX_MMENU, },\
{(int8_t *)"Y", (int8_t *)"Reset Drop Count", CAN_FUNC_CMD_RESET_DROP_COUNT_MMENU, },\
{(int8_t *)"Z", (int8_t *)"Display Counts", CAN_FUNC_CMD_DISPLAY_COUNTS_MMENU, },\
{(int8_t *)"-", (int8_t *)"---------------------------",SEPARATOR7, },\
{NULL, NULL, 0, }
};
/****** Command Tables *******/
static struct canDemofunc_cmdtbl CAN_InterruptMenuCmds[] = {
{(int8_t *)"1", (int8_t *)"Set Interrupt Steering", CAN_FUNC_CMD_SET_INT_STEERING_IMENU, },\
{(int8_t *)"2", (int8_t *)"Set Interrupt Trigger Type", CAN_FUNC_CMD_SET_INT_TRIG_TYPE_IMENU,},\
{(int8_t *)"3", (int8_t *)"Set Channel Mapped Interrupt", CAN_FUNC_CMD_SET_CHAN_INT_IMENU, },\
{(int8_t *)"4", (int8_t *)"Set Event Mapped Interrupt", CAN_FUNC_CMD_SET_EVENT_INT_IMENU, },\
{(int8_t *)"5", (int8_t *)"Set Interrupt Enable", CAN_FUNC_CMD_SET_INT_ENABLE_IMENU, },\
{(int8_t *)"6", (int8_t *)"Set Interrupt Disable", CAN_FUNC_CMD_SET_INT_DISABLE_IMENU, },\
{(int8_t *)"-", (int8_t *)"---------------------------", SEPARATOR_INT, },\
{NULL, NULL, 0, }
};
static struct canDemofunc_cmdtbl CAN_StatusMenuCmds[] = {
{(int8_t *)"1", (int8_t *)"Get Chan Mapped Status", CAN_FUNC_CMD_GET_CHAN_STATUS_SMENU, },\
{(int8_t *)"2", (int8_t *)"Get Chan Mapped Status Raw", CAN_FUNC_CMD_GET_CHAN_STATUS_RAW_SMENU, },\
{(int8_t *)"3", (int8_t *)"Clear Chan Mapped Status", CAN_FUNC_CMD_CLEAR_CHAN_STATUS_SMENU, },\
{(int8_t *)"4", (int8_t *)"Clear Chan Mapped Status Raw", CAN_FUNC_CMD_CLEAR_CHAN_STATUS_RAW_SMENU, },\
{(int8_t *)"5", (int8_t *)"Get Event Mapped Status", CAN_FUNC_CMD_GET_EVENT_STATUS_SMENU, },\
{(int8_t *)"6", (int8_t *)"Get Event Mapped Status Raw", CAN_FUNC_CMD_GET_EVENT_STATUS_RAW_SMENU, },\
{(int8_t *)"7", (int8_t *)"Clear Event Mapped Status", CAN_FUNC_CMD_CLEAR_EVENT_STATUS_SMENU, },\
{(int8_t *)"8", (int8_t *)"Clear Event Mapped Status Raw", CAN_FUNC_CMD_CLEAR_EVENT_STATUS_RAW_SMENU,},\
{(int8_t *)"-", (int8_t *)"------------------------------",SEPARATOR_STATUS, },\
{NULL, NULL, 0, }
};
/***** Global Variables *****/
static bool_t globalQuit = NAI_FALSE;
static int32_t g_moduleCount = 0u;
static volatile int irqFlag = 0u;
static volatile uint32_t irqCount = 0u;
static uint32_t receivedVector = 0u;
/* Track active interrupts per channel; -1 means none */
static int32_t activeInterrupts[MAX_AR_CAN_CHANNEL_COUNT];
static uint32_t activeChannelCount = 0;
static bool_t isIsrConnected = NAI_FALSE;
static const char* eventMappedInterruptStrings[] = {
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_EMPTY_REALTIME",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_EMPTY_LATCHED",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_EMPTY_REALTIME",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_EMPTY_LATCHED",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_FULL_REALTIME",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_FULL_LATCHED",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_FULL_REALTIME",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_FULL_LATCHED",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_EMPTY_REALTIME",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_EMPTY_LATCHED",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_EMPTY_REALTIME",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_EMPTY_LATCHED",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_FULL_REALTIME",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_FULL_LATCHED",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_FULL_REALTIME",
"NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_FULL_LATCHED"
};
static const char* channelMappedInterruptStrings[] = {
"NAIBRD_AR_CAN_STATUS_BIT_LATCHED",
"NAIBRD_AR_CAN_STATUS_BIT_REALTIME",
"NAIBRD_AR_CAN_NEW_RX_DATA_LATCHED",
"NAIBRD_AR_CAN_NEW_RX_DATA_REALTIME"
};
static const char* interruptSteeringStrings[] = {
"",
"NAIBRD_INT_STEERING_VME",
"NAIBRD_INT_STEERING_ONBOARD_ARM",
"",
"",
"NAIBRD_INT_STEERING_PCIE",
"NAIBRD_INT_STEERING_CPCI"
};
static const char* interruptTriggerTypeStrings[] = {
"NAIBRD_INT_TRIGGER_TYPE_EDGE",
"NAIBRD_INT_TRIGGER_TYPE_LEVEL"
};
/**************************************************************************************************************/
/**
<summary>
AR_CAN_Basic_Ops illustrates basic interactions with the AR_CAN function module.
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t naiapp_AR_CAN_BasicOps(void)
#else
int32_t main(void)
#endif
{
bool_t stop = NAI_FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
Init_UserParams();
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);
/* Set global var userInput.nCardIdx */
userInput.nCardIdx = cardIndex;
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Set global var g_moduleCount */
g_moduleCount = moduleCnt;
/* Query the user for the module number */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &userInput.nModuleNumber);
if (stop != NAI_TRUE)
{
Run_CAN_DisplayCANChoices();
}
}
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;
}
void Init_UserParams(void)
{
int i;
userInput.nCardIdx = -1;
userInput.nModuleNumber = -1;
userInput.nChannelNumber = -1;
userInput.nProtocolIndex = -1;
userInput.nBaudBaseRate = -1;
userInput.nBaudDataRate = -1;
userInput.nInterruptSteering = -1;
userInput.nInterruptTriggerType = -1;
userInput.nInterrupt = -1;
userInput.interruptLabel = -1;
for (i = 0; i < MAX_AR_CAN_CHANNEL_COUNT; i++) {
chanConfig[i].nProtocolIndex = -1;
chanConfig[i].nBaudBaseRate = -1;
chanConfig[i].nBaudDataRate = -1;
chanConfig[i].nInterruptSteering = -1;
chanConfig[i].nInterruptTriggerType = -1;
chanConfig[i].nInterrupt = -1;
chanConfig[i].interruptLabel = -1;
}
for (i = 0; i < MAX_AR_CAN_CHANNEL_COUNT; i++)
activeInterrupts[i] = -1;
activeChannelCount = 0;
isIsrConnected = NAI_FALSE;
return;
}
void Run_CAN_DisplayCANChoices(void)
{
bool_t bQuit = NAI_FALSE;
int32_t cmdIdx;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
do
{
if (globalQuit)
break;
Show_CanDemoFunc_Commands();
naiif_printf("\r\nType CAN command or %c to quit : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
for (cmdIdx = 0; cmdIdx < CAN_FUNC_CMD_COUNT; cmdIdx++)
{
if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)CAN_DemoFuncMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
break;
}
switch (cmdIdx)
{
case CAN_FUNC_CMD_SELECT_CHANNEL_MMENU:
CAN_SetChan();
break;
case CAN_FUNC_CMD_SELECT_PROTOCOL_MMENU:
CAN_SetProtocol();
break;
case CAN_FUNC_CMD_SELECT_BAUD_MMENU:
CAN_SetBaud();
break;
case CAN_FUNC_CMD_RESET_CHANNEL_MMENU:
CAN_ResetChannel();
break;
case CAN_FUNC_CMD_ENABLE_TERMINATION_MMENU:
CAN_SetTermination(NAI_TRUE);
break;
case CAN_FUNC_CMD_DISABLE_TERMINATION_MMENU:
CAN_SetTermination(NAI_FALSE);
break;
case CAN_FUNC_CMD_SINGLE_LEC_MMENU:
CAN_GET_ClearLEC();
break;
case CAN_FUNC_CMD_INTERRUPT_MMENU:
CAN_SetInterrupts();
break;
case CAN_FUNC_CMD_STATUS_MMENU:
CAN_GetStatuses();
break;
case CAN_FUNC_CMD_SINGLE_8BYTE_XMIT_MMENU:
CAN_Single8ByteXmit();
break;
case CAN_FUNC_CMD_SINGLE_64BYTE_XMIT_MMENU:
CAN_Single64ByteXmit();
break;
case CAN_FUNC_CMD_RECEIVE_MMENU:
CAN_ReceiveMsg();
break;
case CAN_FUNC_CMD_RECEIVE_MSG_PUMP_MMENU:
CAN_ReceiveMsgPump();
break;
case CAN_FUNC_CMD_SCHEDULE_MSG_XMIT_MMENU:
CAN_ScheduleMsg();
break;
case CAN_FUNC_CMD_START_SCHEDULE_MMENU:
CAN_StartSchedule();
break;
case CAN_FUNC_CMD_STOP_SCHEDULE_MMENU:
CAN_StopSchedule();
break;
case CAN_FUNC_CMD_SET_FILTER_MMENU:
CAN_SetFilter();
break;
case CAN_FUNC_CMD_GET_FILTER_MMENU:
CAN_GetFilter();
break;
case CAN_FUNC_CMD_SET_FILTER_MASK_MMENU:
CAN_SetFilterMask();
break;
case CAN_FUNC_CMD_GET_FILTER_MASK_MMENU:
CAN_GetFilterMask();
break;
case CAN_FUNC_CMD_REMOVE_FILTER_MMENU:
CAN_RemoveFilter();
break;
case CAN_FUNC_CMD_ENABLE_FILTERS_MMENU:
CAN_EnableFilters();
break;
case CAN_FUNC_CMD_DISABLE_FILTERS_MMENU:
CAN_DisableFilters();
break;
case CAN_FUNC_CMD_RESET_TX_FIFO_MMENU:
CAN_ResetTxFIFO();
break;
case CAN_FUNC_CMD_RESET_RX_FIFO_MMENU:
CAN_ResetRxFIFO();
break;
case CAN_FUNC_CMD_ENABLE_TX_MMENU:
CAN_EnableTx();
break;
case CAN_FUNC_CMD_DISABLE_TX_MMENU:
CAN_DisableTx();
break;
case CAN_FUNC_CMD_RESET_DROP_COUNT_MMENU:
CAN_ResetDropCount();
break;
case CAN_FUNC_CMD_DISPLAY_COUNTS_MMENU:
CAN_DisplayCounts();
break;
default:
break;
}
}
} while (bQuit == NAI_FALSE);
if (bQuit)
globalQuit = NAI_TRUE;
return;
}
static void Show_CanDemoFunc_Commands(void)
{
int i;
naiif_printf("\r\n\t\t CAN Demo Program with FD (flexible data).");
naiif_printf("\r\n\t\t ==========================\r\n");
naiif_printf("\r\n\r\nCommands");
naiif_printf("\r\n--------");
for (i = 0; i < CAN_FUNC_CMD_COUNT && CAN_DemoFuncMenuCmds[i].cmdstr != NULL; i++)
naiif_printf("\r\n%s\t%s", CAN_DemoFuncMenuCmds[i].cmdstr, CAN_DemoFuncMenuCmds[i].menustr);
naiif_printf("\r\n");
}
static void Show_CanInterruptFunc_Commands(void)
{
int i = 0;
naiif_printf("\r\n CAN Interrupts.");
naiif_printf("\r\n ==========================\r\n");
naiif_printf("\r\n\r\nCommands");
naiif_printf("----------------------------\r\n");
for (i = 0; i < CAN_INT_FUNC_CMD_COUNT && CAN_InterruptMenuCmds[i].cmdstr != NULL; i++)
naiif_printf("\r\n%s\t%s", CAN_InterruptMenuCmds[i].cmdstr, CAN_InterruptMenuCmds[i].menustr);
naiif_printf("\r\n");
}
static void Show_CanStatusFunc_Commands(void)
{
int i = 0;
naiif_printf("\r\n CAN Statuses.");
naiif_printf("\r\n ==========================\r\n");
naiif_printf("\r\n\r\nCommands");
naiif_printf("----------------------------\r\n");
for (i = 0; i < CAN_STATUS_FUNC_CMD_COUNT && CAN_StatusMenuCmds[i].cmdstr != NULL; i++)
naiif_printf("\r\n%s\t%s", CAN_StatusMenuCmds[i].cmdstr, CAN_StatusMenuCmds[i].menustr);
naiif_printf("\r\n");
}
static void myIsr(uint32_t vector)
{
int32_t chanIndex = -1;
uint32_t outStatusRaw = 0u;
receivedVector = vector;
irqCount++;
irqFlag = 1; /* main loop clears this */
naiif_printf("\r\n*** INTERRUPT DETECTED ***\r\n");
naiif_printf("Received Vector: 0x%08X\r\n", receivedVector);
naiif_printf("Interrupt Count: %u\r\n", irqCount);
/* Map vector 0xA1-0xA8 to channel 1-8 */
if (receivedVector >= 0xA1 && receivedVector <= 0xA8) {
chanIndex = (receivedVector - 0xA1); /* 0-based index */
}
if (chanIndex < 0 || chanIndex >= MAX_AR_CAN_CHANNEL_COUNT) {
naiif_printf("Unknown interrupt vector!\r\n");
return;
}
if (chanConfig[chanIndex].interruptLabel == CAN_CHANNEL_MAPPED_INTERRUPT_SET)
{
check_status(naibrd_AR_CAN_GetChanMappedStatusRaw(userInput.nCardIdx, userInput.nModuleNumber,
(naibrd_ar_can_chan_mapped_status_type_t)chanConfig[chanIndex].nInterrupt, &outStatusRaw));
naiif_printf("Raw Channel Mapped Status: 0x%08X\r\n", outStatusRaw);
naiif_printf("Channel Mapped Status Type: %s\r\n", channelMappedInterruptStrings[chanConfig[chanIndex].nInterrupt]);
}
else if (chanConfig[chanIndex].interruptLabel == CAN_EVENT_MAPPED_INTERRUPT_SET)
{
check_status(naibrd_AR_CAN_GetEventMappedStatusRaw(userInput.nCardIdx, userInput.nModuleNumber, chanIndex + 1,
NAI_STATUS_LATCHED, NAIBRD_AR_CAN_EVENT_MAP_FIFO, &outStatusRaw));
naiif_printf("Raw Event Mapped Status: 0x%08X\r\n", outStatusRaw);
naiif_printf("Event Mapped Type: %s\r\n", eventMappedInterruptStrings[chanConfig[chanIndex].nInterrupt]);
}
else
{
naiif_printf("Invalid interrupt label!\r\n");
}
}
static void CAN_SetChan()
{
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt = 0u;
int32_t tempChannelNumber = 0u;
int32_t newChanIndex = 0u;
int32_t oldChanIndex = 0u;
naiif_printf("\r\nEnter <<Channel>> Number or %c to quit [[default = 1]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit) {
if (inputResponseCnt == 0)
tempChannelNumber = 1;
else
tempChannelNumber = atoi((const char *)inputBuffer);
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, tempChannelNumber))
{
naiif_printf("\r\nInvalid Channel Number selected, please select one of the listed options.");
}
else
{
/* Save old channel settings */
if (userInput.nChannelNumber > 0)
{
oldChanIndex = userInput.nChannelNumber - 1;
chanConfig[oldChanIndex].nProtocolIndex = userInput.nProtocolIndex;
chanConfig[oldChanIndex].nBaudBaseRate = userInput.nBaudBaseRate;
chanConfig[oldChanIndex].nBaudDataRate = userInput.nBaudDataRate;
chanConfig[oldChanIndex].nInterruptSteering = userInput.nInterruptSteering;
chanConfig[oldChanIndex].nInterruptTriggerType = userInput.nInterruptTriggerType;
chanConfig[oldChanIndex].nInterrupt = userInput.nInterrupt;
chanConfig[oldChanIndex].interruptLabel = userInput.interruptLabel;
}
/* Switch to new channel */
userInput.nChannelNumber = tempChannelNumber;
/* Load stored settings */
newChanIndex = tempChannelNumber - 1;
userInput.nProtocolIndex = chanConfig[newChanIndex].nProtocolIndex;
userInput.nBaudBaseRate = chanConfig[newChanIndex].nBaudBaseRate;
userInput.nBaudDataRate = chanConfig[newChanIndex].nBaudDataRate;
userInput.nInterruptSteering = chanConfig[newChanIndex].nInterruptSteering;
userInput.nInterruptTriggerType = chanConfig[newChanIndex].nInterruptTriggerType;
userInput.nInterrupt = chanConfig[newChanIndex].nInterrupt;
userInput.interruptLabel = chanConfig[newChanIndex].interruptLabel;
naiif_printf("\r\nSwitched to channel %d\r\n", tempChannelNumber);
}
}
}
static void CAN_SetProtocol()
{
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
int32_t chanIndex = 0u;
naiif_printf("---------------------\r\n");
naiif_printf("CAN AB Protocol ENTER: '0'\r\n");
naiif_printf("CAN FD Protocol ENTER: '1'\r\n");
naiif_printf("---------------------\r\n");
naiif_printf("\r\nEnter Protocol Index Number or %c to quit [[default = 1 (CAN FD)]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
userInput.nProtocolIndex = 1;
else
userInput.nProtocolIndex = atoi((const char *)inputBuffer);
if (userInput.nProtocolIndex > 1 || userInput.nProtocolIndex < 0)
{
naiif_printf("Invalid protocol index detected. Defaulting to CAN-FD - protocol index 1\r\n");
userInput.nProtocolIndex = 1;
}
if (userInput.nChannelNumber > 0)
{
chanIndex = userInput.nChannelNumber - 1;
chanConfig[chanIndex].nProtocolIndex = userInput.nProtocolIndex;
}
}
}
static void CAN_SetBaud()
{
nai_status_t status;
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
naibrd_ar_can_low_rate_type_t origBaseRate;
naibrd_ar_can_high_rate_type_t origDataRate;
int32_t chanIndex = 0u;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("Base Rate 1000K ENTER: '0'\r\n");
naiif_printf("Base Rate 500K ENTER: '1'\r\n");
naiif_printf("Base Rate 250K ENTER: '3'\r\n");
naiif_printf("----------------------------\r\n");
naiif_printf("\r\nEnter Base Rate Index Number or %c to quit [[default = 1 (500K)]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
userInput.nBaudBaseRate = 1;
else
userInput.nBaudBaseRate = atoi((const char *)inputBuffer);
if (userInput.nBaudBaseRate > 3 || userInput.nBaudBaseRate < 0)
{
naiif_printf("Invalid Base Rate index detected. Defaulting to 500K - Base Rate index 1\r\n");
userInput.nBaudBaseRate = 1;
}
}
naiif_printf("\r\n---------------------------------\r\n");
naiif_printf("Data Rate 4000K ENTER: '6'\r\n");
naiif_printf("Data Rate 3000K ENTER: '7'\r\n");
naiif_printf("Data Rate 2000K ENTER: '8'\r\n");
naiif_printf("Data Rate 1000K ENTER: '9'\r\n");
naiif_printf("---------------------------------\r\n");
naiif_printf("\r\nEnter Data Rate Index Number or %c to quit [[default = 8 (2000K)]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
userInput.nBaudDataRate = 8;
else
userInput.nBaudDataRate = atoi((const char *)inputBuffer);
if (userInput.nBaudDataRate > 9 || userInput.nBaudDataRate < 6)
{
naiif_printf("Invalid Data Rate index detected. Defaulting to 2000K - Data Rate index 8\r\n");
userInput.nBaudDataRate = 8;
}
}
status = naibrd_AR_CAN_GetBaudRate(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &origBaseRate, &origDataRate);
if (NAI_SUCCESS == status)
naiif_printf("Orig Base Rate: %d Orig Data Rate: %d\r\n", (int32_t)origBaseRate, (int32_t)origDataRate);
else
naiif_printf("ERROR: naibrd_AR_CAN_GetBaudRate returned status: %d\r\n", status);
status = naibrd_AR_CAN_SetBaudRate(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
(naibrd_ar_can_low_rate_type_t)userInput.nBaudBaseRate, (naibrd_ar_can_high_rate_type_t)userInput.nBaudDataRate);
if (NAI_SUCCESS == status)
{
naiif_printf("Successfully set base and data baud rates for channel %d\r\n", userInput.nChannelNumber);
if (userInput.nChannelNumber > 0)
{
chanIndex = userInput.nChannelNumber - 1;
chanConfig[chanIndex].nBaudBaseRate = userInput.nBaudBaseRate;
chanConfig[chanIndex].nBaudDataRate = userInput.nBaudDataRate;
}
}
else
naiif_printf("ERROR: naibrd_AR_CAN_SetBaudRate returned status: %d\r\n", status);
}
static void CAN_ResetChannel()
{
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_ChannelReset(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
if (NAI_SUCCESS == status)
naiif_printf("Successfully performed Channel Reset for channel %d\r\n", userInput.nChannelNumber);
else
naiif_printf("ERROR: naibrd_AR_CAN_ChannelReset returned status: %d\r\n", status);
}
static void CAN_SetTermination(bool_t enableTermination)
{
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_SetTermination(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, enableTermination);
if (NAI_SUCCESS == status)
{
if (enableTermination)
naiif_printf("Successfully Enabled Termination for channel %d\r\n", userInput.nChannelNumber);
else
naiif_printf("Successfully Disabled Termination for channel %d\r\n", userInput.nChannelNumber);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_SetTermination returned status: %d\r\n", status);
}
}
static void CAN_GET_ClearLEC(void)
{
#ifdef ENHANCED_LEC
uint8_t outbusError = 0;
uint16_t outlastError = 0; /* Return value of naibrd_AR_CAN_GetLastError */
#else
int32_t outlastError = 0; /* Return value of naibrd_AR_CAN_GetLastError */
#endif
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
#ifdef ENHANCED_LEC
status = naibrd_AR_CAN_GetEnhancedLastError(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &outlastError,
&outbusError);
naiif_printf("Channel %d LEC value is %d Bus error is %d and status = %d\r\n", userInput.nChannelNumber, outlastError, outbusError,
status);
#else
status = naibrd_AR_CAN_GetLastError(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &outlastError);
naiif_printf("Channel %d LEC value is %d and status = %d\r\n", userInput.nChannelNumber, outlastError, status);
#endif
naiif_printf("\r\nShould we clear the LEC YES(1) NO(0) %c to quit [[default = 0]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
if( (atoi((const char *)inputBuffer) == 1) )
{
naiif_printf("inputBuffer value is %d \r\n", (atoi((const char *)inputBuffer)));
naibrd_AR_CAN_ResetLastError(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
}
}
}
return;
}
static nai_status_t CAN_SetInterrupts()
{
bool_t bQuit = NAI_FALSE;
int32_t cmdIdx = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt = 0;
int32_t cardIndex = userInput.nCardIdx;
int32_t module = userInput.nModuleNumber;
int32_t chanNum = userInput.nChannelNumber;
nai_status_t status = NAI_SUCCESS;
naibrd_ar_can_fifo_event_mapped_status_type_t eventMapInterruptStatus;
naibrd_ar_can_chan_mapped_status_type_t chanMapInterruptStatus;
uint32_t outvector = 0u;
naibrd_int_steering_t interruptSteering, outsteering;
naibrd_int_trigger_type_t interruptTriggerType, outtriggerType;
bool_t outenable = NAI_FALSE;
naibrd_ar_can_event_mapped_category_type_t categoryType = NAIBRD_AR_CAN_EVENT_MAP_FIFO;
int32_t chanIndex = 0u;
uint32_t interruptVector = 0u;
if (!checkChannelNumber(cardIndex, module, chanNum))
return NAI_ERROR_INVALID_CHANNEL;
do
{
Show_CanInterruptFunc_Commands();
naiif_printf("\r\nInterrupt settings will apply to Channel %d.",chanNum);
naiif_printf("\r\nType Interrupt command or %c to return to main menu : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
for (cmdIdx = 0; cmdIdx < CAN_INT_FUNC_CMD_COUNT; cmdIdx++)
{
if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)CAN_InterruptMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
break;
}
switch (cmdIdx)
{
case CAN_FUNC_CMD_SET_INT_STEERING_IMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_INT_STEERING_VME ENTER: '1'\r\n");
naiif_printf("NAIBRD_INT_STEERING_ONBOARD_ARM ENTER: '2'\r\n");
naiif_printf("NAIBRD_INT_STEERING_PCIE ENTER: '5'\r\n");
naiif_printf("NAIBRD_INT_STEERING_CPCI ENTER: '6'\r\n");
naiif_printf("----------------------------\r\n");
naiif_printf("\r\nEnter Steering Index or %c to quit [[default = 2 (NAIBRD_INT_STEERING_ONBOARD_ARM)]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
userInput.nInterruptSteering = 2;
else
userInput.nInterruptSteering = atoi((const char*)inputBuffer);
if (userInput.nInterruptSteering != 1 &&
userInput.nInterruptSteering != 2 &&
userInput.nInterruptSteering != 5 &&
userInput.nInterruptSteering != 6)
{
naiif_printf("Invalid Steering index detected. Defaulting to NAIBRD_INT_STEERING_ONBOARD_ARM, Steering index 1\r\n");
userInput.nInterruptSteering = 2;
}
naiif_printf("Interrupt Steering Selected: %s\r\n", interruptSteeringStrings[userInput.nInterruptSteering]);
if (userInput.nChannelNumber > 0)
{
chanIndex = userInput.nChannelNumber - 1;
chanConfig[chanIndex].nInterruptSteering = userInput.nInterruptSteering;
}
}
break;
case CAN_FUNC_CMD_SET_INT_TRIG_TYPE_IMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_INT_TRIGGER_TYPE_EDGE ENTER: '0'\r\n");
naiif_printf("NAIBRD_INT_TRIGGER_TYPE_LEVEL ENTER: '1'\r\n");
naiif_printf("----------------------------\r\n");
naiif_printf("\r\nEnter Trigger Type Index or %c to quit [[default = 0 (NAIBRD_INT_TRIGGER_TYPE_EDGE)]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
userInput.nInterruptTriggerType = 0;
else
userInput.nInterruptTriggerType = atoi((const char *)inputBuffer);
if (userInput.nInterruptTriggerType != 0 &&
userInput.nInterruptTriggerType != 1)
{
naiif_printf("Invalid Trigger Type index detected. Defaulting to NAIBRD_INT_TRIGGER_TYPE_EDGE, index 0\r\n");
userInput.nInterruptTriggerType = 0;
}
naiif_printf("Interrupt Trigger Type Selected: %s\r\n", interruptTriggerTypeStrings[userInput.nInterruptTriggerType]);
if (userInput.nChannelNumber > 0)
{
chanIndex = userInput.nChannelNumber - 1;
chanConfig[chanIndex].nInterruptTriggerType = userInput.nInterruptTriggerType;
}
}
break;
case CAN_FUNC_CMD_SET_CHAN_INT_IMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_STATUS_BIT ENTER: '0'\r\n");
naiif_printf("NAIBRD_AR_CAN_NEW_RX_DATA ENTER: '2'\r\n");
naiif_printf("----------------------------\r\n");
naiif_printf("\r\nEnter Interrupt Index or %c to quit [[default = 2 (NAIBRD_AR_CAN_NEW_RX_DATA)]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
userInput.nInterrupt = 2;
else
{
userInput.nInterrupt = atoi((const char *)inputBuffer);
if (userInput.nInterrupt % 2 == 0 && userInput.nInterrupt <= 2)
{
naiif_printf("Channel Mapped Interrupt Selected: %s\r\n", channelMappedInterruptStrings[userInput.nInterrupt]);
}
else
{
naiif_printf("Invalid Interrupt index. Defaulting to NAIBRD_AR_CAN_NEW_RX_DATA.\r\n");
userInput.nInterrupt = 2;
}
}
userInput.interruptLabel = CAN_CHANNEL_MAPPED_INTERRUPT_SET;
if (userInput.nChannelNumber > 0)
{
chanIndex = userInput.nChannelNumber - 1;
chanConfig[chanIndex].nInterrupt = userInput.nInterrupt;
chanConfig[chanIndex].interruptLabel = userInput.interruptLabel;
}
}
break;
case CAN_FUNC_CMD_SET_EVENT_INT_IMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_EMPTY, ENTER: 'B'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_EMPTY, ENTER: 'D'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_FULL, ENTER: 'F'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_FULL, ENTER: 'H'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_EMPTY, ENTER: 'J'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_EMPTY, ENTER: 'L'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_FULL, ENTER: 'N'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_FULL, ENTER: 'P'\r\n");
naiif_printf("----------------------------\r\n");
naiif_printf("\r\nEnter Interrupt Index or %c to quit [[default = F (NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_FULL)]]: ",
NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
userInput.nInterrupt = 5;
else
{
char c = inputBuffer[0];
if ((c >= 'A' && c <= 'P') || (c >= 'a' && c <= 'p'))
{
userInput.nInterrupt = (c & ~0x20) - 'A'; /* case-insensitive */
}
else
{
naiif_printf("Invalid Interrupt index. Defaulting to F.\r\n");
userInput.nInterrupt = 'F' - 'A';
}
}
userInput.interruptLabel = CAN_EVENT_MAPPED_INTERRUPT_SET;
naiif_printf("Event Mapped Interrupt Selected: %s\r\n", eventMappedInterruptStrings[userInput.nInterrupt]);
if (userInput.nChannelNumber > 0)
{
chanIndex = userInput.nChannelNumber - 1;
chanConfig[chanIndex].nInterrupt = userInput.nInterrupt;
chanConfig[chanIndex].interruptLabel = userInput.interruptLabel;
}
}
break;
case CAN_FUNC_CMD_SET_INT_ENABLE_IMENU:
if (activeInterrupts[chanNum - 1] != -1)
{
if(chanConfig[chanNum - 1].interruptLabel == CAN_EVENT_MAPPED_INTERRUPT_SET)
naiif_printf("Channel %d already has interrupt %s enabled. Disable it first.\r\n",chanNum,
eventMappedInterruptStrings[userInput.nInterrupt]);
else
naiif_printf("Channel %d already has interrupt %s enabled. Disable it first.\r\n",chanNum,
channelMappedInterruptStrings[userInput.nInterrupt]);
break;
}
if (userInput.nInterrupt == -1)
{
naiif_printf("No Interrupt set. Please choose an Interrupt first.\r\n");
break;
}
else if (userInput.nInterruptSteering == -1)
{
naiif_printf("No Steering set. Please choose an Interrupt Steering first.\r\n");
break;
}
else if (userInput.nInterruptTriggerType == -1)
{
naiif_printf("No Trigger Type set. Please choose an Interrupt Trigger Type first.\r\n");
break;
}
interruptSteering = (naibrd_int_steering_t)userInput.nInterruptSteering;
interruptTriggerType = (naibrd_int_trigger_type_t)userInput.nInterruptTriggerType;
/* Set interrupt vector based on the desired channel */
switch (chanNum)
{
case 1:
interruptVector = 0x000000A1u;
break;
case 2:
interruptVector = 0x000000A2u;
break;
case 3:
interruptVector = 0x000000A3u;
break;
case 4:
interruptVector = 0x000000A4u;
break;
case 5:
interruptVector = 0x000000A5u;
break;
case 6:
interruptVector = 0x000000A6u;
break;
case 7:
interruptVector = 0x000000A7u;
break;
case 8:
interruptVector = 0x000000A8u;
break;
default:
status = NAI_ERROR_INVALID_CHANNEL;
interruptVector = 0x0u;
break;
}
if (status == NAI_SUCCESS)
{ /* Make sure interrupt is cleared before we start */
if (chanConfig[chanNum - 1].interruptLabel == CAN_EVENT_MAPPED_INTERRUPT_SET)
{
eventMapInterruptStatus = (naibrd_ar_can_fifo_event_mapped_status_type_t)userInput.nInterrupt;
check_status(naibrd_AR_CAN_ClearEventMappedStatusBit(cardIndex, module, chanNum, eventMapInterruptStatus));
}
else
{
chanMapInterruptStatus = (naibrd_ar_can_chan_mapped_status_type_t)userInput.nInterrupt;
if ((userInput.nInterrupt % 2) != 0)
{
check_status(naibrd_AR_CAN_ClearChanMappedStatusBit(cardIndex, module, chanNum,
(naibrd_ar_can_chan_mapped_status_type_t)(userInput.nInterrupt - 1)));
}
else
{
check_status(naibrd_AR_CAN_ClearChanMappedStatusBit(cardIndex, module, chanNum, chanMapInterruptStatus));
}
}
}
if (!isIsrConnected)
{
status = naibrd_ConnectISR(cardIndex, myIsr);
if (status == NAI_SUCCESS)
{
isIsrConnected = NAI_TRUE;
}
else if (status == NAI_ERROR_NOT_SUPPORTED)
{
naiif_printf("\r\n**Interrupts are either not supported on this platform or not enabled**\r\n");
}
else
{
naiif_printf("\r\n**Failed to connect ISR!**\r\n");
}
}
if (chanConfig[chanNum - 1].interruptLabel == CAN_EVENT_MAPPED_INTERRUPT_SET)
{
check_status(naibrd_AR_CAN_SetEventMappedInterruptTriggerType(cardIndex, module, chanNum,
eventMapInterruptStatus, interruptTriggerType));
check_status(naibrd_AR_CAN_SetEventMappedInterruptVector(cardIndex, module, chanNum, categoryType,
interruptVector));
check_status(naibrd_AR_CAN_SetEventMappedInterruptSteering(cardIndex, module, chanNum, categoryType,
interruptSteering));
check_status(naibrd_AR_CAN_SetEventMappedInterruptEnable(cardIndex, module, chanNum, eventMapInterruptStatus,
NAI_TRUE));
/* Get Interrupt Config */
check_status(naibrd_AR_CAN_GetEventMappedInterruptTriggerType(cardIndex, module, chanNum, eventMapInterruptStatus,
&outtriggerType));
check_status(naibrd_AR_CAN_GetEventMappedInterruptVector(cardIndex, module, chanNum, categoryType, &outvector));
check_status(naibrd_AR_CAN_GetEventMappedInterruptSteering(cardIndex, module, chanNum, categoryType, &outsteering));
check_status(naibrd_AR_CAN_GetEventMappedInterruptEnable(cardIndex, module, chanNum, eventMapInterruptStatus,
&outenable));
}
else if (chanConfig[chanNum - 1].interruptLabel == CAN_CHANNEL_MAPPED_INTERRUPT_SET)
{
check_status(naibrd_AR_CAN_SetChanMappedInterruptTriggerType(cardIndex, module, chanNum, chanMapInterruptStatus,
interruptTriggerType));
check_status(naibrd_AR_CAN_SetChanMappedInterruptVector(cardIndex, module, chanMapInterruptStatus,
interruptVector));
check_status(naibrd_AR_CAN_SetChanMappedInterruptSteering(cardIndex, module, chanMapInterruptStatus,
interruptSteering));
check_status(naibrd_AR_CAN_SetChanMappedInterruptEnable(cardIndex, module, chanNum, chanMapInterruptStatus,
NAI_TRUE));
/* Get Interrupt Config */
check_status(naibrd_AR_CAN_GetChanMappedInterruptTriggerType(cardIndex, module, chanNum, chanMapInterruptStatus,
&outtriggerType));
check_status(naibrd_AR_CAN_GetChanMappedInterruptVector(cardIndex, module, chanMapInterruptStatus, &outvector));
check_status(naibrd_AR_CAN_GetChanMappedInterruptSteering(cardIndex, module, chanMapInterruptStatus, &outsteering));
check_status(naibrd_AR_CAN_GetChanMappedInterruptEnable(cardIndex, module, chanNum, chanMapInterruptStatus,
&outenable));
}
/* Mark channel as active if not already and connect ISR if this is the first active channel */
if (activeInterrupts[chanNum - 1] == -1) {
activeInterrupts[chanNum - 1] = userInput.nInterrupt;
activeChannelCount++;
}
naiif_printf("\r\nInterrupt Configuration\r\n");
naiif_printf("=======================\r\n");
naiif_printf("Card Index:%d\r\n", cardIndex);
naiif_printf("Module Number:%d\r\n", module);
naiif_printf("Channel:%d\r\n", chanNum);
naiif_printf("Trigger Type: %s\r\n", outtriggerType == NAIBRD_INT_TRIGGER_TYPE_EDGE ? "EDGE" : "LEVEL");
naiif_printf("Vector: 0x%x\r\n", outvector);
naiif_printf("Steering: ");
switch (outsteering)
{
case NAIBRD_INT_STEERING_VME:
naiif_printf("VME\r\n");
break;
case NAIBRD_INT_STEERING_ONBOARD_ARM:
naiif_printf("Onboard ARM\r\n");
break;
case NAIBRD_INT_STEERING_PCIE:
naiif_printf("PCIE\r\n");
break;
case NAIBRD_INT_STEERING_CPCI:
naiif_printf("CPCI\r\n");
break;
}
if (chanConfig[chanNum - 1].interruptLabel == CAN_CHANNEL_MAPPED_INTERRUPT_SET)
naiif_printf("Interrupt enabled. Interrupt will trigger on: %s\r\n",
channelMappedInterruptStrings[userInput.nInterrupt]);
else if (chanConfig[chanNum - 1].interruptLabel == CAN_EVENT_MAPPED_INTERRUPT_SET)
naiif_printf("Interrupt enabled. Interrupt will trigger on: %s\r\n",
eventMappedInterruptStrings[userInput.nInterrupt]);
else
naiif_printf("Interrupt enabled, but unknown interrupt label!\r\n");
break;
case CAN_FUNC_CMD_SET_INT_DISABLE_IMENU:
if (userInput.nInterrupt == -1)
{
naiif_printf("No Interrupt set. Please choose an Interrupt first.\r\n");
break;
}
else
{
if (chanConfig[chanNum - 1].interruptLabel == CAN_EVENT_MAPPED_INTERRUPT_SET)
{
status = naibrd_AR_CAN_SetEventMappedInterruptEnable(cardIndex, module,
chanNum, (naibrd_ar_can_fifo_event_mapped_status_type_t)userInput.nInterrupt, NAI_FALSE);
if (status == NAI_SUCCESS)
{
naiif_printf("Interrupt %s disabled.\r\n", eventMappedInterruptStrings[userInput.nInterrupt]);
}
}
else if (chanConfig[chanNum - 1].interruptLabel == CAN_CHANNEL_MAPPED_INTERRUPT_SET)
{
status = naibrd_AR_CAN_SetChanMappedInterruptEnable(cardIndex, module,
chanNum, (naibrd_ar_can_chan_mapped_status_type_t)userInput.nInterrupt, NAI_FALSE);
if (status == NAI_SUCCESS)
{
naiif_printf("Interrupt %s disabled.\r\n", channelMappedInterruptStrings[userInput.nInterrupt]);
if (userInput.nChannelNumber > 0) {
chanIndex = userInput.nChannelNumber - 1;
chanConfig[chanIndex].nInterrupt = -1;
chanConfig[chanIndex].interruptLabel = -1;
chanConfig[chanIndex].nInterruptSteering = -1;
chanConfig[chanIndex].nInterruptTriggerType = -1;
}
}
}
else
{
naiif_printf("Error Disabling Interrupt");
break;
}
if (status == NAI_SUCCESS)
{
/* Clear this channel's active interrupt */
if (activeInterrupts[chanNum - 1 ] != -1)
{
activeInterrupts[chanNum - 1 ] = -1;
if (activeChannelCount > 0)
{
activeChannelCount--;
}
}
userInput.nInterrupt = -1;
/* Disconnect ISR if last channel was disabled */
if (activeChannelCount == 0 && isIsrConnected)
{
status = naibrd_DisconnectISR(cardIndex);
if (status == NAI_SUCCESS)
{
isIsrConnected = NAI_FALSE;
naiif_printf("ISR disconnected.\r\n");
}
else
{
naiif_printf("**Failed to disconnect ISR!**\r\n");
}
}
}
}
break;
default:
break;
}
}
} while (bQuit == NAI_FALSE);
return status;
}
static void CAN_GetStatuses()
{
uint32_t outstatusRaw = 0u;
nai_status_bit_t outstatusBit;
uint32_t statusType = 0u;
uint32_t statusRaw = 0xFFu;
uint32_t accessType = 0u;
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt = 0;
int32_t cmdIdx = 0;
do
{
Show_CanStatusFunc_Commands();
naiif_printf("\r\nSelected Statuses will apply to Channel %d.", userInput.nChannelNumber);
naiif_printf("\r\nType Status command or %c to return to main menu : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
for (cmdIdx = 0; cmdIdx < CAN_STATUS_FUNC_CMD_COUNT; cmdIdx++)
{
if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)CAN_StatusMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
break;
}
switch (cmdIdx)
{
case CAN_FUNC_CMD_GET_CHAN_STATUS_SMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_STATUS_BIT_LATCHED ENTER: '0'\r\n");
naiif_printf("NAIBRD_AR_CAN_STATUS_BIT_REALTIME ENTER: '1'\r\n");
naiif_printf("NAIBRD_AR_CAN_NEW_RX_DATA_LATCHED ENTER: '2'\r\n");
naiif_printf("NAIBRD_AR_CAN_NEW_RX_DATA_REALTIME ENTER: '3'\r\n");
naiif_printf("--------------------------------\r\n");
naiif_printf("\r\nEnter Status Index or %c to quit [[default = 3 (NAIBRD_AR_CAN_NEW_RX_DATA_REALTIME)]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
statusType = 3;
else
statusType = atoi((const char *)inputBuffer);
if (statusType < 0 || statusType > 3)
{
naiif_printf("Invalid Status index detected. Defaulting to NAIBRD_AR_CAN_NEW_RX_DATA_REALTIME, Status index 3\r\n");
statusType = 3;
}
check_status(naibrd_AR_CAN_GetChanMappedStatusBit(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
(naibrd_ar_can_chan_mapped_status_type_t)statusType, &outstatusBit));
naiif_printf("Channel %d %s: 0x%08X\r\n", userInput.nChannelNumber, channelMappedInterruptStrings[statusType],
outstatusBit);
}
break;
case CAN_FUNC_CMD_GET_CHAN_STATUS_RAW_SMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_STATUS_BIT_LATCHED ENTER: '0'\r\n");
naiif_printf("NAIBRD_AR_CAN_STATUS_BIT_REALTIME ENTER: '1'\r\n");
naiif_printf("NAIBRD_AR_CAN_NEW_RX_DATA_LATCHED ENTER: '2'\r\n");
naiif_printf("NAIBRD_AR_CAN_NEW_RX_DATA_REALTIME ENTER: '3'\r\n");
naiif_printf("--------------------------------\r\n");
naiif_printf("\r\nEnter Status Index or %c to quit [[default = 3 (NAIBRD_AR_CAN_NEW_RX_DATA_REALTIME)]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
statusType = 3;
else
statusType = atoi((const char *)inputBuffer);
if (statusType < 0 || statusType > 3)
{
naiif_printf("Invalid Status index detected. Defaulting to NAIBRD_AR_CAN_NEW_RX_DATA_REALTIME, Status index 3\r\n");
statusType = 3;
}
check_status(naibrd_AR_CAN_GetChanMappedStatusRaw(userInput.nCardIdx, userInput.nModuleNumber,
(naibrd_ar_can_chan_mapped_status_type_t)statusType, &outstatusRaw));
naiif_printf("%s Status Raw: 0x%08X\r\n", channelMappedInterruptStrings[statusType], outstatusRaw);
}
break;
case CAN_FUNC_CMD_CLEAR_CHAN_STATUS_SMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_STATUS_BIT_LATCHED ENTER: '0'\r\n");
naiif_printf("NAIBRD_AR_CAN_NEW_RX_DATA_LATCHED ENTER: '2'\r\n");
naiif_printf("--------------------------------\r\n");
naiif_printf("\r\nEnter Status Index to Clear or %c to quit [[default = quit]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
naiif_printf("No Status index detected. Returning to status menu.\r\n");
break;
}
else
statusType = atoi((const char *)inputBuffer);
if (statusType % 2 == 0 && statusType <= 2)
{
check_status(naibrd_AR_CAN_ClearChanMappedStatusBit(userInput.nCardIdx, userInput.nModuleNumber,
userInput.nChannelNumber, (naibrd_ar_can_chan_mapped_status_type_t)statusType));
naiif_printf("Channel %d %s Cleared\r\n", userInput.nChannelNumber, channelMappedInterruptStrings[statusType]);
}
else
{
naiif_printf("Invalid Status index detected. Returning to status menu.\r\n");
break;
}
}
break;
case CAN_FUNC_CMD_CLEAR_CHAN_STATUS_RAW_SMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_STATUS_BIT_LATCHED ENTER: '0'\r\n");
naiif_printf("NAIBRD_AR_CAN_NEW_RX_DATA_LATCHED ENTER: '2'\r\n");
naiif_printf("--------------------------------\r\n");
naiif_printf("\r\nEnter Raw Status Index to Clear or %c to quit [[default = quit]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
naiif_printf("No Status index detected. Returning to status menu.\r\n");
break;
}
else
statusType = atoi((const char *)inputBuffer);
if (statusType % 2 == 0 && statusType <= 2)
{
check_status(naibrd_AR_CAN_ClearChanMappedStatusRaw(userInput.nCardIdx, userInput.nModuleNumber,
(naibrd_ar_can_chan_mapped_status_type_t)statusType, statusRaw));
naiif_printf("Channel %d Raw %s Cleared\r\n", userInput.nChannelNumber, channelMappedInterruptStrings[statusType]);
}
else
{
naiif_printf("Invalid Status index detected. Returning to status menu.\r\n");
break;
}
}
break;
case CAN_FUNC_CMD_GET_EVENT_STATUS_SMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_EMPTY_REALTIME, ENTER: 'A'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_EMPTY_LATCHED, ENTER: 'B'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_EMPTY_REALTIME, ENTER: 'C'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_EMPTY_LATCHED, ENTER: 'D'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_FULL_REALTIME, ENTER: 'E'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_FULL_LATCHED, ENTER: 'F'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_FULL_REALTIME, ENTER: 'G'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_FULL_LATCHED, ENTER: 'H'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_EMPTY_REALTIME, ENTER: 'I'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_EMPTY_LATCHED, ENTER: 'J'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_EMPTY_REALTIME, ENTER: 'K'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_EMPTY_LATCHED, ENTER: 'L'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_FULL_REALTIME, ENTER: 'M'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_FULL_LATCHED, ENTER: 'N'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_FULL_REALTIME, ENTER: 'O'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_FULL_LATCHED, ENTER: 'P'\r\n");
naiif_printf("--------------------------------\r\n");
naiif_printf("\r\nEnter Status Index or %c to quit [[default = E (NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_FULL_REALTIME)]]: ",
NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
statusType = 4;
else
{
char c = inputBuffer[0];
if ((c >= 'A' && c <= 'P') || (c >= 'a' && c <= 'p'))
{
statusType = (c & ~0x20) - 'A'; /* case-insensitive */
}
else
{
naiif_printf("Invalid Status index. Defaulting to E.\r\n");
statusType = 'E' - 'A';
}
}
if (statusType % 2 == 0)
{
accessType = NAI_STATUS_REALTIME;
}
else
{
accessType = NAI_STATUS_LATCHED;
}
check_status(naibrd_AR_CAN_GetEventMappedStatusBit(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
(nai_status_access_type_t)accessType, (naibrd_ar_can_fifo_event_mapped_status_type_t)statusType,
&outstatusBit));
naiif_printf("Channel %d %s: 0x%08X\r\n", userInput.nChannelNumber, eventMappedInterruptStrings[statusType], outstatusBit);
}
break;
case CAN_FUNC_CMD_GET_EVENT_STATUS_RAW_SMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_REALTIME, ENTER: 'A'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_LATCHED, ENTER: 'B'\r\n");
naiif_printf("--------------------------------\r\n");
naiif_printf("\r\nEnter Status Index or %c to quit [[default = A (NAIBRD_AR_CAN_FIFO_EVENT_STATUS_REALTIME)]]: ",
NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
statusType = 0;
else
{
char c = inputBuffer[0];
if ((c >= 'A' && c <= 'P') || (c >= 'a' && c <= 'p'))
{
statusType = (c & ~0x20) - 'A'; /* case-insensitive */
}
else
{
naiif_printf("Invalid Status index. Defaulting to A.\r\n");
statusType = 'A' - 'A';
}
}
if (statusType % 2 == 0)
{
accessType = NAI_STATUS_REALTIME;
check_status(naibrd_AR_CAN_GetEventMappedStatusRaw(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
(nai_status_access_type_t)accessType, NAIBRD_AR_CAN_EVENT_MAP_FIFO, &outstatusRaw));
naiif_printf("%s Status Raw: 0x%08X\r\n", "NAIBRD_AR_CAN_FIFO_EVENT_STATUS_REALTIME", outstatusRaw);
}
else
{
accessType = NAI_STATUS_LATCHED;
check_status(naibrd_AR_CAN_GetEventMappedStatusRaw(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
(nai_status_access_type_t)accessType, NAIBRD_AR_CAN_EVENT_MAP_FIFO, &outstatusRaw));
naiif_printf("%s Status Raw: 0x%08X\r\n", "NAIBRD_AR_CAN_FIFO_EVENT_STATUS_LATCHED", outstatusRaw);
}
}
break;
case CAN_FUNC_CMD_CLEAR_EVENT_STATUS_SMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_EMPTY_LATCHED, ENTER: 'B'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_EMPTY_LATCHED, ENTER: 'D'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_ALM_FULL_LATCHED, ENTER: 'F'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_RX_FULL_LATCHED, ENTER: 'H'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_EMPTY_LATCHED, ENTER: 'J'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_EMPTY_LATCHED, ENTER: 'L'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_ALM_FULL_LATCHED, ENTER: 'N'\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_TX_FULL_LATCHED, ENTER: 'P'\r\n");
naiif_printf("--------------------------------\r\n");
naiif_printf("\r\nEnter Status Index to Clear or %c to quit [[default = quit]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
naiif_printf("No Status index detected. Returning to status menu.\r\n");
break;
}
else
{
char c = inputBuffer[0];
if ((c >= 'A' && c <= 'P') || (c >= 'a' && c <= 'p'))
{
statusType = (c & ~0x20) - 'A'; /* case-insensitive */
}
else
{
naiif_printf("Invalid Status index detected. Returning to status menu.\r\n");
break;
}
}
check_status(naibrd_AR_CAN_ClearEventMappedStatusBit(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
(naibrd_ar_can_fifo_event_mapped_status_type_t)statusType));
naiif_printf("Channel %d %s Cleared\r\n", userInput.nChannelNumber, eventMappedInterruptStrings[statusType]);
}
break;
case CAN_FUNC_CMD_CLEAR_EVENT_STATUS_RAW_SMENU:
naiif_printf("\r\n----------------------------\r\n");
naiif_printf("NAIBRD_AR_CAN_FIFO_EVENT_STATUS_LATCHED, ENTER: 'B'\r\n");
naiif_printf("--------------------------------\r\n");
naiif_printf("\r\nEnter Raw Status Index to Clear or %c to quit [[default = quit]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
{
naiif_printf("No Status index detected. Returning to status menu.\r\n");
break;
}
else
{
char c = inputBuffer[0];
if ((c >= 'A' && c <= 'P') || (c >= 'a' && c <= 'p'))
{
statusType = (c & ~0x20) - 'A'; /* case-insensitive */
}
else
{
naiif_printf("Invalid Status index detected. Returning to status menu.\r\n");
break;
}
}
check_status(naibrd_AR_CAN_ClearEventMappedStatusRaw(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
NAIBRD_AR_CAN_EVENT_MAP_FIFO, statusRaw));
naiif_printf("Channel %d Raw %s Cleared\r\n", userInput.nChannelNumber, "NAIBRD_AR_CAN_FIFO_EVENT_STATUS_LATCHED");
}
break;
default:
break;
}
}
}while (bQuit == NAI_FALSE);
return;
}
static void CAN_Single8ByteXmit()
{
nai_status_t status;
uint8_t u8Buffer[STANDARD_CAN_MAX_PAYLOAD];
uint32_t msgId = 0x111444u;
bool_t isModeA = NAI_FALSE;
uint32_t i;
bool_t outEnable;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
if (userInput.nProtocolIndex != 0x1u && userInput.nProtocolIndex != 0x0u)
{
naiif_printf("No CAN Protocol Selected! Please choose a CAN Bus protocol first.");
return;
}
u8Buffer[0] = 0x00;
u8Buffer[1] = 0x11;
u8Buffer[2] = 0x22;
u8Buffer[3] = 0x33;
u8Buffer[4] = 0x44;
u8Buffer[5] = 0x55;
u8Buffer[6] = 0x66;
u8Buffer[7] = 0x77;
/* Load one-shot 8 byte message into FIFO */
status = naibrd_AR_CAN_QueueTransmit(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
(naibrd_ar_can_protocol_type_t)userInput.nProtocolIndex, isModeA, msgId, &u8Buffer[0], STANDARD_CAN_MAX_PAYLOAD);
if (NAI_SUCCESS == status)
{
/* Now set the TX Enable so the message gets transmitted */
status = naibrd_AR_CAN_GetTxEnable(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &outEnable);
if (outEnable)
{
if (NAI_SUCCESS == status)
{
naiif_printf("CAN Message sent for chan: %d\r\n", userInput.nChannelNumber);
if (userInput.nProtocolIndex == 0)
naiif_printf("Protocol: CAN AB\r\n");
else
naiif_printf("Protocol: CAN FD\r\n");
naiif_printf("Extended: %d\r\n", (isModeA)?0:1);
naiif_printf("MsgId = 0x%x\r\n", msgId);
for (i=0; i < STANDARD_CAN_MAX_PAYLOAD; i++)
{
naiif_printf(" Payload[%d] = 0x%x\r\n", i, u8Buffer[i]);
}
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_GetTxEnable returned status: %d\r\n", status);
}
}
else
{
naiif_printf("TX Disabled. Message added to TX Fifo but not sent!\r\n");
}
}
else /* naibrd_AR_CAN_QueueTransmit error detected */
{
naiif_printf("ERROR: naibrd_AR_CAN_QueueTransmit returned status: %d\r\n", status);
}
}
static void CAN_Single64ByteXmit()
{
nai_status_t status;
uint8_t u8Buffer[CAN_FD_MAX_PAYLOAD];
uint32_t msgId = 0x17778888u;
bool_t isModeA = NAI_FALSE;
uint32_t i;
bool_t outEnable;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
/* Fill up 64 byte payload buffer */
for (i=0; i < CAN_FD_MAX_PAYLOAD; i++)
{
u8Buffer[i] = (i & 0x000000FFu);
}
/* Load one-shot 64 byte message into FIFO - we force use of protocol CAN-FD since 64 byte payload */
status = naibrd_AR_CAN_QueueTransmit(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, NAIBRD_AR_CAN_PROTOCOL_FD,
isModeA, msgId, &u8Buffer[0], CAN_FD_MAX_PAYLOAD);
if (NAI_SUCCESS == status)
{
/* Now set the TX Enable so the message gets transmitted */
status = naibrd_AR_CAN_GetTxEnable(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &outEnable);
if (outEnable)
{
if (NAI_SUCCESS == status)
{
naiif_printf("CAN Message sent for chan: %d\r\n", userInput.nChannelNumber);
naiif_printf("Protocol: CAN FD\r\n");
naiif_printf("Extended: %d\r\n", (isModeA)?0:1);
naiif_printf("MsgId = 0x%x\r\n", msgId);
for (i=0; i < CAN_FD_MAX_PAYLOAD; i++)
{
naiif_printf(" Payload[%d] = 0x%x\r\n", i, u8Buffer[i]);
}
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_GetTxEnable returned status: %d\r\n", status);
}
}
else
{
naiif_printf("TX Disabled. Message added to TX Fifo but not sent!\r\n");
}
}
else /* naibrd_AR_CAN_QueueTransmit error detected */
{
naiif_printf("ERROR: naibrd_AR_CAN_QueueTransmit returned status: %d\r\n", status);
}
}
static void CAN_ReceiveMsg()
{
nai_status_t status;
uint8_t u8Buffer[SINGLE_MSG_BUFFER_LEN];
uint32_t msgId = 0u;
uint32_t timestamp;
int32_t outRxCount = 0;
int32_t i = 0;
bool_t msgWaiting = NAI_FALSE;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
/* 1st determine if there is a CAN message that we should be waiting for! */
status = naibrd_AR_CAN_GetRxFIFOMessageWaiting(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &msgWaiting);
if (NAI_SUCCESS == status && msgWaiting)
{
status = naibrd_AR_CAN_Receive(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, SINGLE_MSG_BUFFER_LEN,
&msgId, ×tamp, &u8Buffer[0], &outRxCount);
if (NAI_SUCCESS == status)
{
naiif_printf("\r\nCAN Message Received For Channel: %d\r\n", userInput.nChannelNumber);
naiif_printf("MsgId = 0x%x\r\n", msgId);
naiif_printf("Timestamp = 0x%x\r\n", timestamp);
naiif_printf("Payload Count = %d\r\n", outRxCount);
for (i=0; i < outRxCount; i++)
{
naiif_printf(" Payload[%d] = 0x%x\r\n", i, u8Buffer[i]);
}
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_Receive returned status: %d\r\n", status);
}
}
else /* Either an error trying to detect if message is waiting or there are no messages waiting */
{
if (NAI_SUCCESS == status)
{
naiif_printf("There are no messages waiting for retrieval!\r\n");
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_GetRxFIFOMessageWaiting returned status: %d\r\n", status);
}
}
}
static void CAN_ReceiveMsgPump()
{
nai_status_t status;
uint8_t u8Buffer[SINGLE_MSG_BUFFER_LEN];
uint32_t msgId = 0u;
uint32_t timestamp;
int32_t outRxCount = 0;
int32_t receivedMsgCount = 0;
bool_t msgWaiting = NAI_FALSE;
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
naiif_printf("\r\nType Interrupt command or %c to return to main menu : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
do
{
/* 1st determine if there is a CAN message that we should be waiting for! */
status = naibrd_AR_CAN_GetRxFIFOMessageWaiting(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &msgWaiting);
if (NAI_SUCCESS == status && msgWaiting)
{
status = naibrd_AR_CAN_Receive(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, SINGLE_MSG_BUFFER_LEN,
&msgId, ×tamp, &u8Buffer[0], &outRxCount);
if (NAI_SUCCESS == status)
{
receivedMsgCount++;
naiif_printf("\r\nCAN Message Received For Channel: %d\r\n", userInput.nChannelNumber);
naiif_printf("Msg Receive Count = %d\r\n", receivedMsgCount);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_Receive returned status: %d\r\n", status);
}
}
else /* Either an error trying to detect if message is waiting or there are no messages waiting ...
if no message we continue to poll */
{
if (NAI_SUCCESS != status)
{
naiif_printf("ERROR: naibrd_AR_CAN_GetRxFIFOMessageWaiting returned status: %d\r\n", status);
}
}
} while (NAI_SUCCESS == status && bQuit == NAI_FALSE);
return;
}
static void CAN_ScheduleMsg()
{
nai_status_t status;
uint8_t u8Buffer[CAN_FD_MAX_PAYLOAD];
uint32_t msgId = 0x11112222u;
bool_t isModeA = NAI_FALSE;
uint32_t i;
uint8_t value = CAN_FD_MAX_PAYLOAD;
int16_t entryIndex = 1;
int16_t rate = 5;
int16_t skew = 5;
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
naiif_printf("\r\nEnter the Message RATE or %c to quit [[default = 5]]: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt == 0)
rate = 5;
else
rate = (int16_t)atoi((const char *)inputBuffer);
}
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
/* Fill up 64 byte payload buffer */
for (i=0; i < CAN_FD_MAX_PAYLOAD; i++)
{
u8Buffer[i] = value;
value--;
}
/* Submit 1st scheduled message */
status = naibrd_AR_CAN_ScheduleMsg(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
entryIndex, rate, skew, NAIBRD_AR_CAN_PROTOCOL_FD, isModeA, msgId, &u8Buffer[0], CAN_FD_MAX_PAYLOAD);
if (NAI_SUCCESS == status)
{
naiif_printf("CAN Message with msgId: 0x%x was scheduled for chan: %d at entryIndex %d\r\n", msgId, userInput.nChannelNumber,
entryIndex);
}
else /* naibrd_AR_CAN_QueueTransmit error detected */
{
naiif_printf("ERROR: naibrd_AR_CAN_ScheduleMsg returned status: %d\r\n", status);
}
}
static void CAN_StartSchedule()
{
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_StartScheduler(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
if (NAI_SUCCESS == status)
{
naiif_printf("Scheduler for channel %d has been started!\r\n", userInput.nChannelNumber);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_StartScheduler returned status: %d\r\n", status);
}
}
static void CAN_StopSchedule()
{
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_StopScheduler(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
if (NAI_SUCCESS == status)
{
naiif_printf("Scheduler for channel %d has been stopped!\r\n", userInput.nChannelNumber);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_StopScheduler returned status: %d\r\n", status);
}
}
static void CAN_SetFilter()
{
nai_status_t status;
int32_t filterIndex = 0;
uint32_t msgId = 0x17778889u; /*This acceptance filter is 1 byte off from the 64 byte message sent when invoked from this sample app*/
/* uint32_t msgId = 0x17778888; This is the original ID, setting the new acceptance
filter should stop the traffic if original msg is sent */
bool_t isModeA = NAI_FALSE;
uint8_t firstTwoBytes[2];
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
/* Acceptance filtering based upon 1st two bytes of payload is also a capability offered but only if the corresponding filter mask
dictates these bits should be used during the comparison */
firstTwoBytes[0] = 0x00;
firstTwoBytes[1] = 0x00;
status = naibrd_AR_CAN_SetAcceptFilter(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, filterIndex, msgId,
isModeA, &firstTwoBytes[0]);
if (NAI_SUCCESS == status)
naiif_printf("Acceptance filter: %d is now active for channel %d\r\n", filterIndex, userInput.nChannelNumber);
else
naiif_printf("ERROR: naibrd_AR_CAN_SetAcceptFilter returned status: %d\r\n", status);
}
static void CAN_GetFilter()
{
nai_status_t status;
int32_t filterIndex = 0;
uint32_t msgId;
bool_t isModeA;
uint8_t firstTwoBytes[2];
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_GetAcceptFilter(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, filterIndex, &msgId,
&isModeA, &firstTwoBytes[0]);
if (NAI_SUCCESS == status)
{
naiif_printf("Acceptance filter for channel: %d and filter index: %d\r\n", userInput.nChannelNumber, filterIndex);
naiif_printf("MsgId = 0x%x\r\n", msgId);
naiif_printf("ExtendedId = %d\r\n", (isModeA?0:1));
naiif_printf("firstTwoBytes[0] = 0x%x\r\n", firstTwoBytes[0]);
naiif_printf("firstTwoBytes[1] = 0x%x\r\n", firstTwoBytes[1]);
}
else
naiif_printf ("ERROR: naibrd_AR_CAN_GetAcceptFilter returned status: %d\r\n", status);
}
static void CAN_SetFilterMask()
{
nai_status_t status;
int32_t maskIndex = 0;
uint32_t msgId = 0x1FFFFFFFu; /* This means all bits of incoming msgId must match what is set in filterIndex 1 msgId in order for it to
pass. */
bool_t isModeA = NAI_FALSE;
uint8_t firstTwoBytes[2];
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
/* Here setting the first two bytes to zero for the mask indicates we are not interesting on filtering based on the 1st two bytes of
the payload */
firstTwoBytes[0] = 0x00;
firstTwoBytes[1] = 0x00;
status = naibrd_AR_CAN_SetAcceptMask(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, maskIndex, msgId,
isModeA, &firstTwoBytes[0]);
if (NAI_SUCCESS == status)
naiif_printf("Mask filter: %d is now active for channel %d\r\n", maskIndex, userInput.nChannelNumber);
else
naiif_printf("ERROR: naibrd_AR_CAN_SetAcceptMask returned status: %d\r\n", status);
}
static void CAN_GetFilterMask()
{
nai_status_t status;
int32_t maskIndex = 0;
uint32_t msgId;
bool_t isModeA;
uint8_t firstTwoBytes[2];
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_GetAcceptMask(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, maskIndex, &msgId,
&isModeA, &firstTwoBytes[0]);
if (NAI_SUCCESS == status)
{
naiif_printf("Acceptance mask for channel: %d and mask index: %d\r\n", userInput.nChannelNumber, maskIndex);
naiif_printf("MsgId = 0x%x\r\n", msgId);
naiif_printf("ExtendedId = %d\r\n", (isModeA?0:1));
naiif_printf("firstTwoBytes[0] = 0x%x\r\n", firstTwoBytes[0]);
naiif_printf("firstTwoBytes[1] = 0x%x\r\n", firstTwoBytes[1]);
}
else
naiif_printf ("ERROR: naibrd_AR_CAN_GetAcceptMask returned status: %d\r\n", status);
}
static void CAN_RemoveFilter()
{
nai_status_t status;
int32_t filterIndex = 0; /* One-based */
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_RemoveAcceptFilter(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, filterIndex);
if (NAI_SUCCESS == status)
naiif_printf("Acceptance Filter at filterIndex: %d has been removed\r\n", filterIndex);
else
naiif_printf("ERROR: naibrd_AR_CAN_RemoveAcceptFilter returned status: %d\r\n", status);
}
static void CAN_EnableFilters()
{
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_EnableAcceptFilters(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, NAI_TRUE /*Enable*/);
if (NAI_SUCCESS == status)
naiif_printf("Filters are now enabled for channel: %d\r\n", userInput.nChannelNumber);
else
{
naiif_printf("ERROR: naibrd_AR_CAN_EnableAcceptFilters returned status: %d\r\n", status);
}
}
static void CAN_DisableFilters()
{
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_EnableAcceptFilters(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, NAI_FALSE);
if (NAI_SUCCESS == status)
naiif_printf("Filters are now disabled for channel: %d\r\n", userInput.nChannelNumber);
else
{
naiif_printf("ERROR: naibrd_AR_CAN_EnableAcceptFilters returned status: %d\r\n", status);
}
}
static void CAN_ResetTxFIFO()
{
nai_status_t status;
int32_t fifoCount = 0;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_GetTxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &fifoCount);
if (NAI_SUCCESS == status)
{
naiif_printf("Tx FIFO Count before reset: %d\r\n", fifoCount);
status = naibrd_AR_CAN_ResetTxFifo(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
if (NAI_SUCCESS == status)
{
naiif_printf("Tx FIFO was reset for chan %d!\r\n", userInput.nChannelNumber);
status = naibrd_AR_CAN_GetTxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &fifoCount);
if (NAI_SUCCESS == status)
naiif_printf("Tx FIFO Count after reset: %d\r\n", fifoCount);
else
naiif_printf("ERROR: naibrd_AR_CAN_GetTxFIFOCount reported status: %d\r\n", status);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_ResetTxFifo reported status: %d\r\n", status);
}
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_GetTxFIFOCount reported status: %d\r\n", status);
}
}
static void CAN_ResetRxFIFO()
{
nai_status_t status;
int32_t fifoCount;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_GetRxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &fifoCount);
if (NAI_SUCCESS == status)
{
naiif_printf("Rx FIFO Count before reset: %d\r\n", fifoCount);
status = naibrd_AR_CAN_ResetRxFifo(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
if (NAI_SUCCESS == status)
{
naiif_printf("Rx FIFO was reset for chan %d!\r\n", userInput.nChannelNumber);
status = naibrd_AR_CAN_GetRxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &fifoCount);
if (NAI_SUCCESS == status)
naiif_printf("Rx FIFO Count after reset: %d\r\n", fifoCount);
else
naiif_printf("ERROR: naibrd_AR_CAN_GetRxFIFOCount reported status: %d\r\n", status);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_ResetRxFifo reported status: %d\r\n", status);
}
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_GetRxFIFOCount reported status: %d\r\n", status);
}
}
static void CAN_EnableTx()
{
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_SetTxEnable(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, NAI_TRUE);
if (NAI_SUCCESS == status)
{
naiif_printf("Tx was enabled for chan %d!\r\n", userInput.nChannelNumber);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_SetTxEnable reported status: %d\r\n", status);
}
}
static void CAN_DisableTx()
{
nai_status_t status;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_SetTxEnable(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, NAI_FALSE);
if (NAI_SUCCESS == status)
{
naiif_printf("Tx was disabled for chan %d!\r\n", userInput.nChannelNumber);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_SetTxEnable reported status: %d\r\n", status);
}
}
static void CAN_ResetDropCount()
{
nai_status_t status;
int32_t dropCount = 0;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
status = naibrd_AR_CAN_GetDropCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &dropCount);
if (NAI_SUCCESS == status)
{
naiif_printf("Drop Count before reset is: %d\r\n", dropCount);
status = naibrd_AR_CAN_ResetDropCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
if (NAI_SUCCESS == status)
{
naiif_printf("Reset Drop Count was executed for chan %d!\r\n", userInput.nChannelNumber);
status = naibrd_AR_CAN_GetDropCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &dropCount);
if (NAI_SUCCESS == status)
naiif_printf("Drop Count after reset is now: %d\r\n", dropCount);
else
naiif_printf("ERROR: naibrd_AR_CAN_GetDropCount reported status: %d\r\n", status);
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_ResetDropCount reported status: %d\r\n", status);
}
}
else
{
naiif_printf("ERROR: naibrd_AR_CAN_GetDropCount reported status: %d\r\n", status);
}
}
static void CAN_DisplayCounts()
{
nai_status_t status;
int32_t txFIFOCount = 0;
int32_t txFIFOFrameCount = 0;
int32_t rxFIFOCount = 0;
int32_t rxFIFOFrameCount = 0;
int32_t dropCount = 0;
int32_t errorCount = 0;
if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
return;
/* Retrieve counts for Tx FIFO count, Tx FIFO Frame count, Rx FIFO count, Rx FIFO Frame count and Drop Count */
status = naibrd_AR_CAN_GetTxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &txFIFOCount);
if (NAI_SUCCESS != status)
{
errorCount++;
naiif_printf("ERROR: naibrd_AR_CAN_GetTxFIFOCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
}
status = naibrd_AR_CAN_GetTxFIFOFrameCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &txFIFOFrameCount);
if (NAI_SUCCESS != status)
{
errorCount++;
naiif_printf("ERROR: naibrd_AR_CAN_GetTxFIFOFrameCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
}
status = naibrd_AR_CAN_GetRxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &rxFIFOCount);
if (NAI_SUCCESS != status)
{
errorCount++;
naiif_printf("ERROR: naibrd_AR_CAN_GetRxFIFOCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
}
status = naibrd_AR_CAN_GetRxFIFOFrameCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &rxFIFOFrameCount);
if (NAI_SUCCESS != status)
{
errorCount++;
naiif_printf("ERROR: naibrd_AR_CAN_GetRxFIFOFrameCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
}
status = naibrd_AR_CAN_GetDropCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &dropCount);
if (NAI_SUCCESS != status)
{
errorCount++;
naiif_printf("ERROR: naibrd_AR_CAN_GetDropCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
}
naiif_printf("-----------------------------------------------------------------\r\n");
naiif_printf("Counts for Channel %d\r\n", userInput.nChannelNumber);
naiif_printf("TxFIFOCount: %d\r\n", txFIFOCount);
naiif_printf("TxFIFOFrameCount: %d\r\n", txFIFOFrameCount);
naiif_printf("RxFIFOCount: %d\r\n", rxFIFOCount);
naiif_printf("RxFIFOFrameCount: %d\r\n", rxFIFOFrameCount);
naiif_printf("NUMBER OF ERRORS RETRIEVING COUNTS: %d\r\n", errorCount);
naiif_printf("-----------------------------------------------------------------\r\n");
}
static bool_t checkChannelNumber(int32_t card, int32_t mod, int32_t chan)
{
bool_t validChannel = NAI_TRUE;
if (chan < 1 || chan > naibrd_AR_CAN_GetChannelCountForModule(card, mod))
{
validChannel = NAI_FALSE;
naiif_printf("ERROR: Invalid channel number detected: %d\r\n", chan);
naiif_printf("Try setting the desired channel before calling this function by invoking the Set Channel menu item\r\n");
}
return validChannel;
}