DT Interrupt Common
Edit this on GitLab
DT Interrupt Common
Explanation
About "Discrete Interrupt Sample Application" Code Overview
This C application is designed by North Atlantic Industries (NAI) to demonstrate the use of their Discrete Interrupt Sample Application. The purpose of this application is to interact with NAI’s embedded function modules and manage discrete interrupts. Below is a detailed explanation of the code:
Definitions - UserInput_DTInt: Structure to hold user input related to the card index, module number, and interrupt trigger type. - BoardState_DTInt: Structure to maintain the current state of the board like card index, module number, and max channels. - globalIntCount: Global variable to keep track of the interrupt count.
Include Files
The code includes a number of header files, which can be categorized as follows:
1. Standard Library Includes: Header files from the C standard library such as stdio.h
, stdlib.h
, string.h
, time.h
, and stdint.h
.
2. Common Sample Program Includes: Custom header files related to NAI applications like naiapp_interrupt.h
, naiapp_interrupt_ether.h
, etc.
3. NAI Board Library: NAI-specific functions are included from headers like nai.h
and naibrd.h
. These likely provide interfaces to interact with NAI boards and modules.
4. Platform-Specific Includes: Conditional includes based on the platform such as VXWORKS
and WIN32
which handle platform-specific configurations.
Function Listings
DisplayMessage_DTInterrupt(int32_t msgId)
This function displays messages based on the message ID passed in. It covers three types of messages:
- Banner: Displays general information about discrete interrupts.
- User Trigger Prompt: Prompts the user to trigger a discrete interrupt.
- User Clear Prompt: Prompts the user to clear interrupts.
PromptUserInput_DTInterrupt(bool_t *bValid)
Handles user prompting for card index, module number, and latched status trigger mode.
- Query for Card Index: Calls naiapp_query_CardIndex
to get the card index from the user.
- Get Module Information: Retrieves module count and module-specific information if card index input is valid.
- Validate Module: Checks if the module is a DT module and accordingly sets bValid
to TRUE
or FALSE
.
ConfigDTInterrupt(interruptCommType_t interruptCommType)
Configures the discrete interrupts based on communication type:
- Disable Current Interrupts: Calls EnableDTInterrupt(FALSE)
to disable interrupts initially.
- Clear Latched Statuses: Clears any previously latched status in the module.
- Set Interrupt Vector: Sets up interrupt vectors for various statuses.
- Set Latched Status Mode: Configures the latched status mode for each channel.
- Interrupt Steering: Configures interrupt steering based on the interruptCommType
parameter.
EnableDTInterrupt(bool_t enabled)
Enables or disables discrete interrupts for all channels:
- Loops through each channel and calls naibrd_DT_SetInterruptEnable
to set the interrupt enable state for different statuses like NAI_DT_STATUS_BIT_LATCHED
, NAI_DT_STATUS_OVERCURRENT_LATCHED
, etc.
GetDTLatchStatusTriggerMode()
Prompts the user for the trigger mode for the latched status register (Edge Triggered
or Level Triggered
):
- User Prompt: Asks the user to input the trigger mode and sets the intTriggerType
in userInput_DTInt
based on the user input.
Main Points About the Code - User Interaction: The code heavily relies on user interaction for configuration, prompting the user to provide necessary inputs like card index, module number, and interrupt trigger modes. - Platform-Specific Handling: There are conditional compilations to handle different platforms, ensuring the code’s adaptability. - Robust Interrupt Management: Clear steps to disable, clear, reconfigure, and enable interrupts, ensuring that the interrupt system is in a known state before operation begins. - Module Information and Validation: Ensures that the correct module type is being operated on and retrieves necessary details like the number of channels.
This code functions as a robust example for handling discrete interrupts on NAI embedded function modules, focusing on user input, hardware interaction, and ensuring configurations are correctly applied.
/**************************************************************************************************************/
/**
<summary>
The DT_Interrupt_Common file contains routines that used by the Discrete Interrupt Sample Applications.
</summary>
*/
/**************************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.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"
/* NAI Board Library include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_dt.h"
#include "naibrd_ether.h"
#include "advanced/nai_ether_adv.h"
#if defined (WIN32)
#include "../../src/maps/nai_map_dt.h"
#else
#include "maps/nai_map_dt.h"
#endif
#if defined (__VXWORKS__)
#include "naibrd_config.h"
#endif
#include "DT_Interrupt_Common.h"
UserInput_DTInt userInput_DTInt;
BoardState_DTInt boardState_DTInt;
uint32_t globalIntCount = 0;
/***********************/
/* Function Prototypes */
/***********************/
bool_t GetDTLatchStatusTriggerMode();
/**************************************************************************************************************/
/***** Functions Invoked Externally *****/
/**************************************************************************************************************/
/**************************************************************************************************************/
/**
<summary>
DisplayMessage_DTInterrupt handles displaying the messages associated with the msgId passed in.
</summary>
*/
/**************************************************************************************************************/
void DisplayMessage_DTInterrupt(int32_t msgId)
{
switch (msgId)
{
case (int32_t)MSG_BANNER_DT_INT:
{
printf("\n********************************************************************************");
printf("\n****** DISCRETE INTERRUPT ******");
printf("\nAn interrupt will occur when a Discrete module generates any of the following: ");
printf("\nFault, Low-to-High Transition, High-to-Low Transition, or Overcurrent ");
printf("\n********************************************************************************");
}
break;
case (int32_t)MSG_USER_TRIGGER_DT_INT:
{
printf("\nPress \"Q\" to quit the application.\nPlease trigger Discrete interrupt (Fault, Lo-Hi Transition, Hi-Lo Transition or Overcurrent ...");
}
break;
case (int32_t)MSG_USER_CLEAR_DT_INT:
{
printf("Press \"C\" to clear interrupts... ");
}
break;
}
}
/**************************************************************************************************************/
/**
<summary>
PromptUserInput_DTInterrupt handles prompting the user for the card index, module number and latched status
trigger mode.
</summary>
*/
/**************************************************************************************************************/
bool_t PromptUserInput_DTInterrupt(bool_t *bValid)
{
bool_t bQuit; int32_t cardIndex = -1, module = 1;
int32_t MaxModule, MaxChannel;
uint32_t ModuleID;
uint32_t ModuleVer;
uint32_t ModuleRev;
uint32_t ModInfo_Special;
/* Initialize the bValid return state */
*bValid = FALSE;
/* Query user to select card number and module number */
bQuit = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (!bQuit)
{
userInput_DTInt.cardIndex = cardIndex;
check_status(naibrd_GetModuleCount(cardIndex, &MaxModule));
bQuit = naiapp_query_ModuleNumber(MaxModule, 1, &module);
if (!bQuit)
{
bQuit = GetDTLatchStatusTriggerMode();
if (!bQuit)
{
userInput_DTInt.moduleNumber = module;
naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
MaxChannel = naibrd_DT_GetChannelCount(ModuleID);
if (MaxChannel == 0)
printf(" *** Module selection not recognized as DT module. ***\n\n");
else
{
boardState_DTInt.cardIndex = userInput_DTInt.cardIndex;
boardState_DTInt.moduleNumber = userInput_DTInt.moduleNumber;
boardState_DTInt.channel = 1;
userInput_DTInt.channel = 1;
boardState_DTInt.maxChannels = MaxChannel;
*bValid = TRUE;
printf("\nDiscrete Module Info: CardIndex=%d, ModuleNumber=%d, MaxChannels=%d",userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, MaxChannel);
}
}
}
}
return bQuit;
}
/**************************************************************************************************************/
/**
<summary>
ConfigDTInterrupt handles disabling the discrete interrupts, clearing any latched statuses, setting the
interrupt vector (NAI_DT_INTERRUPT_VECTOR), and latch status mode (Edge/Level). The interrupt steering
configuration is configured based on the interruptCommType that is passed in.
</summary>
*/
/**************************************************************************************************************/
void ConfigDTInterrupt(interruptCommType_t interruptCommType)
{
uint32_t rawstatus = 0;
int32_t chan;
uint8_t interrupt_t;
/* Disable Interrupts */
EnableDTInterrupt(FALSE);
/* Clear the Interrupt Status (Read the status and write back "1" to statuses which are set to clear the status) */
check_status(naibrd_DT_GetGroupStatusRaw(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_BIT_LATCHED, &rawstatus));
check_status(naibrd_DT_ClearGroupStatusRaw(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_BIT_LATCHED, rawstatus));
check_status(naibrd_DT_GetGroupStatusRaw(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, &rawstatus));
check_status(naibrd_DT_ClearGroupStatusRaw(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, rawstatus));
check_status(naibrd_DT_GetGroupStatusRaw(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, &rawstatus));
check_status(naibrd_DT_ClearGroupStatusRaw(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, rawstatus));
check_status(naibrd_DT_GetGroupStatusRaw(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_OVERCURRENT_LATCHED, &rawstatus));
check_status(naibrd_DT_ClearGroupStatusRaw(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_OVERCURRENT_LATCHED, rawstatus));
/* Setup the Interrupt Vector - map to the same vector */
check_status(naibrd_DT_SetGroupInterruptVector(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_BIT_LATCHED, NAI_DT_INTERRUPT_VECTOR));
check_status(naibrd_DT_SetGroupInterruptVector(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, NAI_DT_INTERRUPT_VECTOR));
check_status(naibrd_DT_SetGroupInterruptVector(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, NAI_DT_INTERRUPT_VECTOR));
check_status(naibrd_DT_SetGroupInterruptVector(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_OVERCURRENT_LATCHED, NAI_DT_INTERRUPT_VECTOR));
/* Setup the Latched Status Mode */
interrupt_t = (uint8_t)userInput_DTInt.intTriggerType;
for (chan = 1; chan <= boardState_DTInt.maxChannels; chan++)
{
check_status(naibrd_DT_SetEdgeLevelInterrupt(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, chan, NAI_DT_STATUS_BIT_LATCHED, interrupt_t));
check_status(naibrd_DT_SetEdgeLevelInterrupt(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, chan, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, interrupt_t));
check_status(naibrd_DT_SetEdgeLevelInterrupt(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, chan, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, interrupt_t));
check_status(naibrd_DT_SetEdgeLevelInterrupt(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, chan, NAI_DT_STATUS_OVERCURRENT_LATCHED, interrupt_t));
}
/* Setup the Interrupt Steering */
switch (interruptCommType)
{
case ETHERNET_INT:
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_BIT_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_1));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_1));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_1));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_OVERCURRENT_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_1));
break;
case MASTER_PCIBUS_OFFBOARD_INT:
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_BIT_LATCHED, NAIBRD_INT_STEERING_CPCI_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, NAIBRD_INT_STEERING_CPCI_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, NAIBRD_INT_STEERING_CPCI_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_OVERCURRENT_LATCHED, NAIBRD_INT_STEERING_CPCI_APP));
break;
case MASTER_PCIE_BUS_OFFBOARD_INT:
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_BIT_LATCHED, NAIBRD_INT_STEERING_PCIE_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, NAIBRD_INT_STEERING_PCIE_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, NAIBRD_INT_STEERING_PCIE_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_OVERCURRENT_LATCHED, NAIBRD_INT_STEERING_PCIE_APP));
break;
case ONBOARD_INT:
#if defined (PPC_XILINX)
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_BIT_LATCHED, NAIBRD_INT_STEERING_PCIE_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, NAIBRD_INT_STEERING_PCIE_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, NAIBRD_INT_STEERING_PCIE_APP));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_OVERCURRENT_LATCHED, NAIBRD_INT_STEERING_PCIE_APP));
#else
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_BIT_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_0));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_0));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_0));
check_status(naibrd_DT_SetGroupInterruptSteering(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, 1, NAI_DT_STATUS_OVERCURRENT_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_0));
#endif
break;
}
}
/**************************************************************************************************************/
/**
<summary>
EnableDTInterrupt handles enabling/disabling the discrete interrupts.
</summary>
*/
/**************************************************************************************************************/
void EnableDTInterrupt(bool_t enabled)
{
int32_t chan;
for (chan = 1; chan <= boardState_DTInt.maxChannels; chan++)
{
check_status(naibrd_DT_SetInterruptEnable(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, chan, NAI_DT_STATUS_BIT_LATCHED, enabled));
check_status(naibrd_DT_SetInterruptEnable(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, chan, NAI_DT_STATUS_OVERCURRENT_LATCHED, enabled));
check_status(naibrd_DT_SetInterruptEnable(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, chan, NAI_DT_STATUS_LO_HI_TRANS_LATCHED, enabled));
check_status(naibrd_DT_SetInterruptEnable(userInput_DTInt.cardIndex, userInput_DTInt.moduleNumber, chan, NAI_DT_STATUS_HI_LO_TRANS_LATCHED, enabled));
}
}
/**************************************************************************************************************/
/***** Internal Functions *****/
/**************************************************************************************************************/
/**************************************************************************************************************/
/**
<summary>
GetDTLatchStatusTriggerMode handles prompting the user for the trigger mode for the latched status register
(Edge Triggered or Level Triggered).
</summary>
*/
/**************************************************************************************************************/
bool_t GetDTLatchStatusTriggerMode()
{
bool_t bQuit;
uint32_t temp;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
printf("\nEnter Latched Status Trigger Mode (Edge=0, Level=1) (Default=0): ");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if(!bQuit)
{
if(inputResponseCnt > 0)
{
temp = (int32_t)atol((const char*)inputBuffer);
if( temp == 0 || temp == 1)
{
userInput_DTInt.intTriggerType = temp;
}
else
{
printf("ERROR: Invalid Interrupt Trigger Mode.\n");
}
}
else
userInput_DTInt.intTriggerType = 0;
}
return(bQuit);
}