Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

CAN Interrupt Basic

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

  1. Bus Interrupt Handling - Install ISR:

    • API calls: naibrd_InstallISR

  2. Enable Module Interrupts:

    • API calls: naibrd_CAN_SetInterruptEdgeLevel, naibrd_CAN_SetIntVector, naibrd_CAN_SetInterruptSteering, naibrd_CAN_SetIntEnable

  3. Configure Module to Cause Rx Interrupt:

    • API calls: naibrd_CAN_SetBitTiming, naibrd_CAN_SetRxEnable

  4. Show Interrupt Handling:

    • Check if any interrupt has occurred and report status and vector

  5. Re-arming Interrupts:

    • API call: naibrd_CAN_ClearStatusRaw

  6. Clear Module Configurations:

    • API call: naibrd_CAN_SetRxEnable

  7. 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;
}

Help Bot

X