RTD Interrupt
Edit this on GitLab
RTD Interrupt Sample Application (SSK 1.x)
Overview
The RTD Interrupt sample application demonstrates how to configure and handle hardware interrupts on Resistance Temperature Detector (RTD) modules using the NAI Software Support Kit (SSK 1.x). The sample covers two interrupt delivery mechanisms: standard (onboard ISR with a message queue and thread-based processing) and Ethernet IDR (Interrupt Driven Response, network-based). Both variants configure open-detect latched status interrupts on a user-selected range of channels and share the same module-level configuration code in nai_rtd_int.c. The difference is only in how the interrupt notification reaches your application.
This sample supports the following RTD module types: G4, RT1, TR1, and TC1.
The sample ships as two separate executables:
-
RTD_Interrupt— standard interrupt delivery. Installs a hardware ISR (onboard or offboard), enables open-detect latched status interrupts on a user-selected channel range, and processes interrupt events through a message queue and handler thread. Unlike RTD_Interrupt_Basic, this variant handles multiple simultaneous interrupts across a range of channels and supports both onboard and offboard ISR routing. -
RTD_Interrupt_Ethernet— Ethernet IDR variant. Delivers interrupt notifications over the network using IDR commands. The board automatically reads the open-detect latched status register and sends the results to your application as UDP messages.
RTD modules expose the following latched interrupt status types:
-
BIT (
NAI_RTD_STATUS_BIT_LATCHED) — Built-In Test fault detected on an RTD channel. -
Open-detect (
NAI_RTD_STATUS_OPEN_LATCHED) — the RTD sensor circuit is open (disconnected or broken lead). This is the status type configured in this sample. -
Alert Lo (
NAI_RTD_STATUS_ALERT_LO_LATCHED) — the measured temperature has fallen below the low alert threshold. -
Alert Hi (
NAI_RTD_STATUS_ALERT_HI_LATCHED) — the measured temperature has risen above the high alert threshold. -
Alarm Lo (
NAI_RTD_STATUS_ALARM_LO_LATCHED) — the measured temperature has fallen below the low alarm threshold (more severe than alert). -
Alarm Hi (
NAI_RTD_STATUS_ALARM_HI_LATCHED) — the measured temperature has risen above the high alarm threshold (more severe than alarm). -
Summary (
NAI_RTD_STATUS_SUMMARY_LATCHED) — an aggregate status indicating that at least one of the above conditions is active on the channel.
This sample configures interrupts on the open-detect status type only. To monitor other status types, use the same configuration pattern shown here with the corresponding nai_rtd_status_type_t constant. For basic RTD channel configuration and temperature reading, see the RTD BasicOps sample application guide. For a simpler single-channel interrupt example, see the RTD Interrupt Basic guide. For background on interrupt concepts — including edge vs. level triggering, interrupt vector numbering, steering architecture, and latency measurement — see the Interrupts API Guide.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an RTD module installed (G4, RT1, TR1, or TC1).
-
SSK 1.x installed on your development host.
-
The sample applications built. Refer to the SSK 1.x build instructions for your platform if you have not already compiled them.
-
For the Ethernet IDR variant: a Gen4 or later board with an Ethernet connection.
How to Run
Launch either executable from your build output directory. On startup the application looks for a configuration file (default_RTD_Interrupt.txt for the standard variant, default_RTD_Interrupt_Ethernet.txt for the Ethernet variant). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, the standard variant prompts you for channel range, trigger mode, and interrupt delivery options, then begins monitoring for interrupt events. The Ethernet variant prompts for a single channel number and IDR configuration parameters.
Board Connection and Module Selection
|
Note
|
This startup sequence is common to all NAI sample applications. The board connection and module selection code shown here is not specific to RTD. For details on board connection configuration, see the First Time Setup Guide. |
Both variants follow the standard SSK 1.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file or present the interactive board menu. The configuration file is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear. -
Initialize module and interrupt configuration structures with
initializeRTDConfigurations()andinitializeInterruptConfigurations(). -
Query the user for card index with
naiapp_query_CardIndex(). -
Query the user for module number with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleID()to verify an RTD module is installed at the selected slot.
initializeRTDConfigurations(0, 0, 0, 0, 0, 0);
initializeInterruptConfigurations(FALSE, FALSE, FALSE, 0, 0, 0, 0);
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
inputRTDConfig.cardIndex = cardIndex;
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
inputRTDConfig.module = module;
if (stop != TRUE)
{
inputRTDConfig.modid = naibrd_GetModuleID(cardIndex, module);
if ((inputRTDConfig.modid != 0))
{
Run_RTD_Interrupt();
}
}
}
}
}
The RtdConfig structure tracks the board and module context throughout the application:
typedef struct
{
int32_t cardIndex;
int32_t module;
uint32_t modid;
int32_t channel;
int32_t maxChannel;
int32_t minChannel;
} RtdConfig;
In your own application, you will track the same values — card index, module slot number, module ID, and the channel range you intend to monitor.
|
Important
|
Common connection errors you may encounter at this stage:
|
User Configuration Queries
Before configuring interrupts, the standard variant (RTD_Interrupt) queries the user for several configuration parameters. These queries are a sample convenience — in your own application, you would set these values directly.
Channel Range
The sample prompts for a minimum and maximum channel number. All channels in this range will have interrupts enabled:
maxChannel = naibrd_RTD_GetChannelCount(inputRTDConfig.modid);
bQuit = naiapp_query_ForChannelRange(&inputRTDConfig.minChannel,
&inputRTDConfig.maxChannel,
minChannel, maxChannel);
naibrd_RTD_GetChannelCount() returns the total number of channels available on the module. The channel range determines which channels will have open-detect latched status interrupts enabled. Consult your module’s manual for the channel count on your specific module type.
Trigger Mode (Edge vs. Level)
bQuit = GetRTDLatchStatusTriggerMode(&inputInterruptConfig.interrupt_Edge_Trigger);
The GetRTDLatchStatusTriggerMode() function prompts for edge-triggered (0) or level-triggered (1) operation:
-
Edge-triggered (0) — the interrupt fires once when the status bit transitions from 0 to 1. This produces a single notification per event and is the default.
-
Level-triggered (1) — the interrupt continues to assert as long as the status condition remains active. This ensures your application does not miss events, but the interrupt will keep firing until you clear the status register.
Interrupt Clear Prompting
bQuit = QueryUserForClearingInterruptPrompts(&inputInterruptConfig.bPromptForInterruptClear);
When enabled, the handler pauses after each interrupt and waits for the user to press "C" before clearing the status register. This is useful for debugging — it lets you observe the interrupt state before re-arming. In a production application, you would clear the status automatically.
Onboard vs. Offboard ISR
bQuit = QueryUserForOnboardOffboardInterrupts(&inputInterruptConfig.bProcessOnboardInterrupts);
This selects whether the ISR runs on the board’s onboard processor or on an external host connected via cPCI/PCIe. Onboard processing is the typical configuration for Ethernet-connected boards. Offboard processing is used when the board is installed in a CompactPCI or PCIe chassis and the host processor handles interrupts directly.
Interrupt Steering
bQuit = GetIntSteeringTypeFromUser(&inputInterruptConfig.steering);
Interrupt steering determines the physical path by which the interrupt signal reaches your handler:
-
Onboard (
NAIBRD_INT_STEERING_ON_BOARD_0orON_BOARD_1) — handled locally on the board’s processor. -
cPCI offboard (
NAIBRD_INT_STEERING_CPCI_APP) — routes the interrupt to the CompactPCI backplane host. -
PCIe offboard (
NAIBRD_INT_STEERING_PCIE_APP) — routes the interrupt to the PCIe host.
Clearing Status and Configuring Interrupts
Before enabling interrupts, the configureRTDToInterruptOnRx() function clears stale latched status, assigns an interrupt vector, sets the trigger mode, and configures steering for the open-detect latched status type. Always clear status registers before enabling interrupts — stale latched status from a previous run or power-on state will trigger immediate spurious interrupts.
Disabling Existing Interrupts and Clearing Stale Status
The configuration function first disables any previously enabled interrupts and clears stale status to ensure a clean state:
nai_rtd_status_type_t typeOpen = NAI_RTD_STATUS_OPEN_LATCHED;
check_status(naibrd_RTD_SetInterruptEnableRaw(cardIndex, module, typeOpen, 0));
check_status(naibrd_RTD_ClearStatusRaw(cardIndex, module, typeOpen, 0xFFFF));
naibrd_RTD_SetInterruptEnableRaw() with a value of 0 disables interrupts on all channels for the open-detect status type. naibrd_RTD_ClearStatusRaw() with 0xFFFF clears the latched status for all channels. These "raw" API functions operate on a bitmask representing all channels simultaneously rather than iterating per-channel.
Interrupt Vector
The open-detect latched status type is assigned an interrupt vector so the handler can identify which condition triggered the event:
#define NAI_RTD_INTERRUPT_VECTOR 0xA0
check_status(naibrd_RTD_SetInterruptVector(cardIndex, module, typeOpen, vector));
naibrd_RTD_SetInterruptVector() sets the vector for all channels sharing the open-detect status type. In your own application, choose a vector value that does not conflict with other modules on the same board. If you monitor multiple RTD status types simultaneously, assign each type a unique vector so your handler can distinguish which condition fired.
Trigger Mode Per-Channel
The trigger mode is set per-channel across all channels on the module:
nai_rtd_interrupt_t interrupt_Level_Trigger = NAI_RTD_LEVEL_INTERRUPT;
maxChan = naibrd_RTD_GetChannelCount(inputRTDConfig.modid);
for (channel = 1; channel <= maxChan; channel++)
{
check_status(naibrd_RTD_SetInterruptEdgeLevel(cardIndex, module, channel,
typeOpen, interrupt_Level_Trigger));
}
Note that the sample defaults to level-triggered mode (NAI_RTD_LEVEL_INTERRUPT) in the configuration function, but the user can override this via the GetRTDLatchStatusTriggerMode() prompt. naibrd_RTD_SetInterruptEdgeLevel() sets the trigger mode per-channel and per-status-type.
Interrupt Steering
check_status(naibrd_RTD_SetInterruptSteering(cardIndex, module, typeOpen, steering));
Steering is set per-status-type and applies to all channels. The steering value must match the interrupt delivery mechanism you are using: NAIBRD_INT_STEERING_ON_BOARD_0 for the standard onboard ISR, NAIBRD_INT_STEERING_ON_BOARD_1 for Ethernet IDR, or NAIBRD_INT_STEERING_CPCI_APP / NAIBRD_INT_STEERING_PCIE_APP for offboard delivery.
|
Important
|
Common Errors
|
ISR Installation and Interrupt Handling (Standard Variant)
The standard variant installs a hardware ISR, initializes a message queue and processing thread, and then enables interrupts. This approach handles multiple simultaneous interrupts across a range of channels.
Installing the ISR
The ISR is installed based on whether the user selected onboard or offboard processing:
setIRQ(inputInterruptConfig.steering, &inputInterruptConfig.irq);
inputInterruptConfig.cardIndex = inputRTDConfig.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*)&inputRTDConfig.cardIndex));
}
setIRQ() maps the steering value to the appropriate IRQ number. naibrd_InstallISR() registers the ISR callback with the board driver. The IntOnboardIsr and IntOffboardIsr functions are shared SSK utilities that post the interrupt vector to a message queue for asynchronous processing.
In your own application, call naibrd_InstallISR() with your own ISR callback. The ISR should be minimal — set a flag, post to a queue, or signal an event. Do not call blocking functions or perform lengthy operations inside the ISR.
Message Queue and Handler Thread
After installing the ISR and configuring the module, the sample initializes a message queue and a processing thread:
InitInterruptAppThread(ONBOARD_INT, 0);
nai_msDelay(10);
UpdateThreadState(RUN);
InitInterruptAppThread() creates a background thread that waits on the message queue for interrupt events. When the ISR fires, it posts the interrupt vector to the queue. The thread dequeues the vector and calls the registered handler function.
Enabling Interrupts
With the ISR installed and the handler thread running, interrupts are enabled on all channels in the selected range:
void enableRTDInterrupts(RtdConfig inputRTDConfig, bool_t enable) {
int32_t channel;
nai_rtd_status_type_t typeOpen = NAI_RTD_STATUS_OPEN_LATCHED;
int32_t enableRegVal = 0;
int32_t isEnabled = 0;
for (channel = inputRTDConfig.minChannel;
channel <= inputRTDConfig.maxChannel; channel++)
{
isEnabled = ((1 << (channel-1)) & enableRegVal);
if (enable)
enableRegVal = (1 << (channel-1)) | enableRegVal;
else if (isEnabled)
enableRegVal = (1 << (channel-1)) ^ enableRegVal;
}
check_status(naibrd_RTD_SetInterruptEnableRaw(inputRTDConfig.cardIndex,
inputRTDConfig.module, typeOpen, enableRegVal));
}
Unlike some other module types that enable interrupts per-channel, the RTD module uses naibrd_RTD_SetInterruptEnableRaw() with a raw bitmask. Each bit in enableRegVal corresponds to a channel (bit 0 = channel 1, bit 1 = channel 2, etc.). The function builds the bitmask by OR-ing the bit for each channel in the selected range.
Handling Interrupts
The handler function assigned to rtdIntProcessFunc is called by the background thread when an interrupt event arrives:
rtdIntProcessFunc = handleRTDInterrupt;
The handleRTDInterrupt() function reads the open-detect latched status, clears it, and displays the interrupt information:
void handleRTDInterrupt(uint32_t nVector) {
uint32_t statusOpen;
printf("\n\nInterrupt Occurred \n\n");
if (inputInterruptConfig.bPromptForInterruptClear)
{
promptUserToClearInterrupt_RTD();
}
check_status(naibrd_RTD_GetStatusRaw(inputRTDConfig.cardIndex,
inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, &statusOpen));
check_status(naibrd_RTD_ClearStatusRaw(inputRTDConfig.cardIndex,
inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, statusOpen));
printInterruptInformationToFile(nVector, statusOpen, FALSE, fifoDataFile);
printInterruptInformation_RTD(nVector, statusOpen, FALSE);
}
The handler pattern is: optionally pause for user acknowledgment (debugging feature), read the raw status to identify which channels triggered, clear the status to re-arm the interrupt, and display the results. The printInterruptInformation_RTD() function prints the interrupt vector and open-detect status bitmask.
In the status bitmask, each bit corresponds to a channel. For example, if statusOpen is 0x05, channels 1 and 3 (bits 0 and 2) have an open-detect condition active. The handler also logs interrupt data to a file via printInterruptInformationToFile() for post-run analysis.
Cleanup
When the user exits, the application disables interrupts and uninstalls the ISR:
enableRTDInterrupts(inputRTDConfig, FALSE);
check_status(naibrd_UninstallISR(inputInterruptConfig.cardIndex));
Always disable interrupts before uninstalling the ISR. If you uninstall the ISR while interrupts are still enabled, the board may attempt to deliver interrupts to a handler that no longer exists.
|
Important
|
Common Errors
|
Ethernet IDR Interrupt Handling
The Ethernet IDR variant (RTD_Interrupt_Ethernet) delivers interrupt notifications over the network instead of through a local ISR. Use this approach when your application runs on a remote host connected via Ethernet, when a hardware ISR is not available or practical for your deployment, or when you want the board to automatically read status registers and package the results into UDP messages.
How the Ethernet IDR Mechanism Works
The Ethernet IDR mechanism works as follows:
-
Your application configures an IDR definition on the board that specifies: a trigger vector, a response IP address and port, a transport protocol (UDP), and a set of Ethernet commands (register reads) to execute when the interrupt fires.
-
When the specified interrupt vector fires on the board, the board’s onboard processor automatically executes the pre-configured Ethernet commands — reading the open-detect latched status register.
-
The board packages the results into Ethernet messages and sends them to the configured IP address and port.
-
Your application runs a listener (IDR server) that receives and decodes these messages.
This approach eliminates the need for your host application to poll registers over the network. The board does the register reads locally (fast) and sends only the results over the network, reducing round-trips and latency.
Prerequisites
Ethernet IDR requires a Generation 4 or later board with Ethernet support. The Ethernet variant verifies this at startup:
bGen4RtdIDRCommands = SupportsGen4Ether(inputRTDConfig.cardIndex);
if (!bGen4RtdIDRCommands)
{
printf("RTD Ethernet Interrupt Support Prior to Generation 4 "
"Ethernet commands currently not supported\n");
bQuit = TRUE;
}
If the check fails, the board’s firmware does not support the Gen4 Ethernet protocol and IDR commands will not work. You may need to update the board firmware.
IDR Configuration
The Ethernet variant prompts the user for the IDR response IP address and port (defaults: 192.168.1.100:52802), then builds and registers a single IDR definition for open-detect latched status (DEF_ETHERNET_RTD_IDR_ID). Since this sample monitors only one status type, only one IDR definition is needed — to monitor additional status types, you would register separate IDR definitions with distinct vectors for each type.
The setupRTDIDRConfiguration() function constructs Ethernet commands and registers the IDR:
check_status(naibrd_Ether_ClearIDRConfig(cardIndex,
(uint16_t)DEF_ETHERNET_RTD_IDR_ID));
InitRTDRxIDRCommands(inputRTDConfig, inputIDRConfig, bGen4RtdIDRCommands);
check_status(naibrd_Ether_SetIDRConfig(cardIndex,
(uint16_t)DEF_ETHERNET_RTD_IDR_ID,
protocol, ipLength, ipAddress, port, vector,
*cmdcount, *cmdlength, commands));
The InitRTDRxIDRCommands() function constructs the Ethernet read command by resolving the board address and module offset:
status = check_status(naibrd_GetModuleOffset(inputRTDConfig.cardIndex,
inputRTDConfig.module, &moduleOffset));
if (status == NAI_SUCCESS)
status = check_status(naibrd_GetAddress(inputRTDConfig.cardIndex,
&boardAddress));
These addresses are combined with the open-detect latched status register offset (NAI_RTD_GEN5_REG_OPEN_STATUS_LATCHED_ADD) to form the full register address for the Ethernet read command.
After registration, the IDR is started:
check_status(naibrd_Ether_StartIDR(inputIDRConfig.cardIndex,
(uint16_t)DEF_ETHERNET_RTD_IDR_ID));
Onboard vs. Offboard IDR
The Ethernet variant supports both onboard and offboard IDR processing. This determines the board interface and steering used for the IDR commands:
if (inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
{
inputIDRConfig.cardIndex = inputRTDConfig.cardIndex;
inputIDRConfig.boardInterface = NAI_INTF_ONBOARD;
inputInterruptConfig.steering = NAIBRD_INT_STEERING_ON_BOARD_1;
}
else
{
inputIDRConfig.cardIndex = 0;
inputIDRConfig.boardInterface = NAI_INTF_PCI;
inputInterruptConfig.steering = NAIBRD_INT_STEERING_CPCI_APP;
}
For onboard processing, steering is set to ON_BOARD_1 (which triggers the IDR mechanism). For offboard processing, the board interface is set to PCI and steering routes to the cPCI host.
Decoding IDR Responses
When the IDR server receives a message, it calls HandleRTDEtherInterrupt() to decode and process the results:
void HandleRTDEtherInterrupt(uint16_t msglen, uint8_t msg[],
uint16_t tdr_idr_id)
{
static uint8_t status;
uint16_t seq;
nai_ether_typecode_t typeCode;
nai_ether_gen_t gen = NAI_ETHER_GEN4;
int32_t size;
int32_t commandIndex;
nai_ether_DecodeMessageHeader(msg, msglen, &seq, &typeCode, gen, &size);
commandIndex = (seq & (0x0F << 6)) >> 6;
switch (typeCode)
{
case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_WRITE_4:
break;
case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4:
if (command_index_interrupt_status == commandIndex)
status = msg[11];
break;
}
if (commandIndex == inputIDRConfig.cmdcount - 1)
{
printf("\nInterrupt Occurred\n");
printInterruptInformation_RTD(tdr_idr_id, status, TRUE);
printInterruptInformationToFile(tdr_idr_id, status, TRUE, fifoDataFile);
}
}
The handler decodes the Gen4 Ethernet response, extracts the open-detect latched status register value from the read response, and waits until all IDR commands have been processed before printing the results. The tdr_idr_id identifies which IDR definition triggered the response. When the isEther flag is TRUE, the print functions label the interrupt identifier as "IDR ID" rather than "Vector."
Stopping the IDR
When the user exits, the IDR must be stopped and cleaned up:
check_status(naibrd_Ether_StopIDR(inputIDRConfig.cardIndex,
(uint16_t)DEF_ETHERNET_RTD_IDR_ID));
check_status(naibrd_Ether_ClearIDRConfig(inputIDRConfig.cardIndex,
(uint16_t)DEF_ETHERNET_RTD_IDR_ID));
Always stop the IDR before closing the connection. If you close the connection without stopping the IDR, the board will continue sending messages to an address that is no longer listening.
|
Important
|
Common Ethernet IDR Errors
|
Troubleshooting Reference
This table summarizes common errors and symptoms covered in the sections above. For detailed context, refer to the relevant section. Consult your module’s manual for hardware-specific diagnostic procedures.
Debugging Interrupts That Are Not Firing
When interrupts are not being delivered, use this two-step approach to isolate the problem:
-
Check whether the status registers are changing. Call
naibrd_RTD_GetStatusRaw()withNAI_RTD_STATUS_OPEN_LATCHEDto read the latched status. If the status bits are changing when an open-detect condition occurs, the module is detecting events correctly — the issue is in your interrupt delivery path (steering, ISR installation, or IDR configuration). -
If the status registers are NOT changing, the issue is at the hardware or channel configuration level. Verify that the RTD module is installed correctly, that RTD sensors are connected, and that the channels are functional. Consult your module’s manual for open-detect conditions and diagnostic procedures.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found or connection timeout |
Board not powered, incorrect or missing configuration file, network issue |
Verify hardware is powered and connected. If the configuration file exists, check that it lists the correct interface and address. If it does not exist, the board menu will appear — configure and save your connection settings. |
Module not detected or channel count is 0 |
No RTD module installed at the selected slot, incorrect module number, or a non-RTD module is present |
Verify hardware configuration. |
Spurious interrupts immediately after enable |
Stale latched status from previous run or power-on state |
Always clear all status registers before enabling interrupts. Use the clear-then-configure pattern shown in |
No open-detect interrupts |
No open-detect condition present (sensor connected), wrong steering mode, ISR not installed |
Verify that an open-detect condition is actually occurring on the RTD channels (disconnect or break a sensor lead). Confirm steering matches your delivery mechanism. |
ISR never fires |
Wrong IRQ, steering mismatch, |
Verify that |
Handler thread not processing interrupts |
Message queue not initialized, thread not in RUN state |
Ensure |
Continuous interrupts without new open-detect faults |
Level-triggered mode active and status not cleared |
Verify the handler calls |
Ethernet IDR: no messages received |
Wrong response IP/port, firewall blocking, IDR not started, Gen4 not supported |
Verify IP address and port match your listener. Confirm |
Steering mismatch |
Steering set to wrong destination for the chosen delivery mechanism |
Match steering to where your application executes. Standard onboard ISR: |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail. This sample consists of two main application files and three shared utility files.
Full Source — RTD_Interrupt.c (SSK 1.x)
/**************************************************************************************************************/
/**
<summary>
The RTD_Interrupt program demonstrates how to check for RTD Open interrupts via PCI Bus Connection
to the board. 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 RTD_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_rtd_int.h"
#include "nai_rtd_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_rtd.h"
IntProcessFuncDef rtdIntProcessFunc;
InterruptConfig inputInterruptConfig;
/* Extern Functions or Variables*/
extern RtdConfig inputRTDConfig;
extern FILE* fifoDataFile;
/*********************************************/
/* Application Name and Revision Declaration */
/*********************************************/
static const int8_t *CONFIG_FILE = (int8_t *)"default_RTD_Interrupt.txt";
/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_RTD_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 RTD_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;
initializeRTDConfigurations(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);
inputRTDConfig.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);
inputRTDConfig.module = module;
if (stop != TRUE)
{
inputRTDConfig.modid = naibrd_GetModuleID(cardIndex, module);
if ((inputRTDConfig.modid != 0))
{
Run_RTD_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 interrupt when RTD open latched status of channel is set to 1.
API CALLS - naibrd_RTD_SetInterruptEdgeLevel, naibrd_RTD_SetInterruptVector, naibrd_RTD_SetInterruptSteering,
naibrd_RTD_SetInterruptEnableRaw, naibrd_RTD_ClearStatusRaw
4. Nothing needs to be done for the RTD 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_RTD_ClearStatusRaw
7. Clear Module Configurations
API CALLS - naibrd_RTD_SetInterruptEnableRaw
8. Clear Board Configurations
API CALLS - naibrd_UninstallISR
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_RTD_Interrupt()
{
bool_t bQuit = FALSE;
int32_t minChannel;
int32_t maxChannel;
minChannel = 1;
maxChannel = naibrd_RTD_GetChannelCount(inputRTDConfig.modid);
/* Query for Channels to Operate on */
bQuit = naiapp_query_ForChannelRange(&inputRTDConfig.minChannel, &inputRTDConfig.maxChannel, minChannel, maxChannel);
/* Query for Trigger Status of interrupts */
if (!bQuit)
{
bQuit = GetRTDLatchStatusTriggerMode(&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)
{
if (inputInterruptConfig.displayData)
fifoDataFile = stdout;
else
fifoDataFile = fopen("fifoData.txt", "w+");
/**** 2. Implement Bus Interrupt Handling ****/
setIRQ(inputInterruptConfig.steering, &inputInterruptConfig.irq);
inputInterruptConfig.cardIndex = inputRTDConfig.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*)&inputRTDConfig.cardIndex));
}
/**** 3. configure Module to perform interrupts ****/
configureRTDToInterruptOnRx(inputInterruptConfig, inputRTDConfig);
/**** Initialize Message Queue ****/
InitInterruptAppThread(ONBOARD_INT, 0);
nai_msDelay(10);
UpdateThreadState(RUN);
/**** Enable Interrupts ****/
enableRTDInterrupts(inputRTDConfig, TRUE);
/*** 5. Show Interrupt Handling (contains step 6) ***/
rtdIntProcessFunc = handleRTDInterrupt;
/*** Display RTD Interrupt Message ***/
DisplayMessage_RTDInterrupt(MSG_BANNER_RTD_INT);
/**** Wait on program threads ****/
while (!isThreadStateTerminated())
{
}
bQuit = TRUE;
if (!inputInterruptConfig.displayData)
fclose(fifoDataFile);
/***** 7. Clear Module Configurations *****/
enableRTDInterrupts(inputRTDConfig, FALSE);
/***** 8. Clear Board Configurations *****/
check_status(naibrd_UninstallISR(inputInterruptConfig.cardIndex));
}
return bQuit;
}
Full Source — RTD_Interrupt_Ethernet.c (SSK 1.x)
/**************************************************************************************************************/
/**
<summary>
The RTD_Interrupt_Ethernet program demonstrates how to check for RTD Open interrupts via Ethernet connection
to the board. 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_rtd_int_ether.h"
#include "nai_rtd_int.h"
#include "nai_rtd_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_rtd.h"
#include "maps/nai_map_rtd.h"
static uint8_t DEF_RX_RESPONSE_IPv4_ADDR[] = { 192,168,1,100 };
static uint8_t COMMANDS[MAX_ETHER_IDR_CMD_CNT*MAX_ETHER_BLOCK_REG_CNT];
/*********************************************/
/* Program Configurations */
/*********************************************/
InterruptConfig inputInterruptConfig;
IDRConfig inputIDRConfig;
ClearInterrupt RTD_ClearInterrupt;
etherIntFuncDef rtdEtherIntFunc;
bool_t bDisplayEtherUPR;
/* Extern Functions or Variables*/
extern RtdConfig inputRTDConfig;
extern FILE* fifoDataFile;
/*********************************************/
/* Application Name and Revision Declaration */
/*********************************************/
static const int8_t *CONFIG_FILE = (int8_t *)"default_RTD_Interrupt_Ethernet.txt";
/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_RTD_Interrupt_Basic_Ethernet();
/**************************************************************************************************************/
/***** 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 RTD_Interrupt_Basic_Ethernet(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;
initializeRTDConfigurations(0, 0, 0, 0, 0, 0);
initializeInterruptConfigurations(FALSE, FALSE, FALSE, 0, NAIBRD_INT_STEERING_ON_BOARD_1, -1, 0);
initializeIDRConfigurations(0, 0, DEF_RX_RESPONSE_PROTOCOL, DEF_RX_RESPONSE_PORT, DEF_RX_RESPONSE_IPv4_ADDR, DEF_RX_RESPONSE_IPv4_LENGTH, COMMANDS, 0, 0, DEF_ETHERNET_RTD_IDR_ID);
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
inputRTDConfig.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);
inputRTDConfig.module = module;
if (stop != TRUE)
{
inputRTDConfig.modid = naibrd_GetModuleID(cardIndex, module);
if ((inputRTDConfig.modid != 0))
{
Run_RTD_Interrupt_Basic_Ethernet();
}
}
}
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.
2a. Ethernet Interrupt Handling - Setup IDR to handle interrupt
API CALLS - naibrd_Ether_SetIDRConfig, naibrd_Ether_StartIDR,naibrd_Ether_ClearIDRConfig
3. Enable Module Interrupts- Configures module to interrupt when RTD open latched status of channel is set to 1.
API CALLS - naibrd_RTD_SetInterruptEdgeLevel, naibrd_RTD_SetInterruptVector, naibrd_RTD_SetInterruptSteering,
naibrd_RTD_SetInterruptEnableRaw, naibrd_RTD_ClearStatusRaw
4. Nothing needs to be done for the RTD module
5. Show Interrupt Handling - The IDR server will listen on the boards ports for IDRs indicating an interrupt.
These results will be decoded and displayed to the user.
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, the write command is included in the IDR.
API CALLS - nai_ether_BeginWriteMessage, nai_ether_WriteMessageData, nai_ether_FinishMessage
7. Clear Module Configurations
API CALLS - naibrd_RTD_SetInterruptEnableRaw
8. Clear Board Configurations
API CALLS - naibrd_Ether_StopIDR, naibrd_Ether_ClearIDRConfig
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_RTD_Interrupt_Basic_Ethernet()
{
bool_t bQuit = FALSE;
bool_t bGen4RtdIDRCommands;
inputRTDConfig.maxChannel = naibrd_RTD_GetChannelCount(inputRTDConfig.modid);
inputRTDConfig.minChannel = 1;
/* check if RTD module supports GEN 4 Ethernet */
bGen4RtdIDRCommands = SupportsGen4Ether(inputRTDConfig.cardIndex);
if (!bGen4RtdIDRCommands)
{
printf("RTD Ethernet Interrupt Support Prior to Generation 4 Ethernet commands currently not supported\n");
bQuit = TRUE;
}
if (!bQuit)
{
bQuit = naiapp_query_ChannelNumber(inputRTDConfig.maxChannel, inputRTDConfig.minChannel, &inputRTDConfig.channel);
}
if (!bQuit)
{
bQuit = QueryIDRConfigInformation(&inputIDRConfig);
}
if (!bQuit)
{
bQuit = QueryUserForOnboardOffboardInterrupts(&inputInterruptConfig.bProcessOnboardInterrupts);
}
if (!bQuit)
{
bQuit = QueryUserForEtherIDRMsgDisplay(&bDisplayEtherUPR);
}
if (!bQuit)
{
if (inputInterruptConfig.displayData)
fifoDataFile = stdout;
else
fifoDataFile = fopen("RTD_Interrupt_FIFO_Data.txt", "w+");
/**** 2. Setup IDR to Handle Interrupt (also contains step 6) ****/
if (inputInterruptConfig.bProcessOnboardInterrupts == TRUE)
{
inputIDRConfig.cardIndex = inputRTDConfig.cardIndex;
inputIDRConfig.boardInterface = NAI_INTF_ONBOARD;
inputInterruptConfig.steering = NAIBRD_INT_STEERING_ON_BOARD_1;
}
else /* OffBoard Interrupt */
{
inputIDRConfig.cardIndex = 0;
inputIDRConfig.boardInterface = NAI_INTF_PCI;
inputInterruptConfig.steering = NAIBRD_INT_STEERING_CPCI_APP;
/* Setting steering on master to listener */
}
check_status(naibrd_RTD_ClearStatusRaw(inputRTDConfig.cardIndex, inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, 0x0));
setupRTDIDRConfiguration(inputRTDConfig, &inputIDRConfig, bGen4RtdIDRCommands);
check_status(naibrd_Ether_StartIDR(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_RTD_IDR_ID));
/**** 3. configure module To Interrupt ****/
configureRTDToInterruptOnRx(inputInterruptConfig, inputRTDConfig);
enableRTDInterrupts(inputRTDConfig, TRUE);
/**** 4. Configure RTD to cause Interrupts ****/
/* Nothing needs to be done for the RTD module */
/**** 5. Show Interrupt Handling ****/
RTD_ClearInterrupt = ClearInterrupt_RTD;
rtdEtherIntFunc = HandleRTDEtherInterrupt;
bQuit = runIDRServer(inputIDRConfig);
/**** 6. Prompt User To Clear Interrupt Statuses ****/
/* Taken care of in step 2 */
/***** 7. Clear Module Configurations *****/
enableRTDInterrupts(inputRTDConfig, FALSE);
/***** 8. Clear Board Configurations *****/
check_status(naibrd_Ether_StopIDR(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_RTD_IDR_ID));
check_status(naibrd_Ether_ClearIDRConfig(inputIDRConfig.cardIndex, (uint16_t)DEF_ETHERNET_RTD_IDR_ID));
}
return bQuit;
}
Full Source — nai_rtd_int.c (SSK 1.x)
/* Common Sample Program include files */
#include "include/naiapp_interrupt.h"
#include "include/naiapp_interrupt_ether.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"
/* Common RTD Sample Program include files */
#include "nai_rtd_int.h"
#include "nai_rtd_cfg.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "naibrd_ether.h"
#include "functions/naibrd_rtd.h"
#include "../src/maps/nai_map_rtd.h"
#include <stdlib.h>
bool_t interruptOccurred;
uint32_t interruptVectorOpen;
/* Extern Functions or Variables*/
extern InterruptConfig inputInterruptConfig;
extern RtdConfig inputRTDConfig;
extern FILE* fifoDataFile;
/**************************************************************************************************************/
/**
<summary>
The routine is called to handle a interrupt. This function alerts checkForInterrupt that an interrupt has occurred.
In vxWorks you must clear the Interrupt on the board within the ISR.
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
void basic_ISR_RTD( uint32_t param )
#else
void basic_ISR_RTD( void *param, uint32_t vector )
#endif
{
interruptOccurred = TRUE;
#if defined (WIN32)
UNREFERENCED_PARAMETER( param );
#endif
#if defined (__VXWORKS__)
interruptVectorOpen = nai_Onboard_GetInterruptVector();
nai_Onboard_ClearInterrupt();
#else
interruptVectorOpen = vector;
#endif
}
/**************************************************************************************************************/
/**
<summary>
This function configures an interrupt to occur when the open latched status of any of the RTD channels is
set to 1.
</summary>
*/
/**************************************************************************************************************/
void configureRTDToInterruptOnRx( InterruptConfig inputInterruptConfig, RtdConfig inputRTDConfig )
{
int32_t channel;
int32_t maxChan;
int32_t cardIndex = inputRTDConfig.cardIndex;
int32_t module = inputRTDConfig.module;
int32_t vector = NAI_RTD_INTERRUPT_VECTOR;
nai_rtd_interrupt_t interrupt_Level_Trigger = NAI_RTD_LEVEL_INTERRUPT;
int32_t steering = inputInterruptConfig.steering;
nai_rtd_status_type_t typeOpen = NAI_RTD_STATUS_OPEN_LATCHED;
/* clear interruptConfigs of previous channels */
check_status( naibrd_RTD_SetInterruptEnableRaw( cardIndex, module, typeOpen, 0 ) );
check_status( naibrd_RTD_ClearStatusRaw( cardIndex, module, typeOpen, 0xFFFF ) );
check_status( naibrd_RTD_SetInterruptVector( cardIndex, module, typeOpen, vector ) );
maxChan = naibrd_RTD_GetChannelCount( inputRTDConfig.modid );
for ( channel = 1; channel <= maxChan; channel++ )
{
check_status( naibrd_RTD_SetInterruptEdgeLevel( cardIndex, module, channel, typeOpen, interrupt_Level_Trigger ) ); /* Level triggered */
}
check_status( naibrd_RTD_SetInterruptSteering( cardIndex, module, typeOpen, steering ) );
}
/**************************************************************************************************************/
/**
<summary>
Enables the channels within the (minChannel, maxChannel) range to interrupt
if enable is true and disables them otherwise.
</summary>
*/
/**************************************************************************************************************/
void enableRTDInterrupts( RtdConfig inputRTDConfig, bool_t enable )
{
int32_t channel;
nai_rtd_status_type_t typeOpen = NAI_RTD_STATUS_OPEN_LATCHED;
int32_t enableRegVal = 0;
int32_t isEnabled = 0;
for ( channel = inputRTDConfig.minChannel; channel <= inputRTDConfig.maxChannel; channel++ )
{
isEnabled = ( ( 1 << ( channel-1 ) ) & enableRegVal );
if (enable)
enableRegVal = ( 1 << ( channel-1 ) ) | enableRegVal;
else if ( isEnabled )
enableRegVal = ( 1 << ( channel-1 ) ) ^ enableRegVal;
}
check_status( naibrd_RTD_SetInterruptEnableRaw( inputRTDConfig.cardIndex, inputRTDConfig.module, typeOpen, enableRegVal ) );
}
/**************************************************************************************************************/
/**
<summary>
Prompts user to check if an interrupt has occurred. MyIsr() should be installed if using this function.
</summary>
*/
/**************************************************************************************************************/
bool_t checkForRTDInterrupt( RtdConfig inputRTDConfig )
{
bool_t bQuit;
uint32_t statusOpen;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
statusOpen = 0;
bQuit = FALSE;
interruptOccurred = FALSE;
while (!bQuit)
{
printf( "\nPress enter to check if interrupt Occurred (press Q to quit):" );
bQuit = naiapp_query_ForQuitResponse( sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt );
if (!bQuit)
{
if (interruptOccurred)
{
check_status( naibrd_RTD_GetStatusRaw( inputRTDConfig.cardIndex, inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, &statusOpen ) );
printf( "\nOpen Vector = %#x \n", interruptVectorOpen );
printf( "Open Status = %#x \n", statusOpen );
interruptOccurred = FALSE;
}
else
{
printf( "\nNo Interrupt Occurred" );
}
printf( "\n\nWould you like to clear the status registers? (default:N):" );
bQuit = naiapp_query_ForQuitResponse( sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt );
if ( inputBuffer[0] == 'y' || inputBuffer[0] =='Y' )
{
check_status( naibrd_RTD_ClearStatusRaw( inputRTDConfig.cardIndex, inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, statusOpen ) );
}
}
}
return bQuit;
}
/**************************************************************************************************************/
/**
<summary>
GetRTDLatchStatusTriggerMode handles prompting the user for the trigger mode for the latched status register
(Edge Triggered or Level Triggered).
</summary>
*/
/**************************************************************************************************************/
bool_t GetRTDLatchStatusTriggerMode( int32_t* interrupt_Edge_Trigger )
{
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 )
{
*interrupt_Edge_Trigger = temp;
}
else
{
printf( "ERROR: Invalid Interrupt Trigger Mode.\n" );
}
}
else
*interrupt_Edge_Trigger = 0;
}
return( bQuit );
}
/**************************************************************************************************************/
/**
<summary>
DisplayMessage_RTDInterrupt handles displaying the messages associated with the msgId passed in.
</summary>
*/
/**************************************************************************************************************/
void DisplayMessage_RTDInterrupt( int32_t msgId )
{
switch (msgId)
{
case (int32_t)MSG_BANNER_RTD_INT:
{
printf( "\n********************************************************************************" );
printf( "\n****** RTD INTERRUPT ******" );
printf( "\nAn interrupt will occur when one of the interrupt conditions of the RTD module" );
printf( "\nstatuses is met." );
printf( "\n********************************************************************************" );
}
break;
case (int32_t)MSG_USER_CLEAR_RTD_INT:
{
printf( "Press \"C\" to clear interrupts... " );
}
break;
}
}
/**************************************************************************************************************/
/**
<summary>
This routine takes in the vector of the RTD open interrupt that has just occurred. And gets the open latched
status of all channels that interrupted, and prints it.
</summary>
*/
/**************************************************************************************************************/
void handleRTDInterrupt( uint32_t nVector )
{
uint32_t statusOpen;
printf( "\n\nInterrupt Occurred \n\n" );
if ( inputInterruptConfig.bPromptForInterruptClear )
{
promptUserToClearInterrupt_RTD();
}
check_status( naibrd_RTD_GetStatusRaw( inputRTDConfig.cardIndex, inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, &statusOpen ) );
check_status( naibrd_RTD_ClearStatusRaw( inputRTDConfig.cardIndex, inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, statusOpen ) );
printInterruptInformationToFile( nVector, statusOpen, FALSE, fifoDataFile );
printInterruptInformation_RTD( nVector, statusOpen, FALSE );
}
/**************************************************************************************************************/
/**
<summary>
This function prompts the user to clear the open status latched register upon open interrupt.
</summary>
*/
/**************************************************************************************************************/
void promptUserToClearInterrupt_RTD()
{
/* Prompt the user to clear the interrupt received */
SetUserRequestClearInt( FALSE );
printf( "\n" );
DisplayMessage_RTDInterrupt( MSG_USER_CLEAR_RTD_INT );
/* Wait for the user to respond */
while ( !GetUserRequestClearInt() )
{
nai_msDelay( 10 );
}
}
/**************************************************************************************************************/
/**
<summary>
Function will print the RTD open latched status and idr id or vector to a file.
</summary>
*/
/**************************************************************************************************************/
void printInterruptInformationToFile( int32_t interruptID, uint32_t statusOpen, bool_t isEther, FILE* stream )
{
fprintf( stream, "Interrupt Information\n" );
fprintf( stream, "-----------------------------------\n" );
if (isEther)
fprintf( stream, "\nIDR ID = %#x \n", interruptID );
else
fprintf( stream, "\nVector = %#x \n", interruptID );
fprintf( stream, "Open Status = %#x \n", statusOpen );
}
/**************************************************************************************************************/
/**
<summary>
Function will print the RTD open latched status and idr id or vector.
</summary>
*/
/**************************************************************************************************************/
void printInterruptInformation_RTD( int32_t interruptID, uint32_t statusOpen, bool_t isEther )
{
printf( "Interrupt Information\n" );
printf( "-----------------------------------\n" );
if (isEther)
printf( "\nIDR ID = %#x \n", interruptID );
else
printf( "\nVector = %#x \n", interruptID );
printf( "Open Status = %#x \n", statusOpen );
}
void ClearInterrupt_RTD()
{
uint32_t status;
if (inputInterruptConfig.bPromptForInterruptClear)
{
promptUserToClearInterrupt_RTD();
}
naibrd_RTD_GetStatusRaw( inputRTDConfig.cardIndex, inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, &status );
naibrd_RTD_ClearStatusRaw( inputRTDConfig.cardIndex, inputRTDConfig.module, NAI_RTD_STATUS_OPEN_LATCHED, status );
}
Full Source — nai_rtd_int_ether.c (SSK 1.x)
/* 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"
/* Common RTD Sample Program include files */
#include "nai_rtd_int_ether.h"
#include "nai_rtd_cfg.h"
/* naibrd include files */
#include "functions/naibrd_rtd.h"
#include "maps/nai_map_rtd.h"
#include "advanced/nai_ether_adv.h"
int32_t command_index_interrupt_status;
/* Extern Functions or Variables*/
extern IDRConfig inputIDRConfig;
extern FILE* fifoDataFile;
/**************************************************************************************************************/
/**
<summary>
Constructs the ethernet commands that are part of the IDR. Configures the IDR on the board.
</summary>
*/
/**************************************************************************************************************/
void setupRTDIDRConfiguration( RtdConfig inputRTDConfig, IDRConfig* inputIDRConfig, bool_t bGen4RtdIDRCommands )
{
int32_t cardIndex = inputIDRConfig->cardIndex;
uint16_t protocol = inputIDRConfig->protocol;
uint16_t port = inputIDRConfig->port;
uint8_t* ipAddress = inputIDRConfig->ipAddress;
uint8_t ipLength = inputIDRConfig->ipLength;
int32_t vector = NAI_RTD_INTERRUPT_VECTOR;
uint8_t *commands = inputIDRConfig->commands; /* Stores the ethernet commands that are going to be executed as part of the IDR */
uint16_t *cmdcount = &inputIDRConfig->cmdcount;
uint16_t *cmdlength = &inputIDRConfig->cmdlength;
check_status( naibrd_Ether_ClearIDRConfig( cardIndex, (uint16_t)DEF_ETHERNET_RTD_IDR_ID ) ); /* clear IDR config */
InitRTDRxIDRCommands( inputRTDConfig, inputIDRConfig, bGen4RtdIDRCommands );
check_status( naibrd_Ether_SetIDRConfig( cardIndex, (uint16_t)DEF_ETHERNET_RTD_IDR_ID, protocol, ipLength, ipAddress, port, vector, *cmdcount, *cmdlength, commands ) );
}
/**************************************************************************************************************/
/**
<summary>
This function configures the IDR (Interrupt Driven Response) commands when an RTD open interrupt occurs.
There are two Ethernet commands that will be processed by the board when an RTD open interrupt occurs.
</summary>
*/
/**************************************************************************************************************/
void InitRTDRxIDRCommands( RtdConfig inputRTDConfig, IDRConfig* inputIDRConfig, bool_t bGen4RtdIDRCommands )
{
nai_status_t status = NAI_SUCCESS;
uint16_t msgIndex = 0;
uint32_t boardAddress;
uint32_t moduleOffset;
boardAddress = 0;
status = check_status( naibrd_GetModuleOffset( inputRTDConfig.cardIndex, inputRTDConfig.module, &moduleOffset ) );
if ( status == NAI_SUCCESS )
status = check_status( naibrd_GetAddress( inputRTDConfig.cardIndex, &boardAddress ) );
if ( status == NAI_SUCCESS )
{
if (bGen4RtdIDRCommands)
{
MakeRTDRxReadRegsCommand( inputIDRConfig, boardAddress, moduleOffset, bGen4RtdIDRCommands, msgIndex );
msgIndex = inputIDRConfig->cmdlength;
}
}
}
/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet read reg command and stores it in the IDR Configuration. The read will be performed
on the module's open latched status register.
</summary>
*/
/**************************************************************************************************************/
void MakeRTDRxReadRegsCommand( IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex )
{
uint16_t msgIndexOpen = startIndex;
uint16_t seqno;
uint32_t count, stride;
uint32_t regaddrOpen;
if (bGen4Ether)
{
seqno = 0;
regaddrOpen = boardAddress + moduleOffset + NAI_RTD_GEN5_REG_OPEN_STATUS_LATCHED_ADD;
count = 1;
stride = 4;
msgIndexOpen = (uint16_t)nai_ether_MakeReadMessage( &inputIDRConfig->commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface, regaddrOpen, stride, count, NAI_REG32 );
inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndexOpen;
command_index_interrupt_status = inputIDRConfig->cmdcount;
inputIDRConfig->cmdcount++;
}
}
/**************************************************************************************************************/
/**
<summary>
This function constructs an ethernet write reg command and stores it in the IDR Configuration. The write will be performed
on the module's open latched status register. The purpose of this write is to clear the open latched status register and
re-arm the interrupts after one has occurred.
</summary>
*/
/**************************************************************************************************************/
void MakeRTDRxWriteRegsCommand( RtdConfig inputRTDConfig, IDRConfig* inputIDRConfig, uint32_t boardAddress, int32_t moduleOffset, bool_t bGen4Ether, uint16_t startIndex )
{
uint16_t msgIndexOpen = startIndex;
uint16_t seqno;
uint32_t count, stride;
uint32_t regaddrOpen;
uint32_t dataOpen = 0x1 << ( inputRTDConfig.channel-1 );
if (bGen4Ether)
{
seqno = 0;
regaddrOpen = moduleOffset + boardAddress + NAI_RTD_GEN5_REG_OPEN_STATUS_LATCHED_ADD;
count = 1;
stride = 4;
msgIndexOpen = (uint16_t)nai_ether_BeginWriteMessage( &inputIDRConfig->commands[startIndex], seqno, NAI_ETHER_GEN4, (nai_intf_t)inputIDRConfig->boardInterface, regaddrOpen, stride, count, NAI_REG32 );
if ( msgIndexOpen >= 0 )
{
msgIndexOpen = (uint16_t)nai_ether_WriteMessageData( &inputIDRConfig->commands[startIndex], msgIndexOpen, NAI_REG32, &dataOpen, NAI_REG32, count );
if ( msgIndexOpen >= 0 )
{
msgIndexOpen = (uint16_t)nai_ether_FinishMessage( &inputIDRConfig->commands[startIndex], msgIndexOpen, NAI_ETHER_GEN4 );
}
}
inputIDRConfig->cmdlength = inputIDRConfig->cmdlength + msgIndexOpen;
inputIDRConfig->cmdcount++;
}
}
/**************************************************************************************************************/
/**
<summary>
Handles interpreting the idr response msgs received for rtd data. displays the IDR ID and status. Expects
to be parsing a message for a SINGLE channel interrupt only.
</summary>
*/
/**************************************************************************************************************/
void HandleRTDEtherInterrupt( uint16_t msglen, uint8_t msg[], uint16_t tdr_idr_id )
{
static uint8_t status;
uint16_t seq;
nai_ether_typecode_t typeCode;
nai_ether_gen_t gen = NAI_ETHER_GEN4;
int32_t size;
int32_t commandIndex;
nai_ether_DecodeMessageHeader(msg, msglen, &seq, &typeCode, gen, &size);
commandIndex = ( seq & ( 0x0F << 6 ) ) >> 6;
switch (typeCode)
{
/* Write REG */
case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_WRITE_4:
break;
/* READ REG */
case NAI_ETHER_TYPECODE_RSP_COMMAND_COMPLETE_READ_4:
if ( command_index_interrupt_status == commandIndex )
status = msg[11];
break;
}
if ( commandIndex == inputIDRConfig.cmdcount - 1 ) /* Print once all commands have been executed */
{
printf( "\nInterrupt Occurred\n" );
printInterruptInformation_RTD( tdr_idr_id, status, TRUE );
printInterruptInformationToFile( tdr_idr_id, status, TRUE, fifoDataFile );
}
}