RLY Interrupt
Edit this on GitLab
RLY Interrupt
Explanation
About RLY_Interrupt Sample Application Code
This sample application code demonstrates how to perform an interrupt when a single channel receives a relay (RLY) message using North Atlantic Industries' Single-Slot Kit (SSK) and their naibrd library. This demonstration includes user interaction for configuring settings and supports handling multiple interrupts as well as offboard interrupts. Below is a detailed walk-through and explanation of the code.
Include Declarations
The application includes necessary standard library headers like stdio.h
, stdlib.h
, string.h
, and time.h
, along with specific headers for relay interrupt handling and general board access from the North Atlantic Industries' libraries:
- nai_rly_int.h
- nai_rly_cfg.h
- nai_rly_int_ether.h
- naiapp_interrupt.h
- naiapp_interrupt_ether.h
- naiapp_boardaccess_menu.h
- naiapp_boardaccess_query.h
- naiapp_boardaccess_access.h
- naiapp_boardaccess_display.h
- naiapp_boardaccess_utils.h
- nai.h
- naibrd.h
- naibrd_rly.h
Global Configuration and Prototypes The application uses a global constant for the configuration file:
static const int8_t *CONFIG_FILE = (const int8_t *)"default_RLY_Interrupt.txt";
And a prototype for the internal function Run_RLY_Interrupt()
:
static bool_t Run_RLY_Interrupt();
Main Routine This is the entry point of the application, designed to assist in accessing and configuring the board.
#if defined (__VXWORKS__) int32_t RLY_Interrupt(void) #else int32_t main(void) #endif
Initialization:
The program initializes relay and interrupt configurations using the initializeRLYConfigurations
and initializeInterruptConfigurations
functions.
Board Menu:
It calls naiapp_RunBoardMenu
with the configuration file to display a menu for board access. If successful, the program enters a loop to query the user for the card index and module number and sets the configuration accordingly.
Interrupt Handling:
If the user does not choose to quit, the program calls Run_RLY_Interrupt()
to handle the relay interruptions.
Exit: Finally, the program waits for the user to hit the Enter key to exit and closes all open card connections.
Run_RLY_Interrupt Function The function handles all steps required for setting up, processing, and clearing relay interrupts:
static bool_t Run_RLY_Interrupt()
Main Steps:
-
Query for Channels:
-
It queries the user to set channel ranges using
naiapp_query_ForChannelRange
.
-
-
Interrupt Trigger Status:
-
The function queries for the edge trigger status using
GetRLYLatchStatusTriggerMode
.
-
-
Clear Interrupt Prompts:
-
Whether the user wants prompts for clearing interrupts using
QueryUserForClearingInterruptPrompts
.
-
-
Onboard/Offboard Interrupts:
-
Queries if interrupts should be processed onboard or offboard using
QueryUserForOnboardOffboardInterrupts
.
-
-
Interrupt Steering:
-
Queries where the interrupt should be sent out to using
GetIntSteeringTypeFromUser
.
-
-
Install ISR:
-
Based on the user configurations, installs the ISR using
naibrd_InstallISR
either for onboard or offboard processing.
-
-
Configure RLY interrupt:
-
Calls
configureRLYToInterruptOnRx
to configure the module for interrupting on RX.
-
-
Initialize Message Queue:
-
Initializes message queues and threads for handling the interrupts with
InitInterruptAppThread
andUpdateThreadState
.
-
-
Enable Interrupts:
-
Enables interrupts on the configured module with
enableRLYInterrupts
.
-
-
Handle and Display:
-
Processes the actual interrupt using
handleRLYInterrupt
while waiting for user-triggered interrupts.
-
-
Clear Configuration:
-
Clears module and board configurations by calling
enableRLYInterrupts
with false andnaibrd_UninstallISR
.
-
API Functions and Callbacks
Some specific API functions and callbacks utilized in the code include:
- naibrd_InstallISR
- naibrd_RLY_SetInterruptEdgeLevel
- naibrd_RLY_SetIntVector
- naibrd_RLY_SetInterruptSteering
- naibrd_RLY_SetIntEnable
- naibrd_RLY_ClearStatus
- naibrd_RLY_SetRxEnable
- naibrd_UninstallISR
These functions handle everything from installing the ISR, configuring the interrupt vectors, enabling and clearing interrupts, to eventually uninstalling the ISR after processing.
This sample application gives a comprehensive demonstration on setting up and handling relay-based interrupts using the North Atlantic Industries' libraries and tools.
/**************************************************************************************************************/
/**
<summary>
The RLY_Interrupt program demonstrates how to perform an interrupt when a single channel receives
a rly 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.
This application differs from RLY_Interrupt_Basic in that it could handle multiple interrupts at once.
It also queries the user for the edge trigger value and whether the user should be prompted to clear an interrupt.
The application also has support for offboard interrupts.
</summary>
*/
/**************************************************************************************************************/
/************************/
/* Include Declarations */
/************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/*Common Module Specific Sample Program include files*/
#include "nai_rly_int.h"
#include "nai_rly_cfg.h"
#include "nai_rly_int_ether.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_rly.h"
/*********************************************/
/* Application Name and Revision Declaration */
/*********************************************/
/*
static const int8_t *App_Name = "RLY Interrupt Basic";
static const int8_t *App_Rev = "1.0";
*/
static const int8_t *CONFIG_FILE = (const int8_t *)"default_RLY_Interrupt.txt";
/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_RLY_Interrupt();
/**************************************************************************************************************/
/***** 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 RLY_Interrupt(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;
initializeRLYConfigurations(0, 0, 0, 0, 0, 0);
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);
inputRLYConfig.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);
inputRLYConfig.module = module;
if (stop != TRUE)
{
inputRLYConfig.modid = naibrd_GetModuleID(cardIndex, module);
if ((inputRLYConfig.modid != 0))
{
Run_RLY_Interrupt();
}
}
}
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 interrupter when channel receives RLY message.
API CALLS - naibrd_RLY_SetInterruptEdgeLevel, naibrd_RLY_SetIntVector, naibrd_RLY_SetInterruptSteering, naibrd_RLY_SetIntEnable
4. Not applicable to RLY module
5. Show Interrupt Handling - Check the mailbox to see if any interrupts occurred.
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_RLY_ClearStatus
7. Clear Module Configurations
API CALLS - naibrd_RLY_SetRxEnable
8. Clear Board Configurations
API CALLS - naibrd_UninstallISR
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_RLY_Interrupt()
{
bool_t bQuit = FALSE;
int32_t minChannel;
int32_t maxChannel;
minChannel = 1;
maxChannel = naibrd_RLY_GetChannelCount(inputRLYConfig.modid);
/* Query for Channels to Operate on */
bQuit = naiapp_query_ForChannelRange(&inputRLYConfig.minChannel, &inputRLYConfig.maxChannel, minChannel, maxChannel);
/* Query for Trigger Status of interrupts */
if (!bQuit)
{
bQuit = GetRLYLatchStatusTriggerMode(&inputInterruptConfig.interrupt_Edge_Trigger);
}
/* Query user if they'd like to be prompted for clearing interrupts */
if (!bQuit) {
bQuit = QueryUserForClearingInterruptPrompts(&inputInterruptConfig.bPromptForInterruptClear);
}
if (!bQuit) {
bQuit = QueryUserForOnboardOffboardInterrupts(&inputInterruptConfig.bProcessOnboardInterrupts);
}
/* 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);
inputInterruptConfig.cardIndex = inputRLYConfig.cardIndex;
if (inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
{
check_status(naibrd_InstallISR(inputInterruptConfig.cardIndex, inputInterruptConfig.irq, (nai_isr_t)IntOnboardIsr, NULL));
}
else
{
check_status(naibrd_InstallISR(inputInterruptConfig.cardIndex, inputInterruptConfig.irq, (nai_isr_t)IntOffboardIsr, (void*)&inputRLYConfig.cardIndex));
}
/****3. configure Module to perform interrupts****/
configureRLYToInterruptOnRx(inputInterruptConfig, inputRLYConfig);
/****Initialize Message Queue ****/
InitInterruptAppThread(ONBOARD_INT, 0);
nai_msDelay(10);
UpdateThreadState(RUN);
/****Enable Interrupts****/
enableRLYInterrupts(inputRLYConfig, TRUE);
/***5. Show Interrupt Handling (contains step 6) ***/
rlyIntProcessFunc = handleRLYInterrupt;
/***Request user triggers interrupt ***/
DisplayMessage_RLYInterrupt(MSG_USER_TRIGGER_RLY_INT);
/****Wait on program threads****/
while (!isThreadStateTerminated()) {
}
bQuit = TRUE;
/*****7. Clear Module Configurations*****/
enableRLYInterrupts(inputRLYConfig, FALSE);
/*****8. Clear Board Configurations *****/
check_status(naibrd_UninstallISR(inputInterruptConfig.cardIndex));
}
return bQuit;
}