CAN Interrupt Basic
Edit this on GitLab
CAN Interrupt Basic
Explanation
About the "CAN_Interrupt_Basic" Sample Code
This document describes the "CAN_Interrupt_Basic" program provided by North Atlantic Industries (NAI). The purpose of the program is to demonstrate how to perform an interrupt when a single channel receives a CAN (Controller Area Network) message. This demonstration involves method calls from the NAI board library naibrd
. Detailed information on this process can be found in the "naibrd SSK Quick Guide (Interrupts)" file.
Code Components
Include Declarations
The code begins with necessary include declarations, encapsulating standard libraries and NAI-specific headers:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "nai_can_int.h"
#include "nai_can_cfg.h"
#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"
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_can.h"
Application Name
A static constant defines the configuration file used by the application:
static const int8_t *CONFIG_FILE = (int8_t *)"default_CAN_Interrupt_Basic.txt";
Internal Function Prototypes
A forward declaration for the main CAN interrupt handling function:
static bool_t Run_CAN_Interrupt_Basic();
Main Routine
The main function serves as an entry point and assists in accessing and configuring the board. It involves calling routines from nai_sys_cfg.c
for setting up and interacting with the hardware:
- ConfigDevice
- DisplayDeviceCfg
- GetBoardSNModCfg
- CheckModule
The code is highly interactive, querying the user for input such as the card index and module number, and continuously checks for a 'quit' command:
#if defined (__VXWORKS__)
int32_t CAN_Interrupt_Basic(void)
#else
int32_t main(void)
#endif
{
// Variable declarations and initial configurations
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, NAI_J1939_MAX_DATA_LEN, 1, NAI_CAN_500K_BAUD);
initializeInterruptConfigurations(FALSE, FALSE, FALSE, 0, 0, 0, 0);
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
// User queries for card index
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
inputCANConfig.cardIndex = cardIndex;
if (stop != TRUE)
{
// Get module count and module number
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
inputCANConfig.module = module;
if (stop != TRUE)
{
// Get module ID and run the CAN interrupt handling function
inputCANConfig.modid = naibrd_GetModuleID(cardIndex, module);
if ((inputCANConfig.modid != 0))
{
Run_CAN_Interrupt_Basic();
}
}
}
// Quit command check
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
// Exit message and cleanup
printf("\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
Interrupt Handling Function
This function is broken down into multiple steps, aligning with the instructions from the "naibrd SSK Quick Guide (Interrupts)":
static bool_t Run_CAN_Interrupt_Basic()
{
bool_t bQuit = FALSE;
int32_t maxChannel = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
int32_t minChannel = 1;
// Query user for RX channel
if(!bQuit)
{
bQuit = naiapp_query_ChannelNumber(maxChannel, minChannel, &inputCANConfig.channel);
inputCANConfig.minChannel = inputCANConfig.channel;
inputCANConfig.maxChannel = inputCANConfig.channel;
}
// Query user for interrupt location
if(!bQuit)
{
bQuit = GetIntSteeringTypeFromUser(&inputInterruptConfig.steering);
}
// Proceed if quit is not requested
if (!bQuit)
{
// 2. Bus Interrupt Handling - install ISR
setIRQ(inputInterruptConfig.steering, &inputInterruptConfig.irq);
naibrd_InstallISR(inputCANConfig.cardIndex, inputInterruptConfig.irq, basic_ISR_CAN, NULL);
// 3. Enable Module Interrupts
configureCANToInterruptOnRx(inputInterruptConfig, inputCANConfig);
enableCANInterrupts(inputCANConfig, TRUE);
// 4. Configure Module to Cause Rx Interrupt
Cfg_Rx_CAN(inputCANConfig);
// 5. Show Interrupt Handling and Check Occurrences
bQuit = CAN_checkForInterrupt(inputCANConfig);
// 7. Clear Module Configurations
check_status(naibrd_CAN_SetRxEnable(inputCANConfig.cardIndex, inputCANConfig.module, inputCANConfig.channel, FALSE));
// 8. Clear Board Configurations
check_status(naibrd_UninstallISR(inputCANConfig.cardIndex));
}
return bQuit;
}
Major Steps Breakdown
-
Bus Interrupt Handling - Install ISR:
-
API calls:
naibrd_InstallISR
-
-
Enable Module Interrupts:
-
API calls:
naibrd_CAN_SetInterruptEdgeLevel
,naibrd_CAN_SetIntVector
,naibrd_CAN_SetInterruptSteering
,naibrd_CAN_SetIntEnable
-
-
Configure Module to Cause Rx Interrupt:
-
API calls:
naibrd_CAN_SetBitTiming
,naibrd_CAN_SetRxEnable
-
-
Show Interrupt Handling:
-
Check if any interrupt has occurred and report status and vector
-
-
Re-arming Interrupts:
-
API call:
naibrd_CAN_ClearStatusRaw
-
-
Clear Module Configurations:
-
API call:
naibrd_CAN_SetRxEnable
-
-
Clear Board Configurations:
-
API call:
naibrd_UninstallISR
-
This program incorporates detailed user interaction for setup and configuration, ensuring customizable and flexible board access and interrupt handling.
/**************************************************************************************************************/
/**
<summary>
The CAN_Interrupt_Basic program demonstrates how to perform an interrupt when a single channel receives
a can message. The purpose of this program is to demonstrate the method calls in the naibrd library for performing
the interrupt. More information on this process can be found in the naibrd SSK Quick Guide(Interrupts) file.
</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.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"
/********************/
/* Application Name */
/********************/
static const int8_t *CONFIG_FILE = (int8_t *)"default_CAN_Interrupt_Basic.txt";
/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_CAN_Interrupt_Basic();
/**************************************************************************************************************/
/***** 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_Basic(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, NAI_J1939_MAX_DATA_LEN, 1, NAI_CAN_500K_BAUD);
initializeInterruptConfigurations(FALSE, FALSE, FALSE, 0, 0, 0, 0);
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_Basic();
}
}
}
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.
2. Bus Interrupt Handling - Install ISR
API CALLS - naibrd_InstallISR
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 - Check if any interrupt has occurred and report back the status and vector
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, we use an API call to do this.
API CALLS - naibrd_CAN_ClearStatusRaw
7. Clear Module Configurations
API CALLS - naibrd_CAN_SetRxEnable
8. Clear Board Configurations
API CALLS - naibrd_UninstallISR
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_CAN_Interrupt_Basic()
{
bool_t bQuit = FALSE;
int32_t maxChannel = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
int32_t minChannel = 1;
/* Query user for RX channel */
if(!bQuit)
{
bQuit = naiapp_query_ChannelNumber(maxChannel,minChannel,&inputCANConfig.channel);
inputCANConfig.minChannel = inputCANConfig.channel;
inputCANConfig.maxChannel = inputCANConfig.channel;
}
/* Query user for location interrupt will be sent out to */
if(!bQuit)
{
bQuit = GetIntSteeringTypeFromUser(&inputInterruptConfig.steering);
}
if (!bQuit)
{
/**** 2. Implement Bus Interrupt Handling****/
setIRQ(inputInterruptConfig.steering,&inputInterruptConfig.irq);
naibrd_InstallISR(inputCANConfig.cardIndex,inputInterruptConfig.irq, basic_ISR_CAN,NULL);
/****3. configure Module to perform interrupts****/
configureCANToInterruptOnRx(inputInterruptConfig,inputCANConfig);
enableCANInterrupts(inputCANConfig,TRUE);
/****4. Configure Module to cause Interrupts ****/
Cfg_Rx_CAN(inputCANConfig);
/****5. Show Interrupt Handling (contains step 6)****/
bQuit = CAN_checkForInterrupt(inputCANConfig);
/*****7. Clear Module Configurations*****/
check_status(naibrd_CAN_SetRxEnable(inputCANConfig.cardIndex, inputCANConfig.module, inputCANConfig.channel, FALSE));
/*****8. Clear Board Configurations *****/
check_status(naibrd_UninstallISR(inputCANConfig.cardIndex));
}
return bQuit;
}