CAN Interrupt Ethernet
Edit this on GitLab
CAN Interrupt Ethernet
Explanation
About the CAN_Interrupt_Ethernet Program
This C application is designed to demonstrate how to configure and handle CAN (Controller Area Network) message reception interrupts over Ethernet using North Atlantic Industries' (NAI) embedded function modules. The application highlights the steps to set up the board, handle Ethernet interrupts, and manage CAN message reception interrupts.
Code Structure
Include Declarations
The program starts by including standard C libraries and custom header files specific to NAI’s hardware and software configuration.
-
Standard Libraries:
stdio.h
,stdlib.h
,string.h
, andtime.h
-
NAI-specific Headers:
-
For CAN and Ethernet operations:
nai_can_int_ether.h
,nai_can_int.h
,nai_can_cfg.h
-
For handling general interrupts and board access:
naiapp_interrupt.h
,naiapp_interrupt_ether.h
,naiapp_boardaccess_menu.h
, etc.
Static Variables
-
DEF_RX_RESPONSE_IPv4_ADDR[]
: Defines a default IP address for the Ethernet response. -
COMMANDS[]
: An array to hold Ethernet command data. -
CONFIG_FILE
: A static string referencing the default configuration file.
Internal Function Prototypes
A function prototype for Run_CAN_Interrupt_Ethernet()
is declared, indicating the primary functionality within the application.
Main Routine
The main function handles initial setup and interacts with the user to configure and access the NAI board.
Steps in the Main Function
-
Initialization:
-
Initialize CAN, interrupt, and IDR configurations using functions such as
initializeCANConfigurations()
andinitializeInterruptConfigurations()
.
-
-
Configuration and Access:
-
If the user configuration (
naiapp_RunBoardMenu()
) is successful, enter a loop to query the card index and module number. -
Retrieve the module ID and run the CAN interrupt and Ethernet handling routine (
Run_CAN_Interrupt_Ethernet()
).
-
-
Repetition or Exit:
-
Offer the user an option to quit or restart the application.
-
Close all open card access.
-
Run_CAN_Interrupt_Ethernet Function
This function contains the core logic for handling CAN message interrupts over Ethernet.
Major Steps:
-
Ethernet Interrupt Handling:
-
Set up the IDR (Interrupt Descriptor Register) to handle Ethernet interrupts using NAI’s Ethernet communication APIs.
-
-
Enable Module Interrupts:
-
Configure the CAN module to generate an interrupt when a CAN message is received.
-
-
Configure CAN for Rx Interrupts:
-
Set up the CAN module with appropriate baud rates and enable the channel to receive CAN messages.
-
-
Interrupt Handling:
-
Use an IDR server to listen for interrupts and display the associated data.
-
-
Re-arm Interrupts:
-
Clear the status register to allow for future interrupts.
-
-
Cleanup:
-
Clear module and board configurations.
-
Detailed Steps in Function: - Query and Setup: - Check CAN module compatibility and support for Ethernet commands. - Query user for channel number, IDR configuration, and interrupt display options.
-
Interrupt Handling:
-
Set up IDR configurations and start the IDR server to handle CAN message reception interrupts.
-
Display data either to the console or a file based on the user’s choice.
-
Cleanup:
-
Disable CAN message reception.
-
Stop the IDR server and clear the configuration.
Conclusion
The provided sample code demonstrates a systematic approach to configuring and managing CAN message interrupts over Ethernet using NAI’s function modules. By following defined API calls and configuration steps, users can effectively set up and handle interrupts, ensuring reliable communication and data handling within their embedded systems.
/**************************************************************************************************************/
/**
<summary>
The CAN_Interrupt_Ethernet program demonstrates how to perform an interrupt when a single channel receives
a can message.
</summary>
*/
/**************************************************************************************************************/
/************************/
/* Include Declarations */
/************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/*Common Module Specific Sample Program include files*/
#include "nai_can_int_ether.h"
#include "nai_can_int.h"
#include "nai_can_cfg.h"
/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
/* Module Specific NAI Board Library files */
#include "functions/naibrd_can.h"
static uint8_t DEF_RX_RESPONSE_IPv4_ADDR[] = {192,168,1,100};
static uint8_t COMMANDS[MAX_ETHER_IDR_CMD_CNT*MAX_ETHER_BLOCK_REG_CNT];
/********************/
/* Application Name */
/********************/
static const int8_t *CONFIG_FILE = (int8_t *)"default_CAN_Interrupt_Ethernet.txt";
/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_CAN_Interrupt_Ethernet();
/**************************************************************************************************************/
/***** Main Routine *****/
/**************************************************************************************************************/
/**************************************************************************************************************/
/**
<summary>
The main routine assists in gaining access to the board.
The following routines from the nai_sys_cfg.c file are
called to assist with accessing and configuring the board.
- ConfigDevice
- DisplayDeviceCfg
- GetBoardSNModCfg
- CheckModule
</summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t CAN_Interrupt_Ethernet(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
initializeCANConfigurations(0,0,0,0,0,0, MAX_ETHER_CAN_FRAME_PAYLOAD,1,NAI_CAN_500K_BAUD);
initializeInterruptConfigurations(FALSE,FALSE,FALSE,0,NAIBRD_INT_STEERING_ON_BOARD_1,0,0);
initializeIDRConfigurations(0,0,DEF_RX_RESPONSE_PROTOCOL,DEF_RX_RESPONSE_PORT,DEF_RX_RESPONSE_IPv4_ADDR, DEF_RX_RESPONSE_IPv4_LENGTH,COMMANDS,0,0,DEF_ETHERNET_CAN_IDR_ID);
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
inputCANConfig.cardIndex = cardIndex;
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Query the user for the module number */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
inputCANConfig.module = module;
if (stop != TRUE)
{
inputCANConfig.modid = naibrd_GetModuleID(cardIndex, module);
if ((inputCANConfig.modid != 0))
{
Run_CAN_Interrupt_Ethernet();
}
}
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
printf("\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
/**************************************************************************************************************/
/**
<summary>
This function is broken into the following major steps. These steps correspond with the steps provided
in the naibrd SSK Quick Guide(Interrupts) file.
2a. Ethernet Interrupt Handling - Setup IDR to handle interrupt
API CALLS - naibrd_Ether_SetIDRConfig, naibrd_Ether_StartIDR,naibrd_Ether_ClearIDRConfig
3. Enable Module Interrupts- Configures module to interrupt when channel receives CAN message.
API CALLS - naibrd_CAN_SetInterruptEdgeLevel, naibrd_CAN_SetIntVector, naibrd_CAN_SetInterruptSteering, naibrd_CAN_SetIntEnable
4. Configure Module to Cause Rx Interrupt - sets the BAUD Rate to 1mbit/s (CAN AB) or 500k bits/s (CAN J1939) as definted in nai_can_cfg.h
It also enables the particular channel on the module to receive can messages
API CALLS - naibrd_CAN_SetBitTiming , naibrd_CAN_SetRxEnable
5. Show Interrupt Handling - The IDR server will listen on the boards ports for IDRs indicating an interrupt.
These results will be decoded and displayed to the user.
6. Re-arming Interrupts - Clear the status register to allow interrupts to occur again. This is done by writing to the status register.
In this program, the write command is included in the IDR.
API CALLS - nai_ether_BeginWriteMessage, nai_ether_WriteMessageData, nai_ether_FinishMessage
7. Clear Module Configurations
API CALLS - naibrd_CAN_SetRxEnable, naibrd_CAN_ClearStatus
8. Clear Board Configurations
API CALLS - naibrd_Ether_StopIDR, naibrd_Ether_ClearIDRConfig
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_CAN_Interrupt_Ethernet()
{
bool_t bQuit = FALSE;
bool_t bGen4CanIDRCommands;
int32_t maxChannel = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
int32_t minChannel = 1;
/* check if CAN module supports GEN 4 Ethernet */
bGen4CanIDRCommands = SupportsGen4Ether(inputCANConfig.cardIndex);
if(!bGen4CanIDRCommands)
{
printf("CAN Ethernet Interrupt Support Prior to Generation 4 Ethernet commands currently not supported\n");
bQuit = TRUE;
}
if(!bQuit){
bQuit = naiapp_query_ChannelNumber(maxChannel,minChannel,&inputCANConfig.channel);
inputCANConfig.maxChannel = inputCANConfig.channel;
inputCANConfig.minChannel = inputCANConfig.channel;
}
if(!bQuit){
bQuit = QueryIDRConfigInformation(&inputIDRConfig);
}
if(!bQuit){
bQuit = QueryUserForOnboardOffboardInterrupts(&inputInterruptConfig.bProcessOnboardInterrupts);
}
if(!bQuit)
{
bQuit = QueryUserForEtherIDRMsgDisplay(&bDisplayEtherUPR);
}
if(!bQuit)
{
bQuit = QueryUserForDisplayingData(&inputInterruptConfig.displayData);
}
if (!bQuit)
{
if(inputInterruptConfig.displayData)
fifoDataFile = stdout;
else
fifoDataFile = fopen("CAN_Interrupt_FIFO_Data.txt","w+");
/****2. Setup IDR to Handle Interrupt (also contains step 6) ****/
if(inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
{
inputIDRConfig.cardIndex = inputCANConfig.cardIndex;
inputIDRConfig.boardInterface = NAI_INTF_ONBOARD;
inputInterruptConfig.steering = NAIBRD_INT_STEERING_ON_BOARD_1;
}
else /*OffBoard Interrupt*/
{
inputIDRConfig.cardIndex = 0;
inputIDRConfig.boardInterface = NAI_INTF_PCI;
inputInterruptConfig.steering = NAIBRD_INT_STEERING_CPCI_APP;
}
setupIDRConfiguration(inputCANConfig,&inputIDRConfig,bGen4CanIDRCommands);
check_status(naibrd_Ether_StartIDR(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_CAN_IDR_ID));
/****3. configure module To Interrupt****/
configureCANToInterruptOnRx(inputInterruptConfig,inputCANConfig);
enableCANInterrupts(inputCANConfig,TRUE);
/****4. Configure CAN to cause Interrupts ****/
Cfg_Rx_CAN(inputCANConfig);
/****5. Show Interrupt Handling****/
CAN_ClearInterrupt = ClearInterrupt_CAN;
canEtherIntFunc = HandleCANEtherInterrupt;
bQuit = runIDRServer(inputIDRConfig);
/***** 7. Clear Module Configurations *****/
check_status(naibrd_CAN_SetRxEnable(inputCANConfig.cardIndex, inputCANConfig.module, inputCANConfig.channel, FALSE));
enableCANInterrupts(inputCANConfig,FALSE);
/*****8. Clear Board Configurations *****/
check_status(naibrd_Ether_StopIDR(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_CAN_IDR_ID));
if(!inputInterruptConfig.displayData)
{
fclose(fifoDataFile);
}
}
return bQuit;
}