IOCT Interrupts
Edit this on GitLab
IOCT Interrupts
Explanation
About the Code
This sample application code is designed to interact with North Atlantic Industries (NAI) embedded function modules using their Software Support Kit (SSK). The code primarily focuses on handling interrupts for the IOCT (Input/Output Control) modules. Below is a detailed explanation of the sample code.
Definitions and Types
- CONFIG_FILE: A constant string that points to the default configuration file for use with IOCT interrupts (default_IOCT_Interrupt.txt
).
- IRQ Count and Vectors:
- irqIOCTCount
: Keeps track of the number of IOCT interrupts received.
- receivedVector
: Stores the received interrupt vector.
- IOCT_INTERRUPT_VECTOR_CH1
and IOCT_INTERRUPT_VECTOR_CH2
: Defined constants representing interrupt vectors for two channels (channel 1 and channel 2).
Function Prototypes - Run_IOCT_Interrupt: Configures and handles IOCT interrupts. - MyIOCTIsr: Interrupt service routine (ISR) for handling interrupts. - checkForIOCTStatusChange: Checks and handles status changes for IOCT.
Main Program Execution
The main function (IOCT_Interrupts
for VxWorks systems or main
for others) performs the following:
1. Initializes application and runs board configuration.
2. Queries the user to select card index and module number.
3. Executes the Run_IOCT_Interrupt
function with the selected parameters.
4. Repeats or quits based on user input.
5. Closes all open connections and exits.
Function Details
Run_IOCT_Interrupt
This function is responsible for setting up and handling IOCT interrupts:
- Uses the naibrd
library to configure interrupts for a specific module and channel.
- Clears existing interrupts and sets interrupt type and vectors.
- Enables interrupts for specific event groups.
- Waits for interrupts and processes them when received.
MyIOCTIsr
- MyIOCTIsr: Handles the actual interrupt when it occurs.
- Increments irqIOCTCount
.
- Determines which interrupt vector was received and sets the corresponding flags (bReceivedIOCTInt_Ch1
or bReceivedIOCTInt_Ch2
).
checkForIOCTStatusChange
Checks for status changes in IOCT channels and determines if an interrupt has occurred:
- Monitors interrupt status for all channels.
- Increments irqIOCTCount
when an interrupt is detected.
- Updates the corresponding interrupt flags.
Configuration and Utilities
The program uses various utility functions and configuration settings:
- ConfigDevice, DisplayDeviceCfg, GetBoardSNModCfg, CheckModule: Utility routines from the nai_sys_cfg.c
file for initial configuration setup.
- naiapp_query_CardIndex, naiapp_query_ModuleNumber, naiapp_query_ForQuitResponse: Functions to interact with the user for input.
- naibrd_GetModuleCount, naibrd_GetModuleID: Functions to retrieve module information from the selected card.
- check_status: Utility to verify if a function call was successful.
Example Interaction 1. Initialization: - The program starts and loads the default configuration file. - It displays a user menu and awaits user input to select a card and module.
-
Configuration:
-
Configures the selected IOCT module to handle interrupts.
-
Sets up interrupt handling routines.
-
-
Interrupt Handling:
-
Waits for an interrupt, then processes the interrupt using
Run_IOCT_Interrupt
. -
The ISR (
MyIOCTIsr
) processes and acknowledges the received interrupt.
-
-
Termination:
-
Continues running until the user chooses to quit.
-
Cleans up by closing all open card connections before exiting.
-
This sample code provides a comprehensive example of setting up and handling IOCT interrupts on NAI embedded function modules, demonstrating the use and interaction of various utility functions and interrupt handling procedures.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.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"
#include "functions/naibrd_ioct.h"
#include "advanced/nai_ether_adv.h"
#include "nai_ioct_utils.h"
static const int8_t *CONFIG_FILE = (const int8_t *)"default_IOCT_Interrupt.txt";
#define RUN_IOCT_ISR
/* Function prototypes */
static bool_t Run_IOCT_Interrupt(int32_t cardIndex, int32_t module, uint32_t modid);
#if defined (__VXWORKS__)
void MyIOCTIsr(uint32_t nVector);
#else
void MyIOCTIsr(void* param,uint32_t vector);
#endif
void checkForIOCTStatusChange(int32_t cardIndex, int32_t module, int32_t maxchan);
uint32_t irqIOCTCount = 0;
static uint32_t receivedVector = 0;
static bool_t bReceivedIOCTInt_Ch1 = FALSE, bReceivedIOCTInt_Ch2 = FALSE;
#define IOCT_INTERRUPT_VECTOR_CH1 0x40
#define IOCT_INTERRUPT_VECTOR_CH2 0x41
/*****************************************************************************/
/**
<summary>
The purpose of the IOCT_Interrupts is to illustrate the methods to call in the
naibrd library to perform interrupt operations with the IOCT modules.
The following system configuration routines from the nai_sys_cfg.c file are
called to assist with the configuration setup for this program prior to
calling the naibrd IOCT routines.
- ConfigDevice
- DisplayDeviceCfg
- GetBoardSNModCfg
- CheckModule
</summary>
*/
/*****************************************************************************/
#if defined (__VXWORKS__)
int32_t IOCT_Interrupts(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
uint32_t moduleID = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Query the user for the module number */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
if (stop != TRUE)
{
moduleID = naibrd_GetModuleID(cardIndex, module);
if (moduleID != 0)
{
Run_IOCT_Interrupt(cardIndex, module, moduleID);
}
}
}
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>
Run_IOCT_Interrupt illustrates the methods to call in the
naibrd library to configure IOCT interrupts.
</summary>
*/
/*****************************************************************************/
static bool_t Run_IOCT_Interrupt(int32_t cardIndex, int32_t module, uint32_t modid)
{
bool_t bContinue = TRUE;
int32_t channel;
uint32_t latched, realtime;
nai_ioct_group_interrupt_t interruptmask;
#if !defined (RUN_IOCT_ISR)
int32_t maxchannel = naibrd_IOCT_GetChannelCount(modid);
#endif
#if defined (RUN_IOCT_ISR)
/* Install the ISR */
check_status(naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_ON_BOARD_0, (nai_isr_t)MyIOCTIsr, NULL));
#endif
if (modid == NAI_MODULE_ID_SC4)
{
channel = 1;
/* Clear Group A and Group B interrupts */
ClearInterruptStatus(modid, cardIndex, module, channel, NAI_IOCT_GROUP_ALL, 0xFFFFFFFF, &latched, &realtime);
DisplayIOCTInterruptStatus(cardIndex, module, modid);
/* Set the Interrupt Type to Edge Trigger for all interrupts */
check_status(naibrd_IOCT_SetEdgeLevelInterrupt(cardIndex, module, channel, NAI_IOCT_EDGE_INTERRUPT));
/* Set the Interrupt Vectors for the IOCT channel */
check_status(naibrd_IOCT_SetInterruptVector(cardIndex, module, channel, NAI_IOCT_GROUP_ALL, IOCT_INTERRUPT_VECTOR_CH1));
/* Set the Interrupt Steering to the application running on the ARM */
check_status(naibrd_IOCT_SetInterruptSteering(cardIndex, module, channel, NAIBRD_INT_STEERING_ON_BOARD_0));
/* Enable Channel 1 Interrupts */
interruptmask = IOCT_GROUP_A_EOB_XMITTED | IOCT_GROUP_A_TX_FIFO_FULL;
check_status(naibrd_IOCT_SetInterruptEnable(cardIndex, module, channel, NAI_IOCT_GROUP_A, interruptmask));
interruptmask = IOCT_GROUP_B_CTRL_WORD_RECVD | IOCT_GROUP_B_EOB_RECVD | IOCT_GROUP_B_RX_FIFO_FULL;
check_status(naibrd_IOCT_SetInterruptEnable(cardIndex, module, channel, NAI_IOCT_GROUP_B, interruptmask));
}
else
{
printf("\nPE interrupt example currently under development\n");
return TRUE;
}
printf("\nWaiting for IOCT Interrupt...\n");
while (bContinue)
{
#if !defined (RUN_IOCT_ISR)
checkForIOCTStatusChange(cardIndex, module, maxchannel);
#endif
if (bReceivedIOCTInt_Ch1 || bReceivedIOCTInt_Ch2)
{
if (bReceivedIOCTInt_Ch1)
{
channel = 1;
printf("Received IOCT Interrupt on Channel 1\n");
bReceivedIOCTInt_Ch1 = FALSE;
}
if (bReceivedIOCTInt_Ch2)
{
channel = 2;
printf("Received IOCT Interrupt on Channel 2\n");
bReceivedIOCTInt_Ch2 = FALSE;
}
if (modid == NAI_MODULE_ID_SC4)
{
/* Display the latched and realtime interrupt status */
DisplayIOCTInterruptStatus(cardIndex, module, modid);
/* Retrieve the interrupt latched status */
naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel, NAI_IOCT_GROUP_ALL, NAI_IOCT_INTERRUPT_STATUS_LATCHED, &latched);
/* Clear the interrupt status */
naibrd_IOCT_ClearInterruptStatus(cardIndex, module, channel, NAI_IOCT_GROUP_ALL, latched);
}
else
{
/* Retrieve the interrupt latched status (note, with PE module, reading the register will unlatch/clear the interrupt status */
naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel, NAI_IOCT_GROUP_ALL, NAI_IOCT_INTERRUPT_STATUS_LATCHED, &latched);
}
}
#if defined (__VXWORKS__)
taskDelay(1);
#endif
}
return bContinue;
}
#if defined (RUN_IOCT_ISR)
/*****************************/
/* Interrupt Service Routine */
/*****************************/
#if defined (__VXWORKS__)
void MyIOCTIsr(uint32_t nVector)
#else
void MyIOCTIsr(void* param, uint32_t vector)
#endif
{
#if defined (WIN32)
UNREFERENCED_PARAMETER(param);
#endif
#if defined (__VXWORKS__)
/* Get the vector that caused the interrupt */
unsigned int vector = nai_Onboard_GetInterruptVector();
/* Clear Interrupt */
nai_Onboard_ClearInterrupt();
#endif
irqIOCTCount++;
/* Determine what interrupt was received */
receivedVector = vector;
switch (vector)
{
case IOCT_INTERRUPT_VECTOR_CH1:
bReceivedIOCTInt_Ch1 = TRUE;
break;
case IOCT_INTERRUPT_VECTOR_CH2:
bReceivedIOCTInt_Ch2 = TRUE;
break;
default:
#if defined (__VXWORKS__)
logMsg("Unknown Interrupt, Vector:0x%02X, IOCT irqCount:%d\n", vector, irqIOCTCount,0,0,0,0);
#else
printf("Unknown Interrupt, Vector:0x%02X, IOCT irqCount:%d\n", vector, irqIOCTCount);
#endif
break;
}
}
#else
void checkForIOCTStatusChange(int32_t cardIndex, int32_t module, int32_t maxchannel)
{
uint32_t latched;
int32_t channel;
for (channel = 1; channel < maxchannel; channel++)
{
/* Retrieve the interrupt latched status */
naibrd_IOCT_GetInterruptStatus(cardIndex, module, channel, NAI_IOCT_GROUP_ALL, NAI_IOCT_INTERRUPT_STATUS_LATCHED, &latched);
if (latched != 0)
{
irqIOCTCount++;
if (channel == 1)
{
receivedVector = IOCT_INTERRUPT_VECTOR_CH1;
bReceivedIOCTInt_Ch1 = TRUE;
}
else if (channel == 2)
{
receivedVector = IOCT_INTERRUPT_VECTOR_CH2;
bReceivedIOCTInt_Ch2 = TRUE;
}
}
}
}
#endif