DT BasicInterrupt
Edit this on GitLab
DT BasicInterrupt Sample Application (SSK 2.x)
Overview
The DT BasicInterrupt sample application demonstrates how to configure and handle hardware interrupts on discrete (DT) I/O modules using the NAI Software Support Kit (SSK 2.x). It covers the complete interrupt lifecycle: connecting an ISR callback, configuring trigger type, steering, and vector, enabling per-channel interrupts, reading and clearing latched status, and disconnecting the ISR when finished. The sample also includes a built-in technique for forcing a BIT error to trigger an interrupt without external wiring changes.
This sample supports the following DT module types: DT1 through DT5. It also works with combination modules that include DT functionality. It serves as a practical API reference — each menu command maps directly to one or more naibrd_DT_*() API calls that you can lift into your own code.
For background on interrupt concepts — including edge vs. level triggering, interrupt vector numbering, steering architecture, and latency measurement — see the Interrupts API Guide. This guide focuses on how those concepts apply specifically to DT modules and walks through the practical implementation using the SSK 2.x API.
For the SSK 1.x version, see DT Interrupts (SSK 1.x).
|
Note
|
This sample is not available on DEOS. The interrupt callback mechanism requires POSIX thread support, which DEOS does not provide. Consult the SSK 2.x Software Development Guide for platform-specific build configuration. |
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with a DT module installed (DT1-DT5, or a combination module with DT functionality).
-
SSK 2.x installed on your development host.
-
The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.
-
A platform that supports hardware interrupts (Petalinux or VxWorks).
How to Run
Launch the dt_basic_interrupt executable from your build output directory. On startup the application looks for a configuration file (default_DT_BasicInterrupt.txt). 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, select a channel and use the command menu to configure interrupts, display status, and force test conditions.
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 DT. |
The main() function follows a standard SSK 2.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_DT_BasicInterrupt.txt) 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. -
Query the user for a card index with
naiapp_query_CardIndex(). -
Query for a module slot with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleName()so downstream code can verify the selected slot contains a DT module.
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t DT_BasicInterrupt(void)
#else
int32_t main(void)
#endif
{
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
bool_t stop = NAI_FALSE;
uint32_t moduleID;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == (bool_t)NAI_TRUE)
{
while (stop != NAI_TRUE)
{
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(),
DEF_DT_CARD_INDEX, &cardIndex);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
stop = naiapp_query_ModuleNumber(moduleCnt, DEF_DT_MODULE, &module);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
if (moduleID != 0)
{
Run_DT_BasicInterrupt(cardIndex, module, moduleID);
}
}
}
}
}
naiapp_access_CloseAllOpenCards();
return 0;
}
Note the SSK 2.x differences from SSK 1.x in this startup sequence:
-
The VxWorks preprocessor guard uses
NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS(SSK 1.x uses__VXWORKS__). -
The module identifier is retrieved with
naibrd_GetModuleName()(SSK 1.x usesnaibrd_GetModuleID()). -
Boolean constants are
NAI_TRUE/NAI_FALSE(SSK 1.x usesTRUE/FALSE). -
Console output uses
naiif_printf()from the platform abstraction layer (SSK 1.x usesprintf()directly).
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
Entry Point
On standard platforms (Petalinux) the entry point is main(). On VxWorks the entry point is DT_BasicInterrupt() — the SSK 2.x build system selects the correct variant via a preprocessor guard:
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t DT_BasicInterrupt(void)
#else
int32_t main(void)
#endif
The startup flow is the same in both cases:
-
Attempt to load the saved configuration file via
naiapp_RunBoardMenu(DEF_CONFIG_FILE). If the file does not yet exist, the interactive board menu is presented instead. -
Enter a loop that queries for card index and module slot.
-
Validate the detected module by calling
naibrd_GetModuleName()and checking the returned ID. If the ID is zero, no valid module was found. -
Call
Run_DT_BasicInterrupt()to verify DT channel support and enter the command loop. -
On exit, close all open board connections with
naiapp_access_CloseAllOpenCards().
Module Validation
Before entering the command loop, Run_DT_BasicInterrupt() calls naibrd_DT_GetChannelCount() with the module ID to confirm the selected slot contains a DT-capable module. If the channel count is zero, the function prints an error and returns:
maxchannel = naibrd_DT_GetChannelCount(modid);
if (maxchannel == 0)
{
naiif_printf(" *** Module selection not recognized as DT module. ***\r\n\r\n");
}
else
{
Cfg_DT_Channel(cardIndex, module, maxchannel);
}
Application Parameters
The Cfg_DT_Channel() function populates an naiapp_AppParameters_t struct that is passed to every command handler. Your application will need to track these same values to identify which board, module, and channel you are targeting:
naiapp_AppParameters_t dtparams;
p_naiapp_AppParameters_t dtParams = &dtparams;
dtParams->cardIndex = cardIndex;
dtParams->module = module;
dtParams->channel = chan;
-
cardIndex— identifies which board in a multi-board system. -
module— the slot number where the DT module is installed. -
channel— the currently selected channel for interrupt configuration and status operations.
Command Loop
Cfg_DT_Channel() drives the interactive command loop. It first prompts for a channel number, then on each iteration it prints the command menu and dispatches the user’s selection to the matching handler function:
naiapp_utils_LoadParamMenuCommands(DT_BASIC_INTERRUPT_CMD_COUNT,
DT_BasicInterruptMenuCmds);
while (bContinue)
{
naiapp_display_ParamMenuCommands((int8_t *)"DT Basic Interrupt Menu");
naiif_printf("\r\nType DT command or %c to quit : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR,
inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt,
inputBuffer, &cmd);
if (bCmdFound)
{
DT_BasicInterruptMenuCmds[cmd].func(APP_PARAM_COUNT,
(int32_t*)dtParams);
}
}
}
else
{
bContinue = NAI_FALSE;
}
}
The available commands are registered in the DT_BasicInterruptMenuCmds[] table:
| Command | Description |
|---|---|
INT |
Configure interrupt (connect ISR, set trigger/steering/vector, enable) |
D |
Disconnect ISR |
STAT |
Display latched status for the selected channel |
CLEAR |
Clear all latched status for the selected channel |
F |
Force a BIT error (switch channel to output and drive HI) |
UF |
Un-force BIT error (drive LO and switch channel back to input) |
The menu-driven structure is a convenience of the sample application. In your own application, you would call the same underlying naibrd_DT_*() and naibrd_ConnectISR() API functions directly — for example, calling naibrd_DT_SetChanMappedInterruptEnable() instead of navigating to the "INT" menu command.
Interrupt Configuration
This section covers the core interrupt setup pattern in SSK 2.x. The Configure_DT_Interrupt() function performs all five steps required to receive a hardware interrupt: connecting the ISR callback, setting the trigger type, configuring steering, assigning a vector, and enabling the interrupt on a specific channel and status type.
Connecting the ISR Callback
The first step in any interrupt setup is to register your callback function with the board. Call naibrd_ConnectISR() once per card — it does not need to be called for each channel or interrupt type. The callback receives the interrupt vector as its only parameter, which your code uses to identify the source:
nai_status_t status;
status = naibrd_ConnectISR(cardIndex, SampleCallBack);
if (status == NAI_ERROR_NOT_SUPPORTED)
{
naiif_printf(
"\r\n**Interrupts are either not supported on this platform "
"or not enabled**\r\n");
}
If the current platform does not support hardware interrupts, naibrd_ConnectISR() returns NAI_ERROR_NOT_SUPPORTED. Your application should check this return value and handle the case gracefully.
Setting Trigger Type, Steering, and Vector
After the ISR is connected, configure the interrupt delivery parameters. Each of these calls targets a specific status type — the sample uses NAIBRD_DT_STATUS_BIT_LATCHED to trigger on BIT fault events:
uint32_t vector = 0xB0u;
/* Set edge triggering for BIT latched status */
check_status(naibrd_DT_SetChanMappedInterruptTriggerType(cardIndex, module, chan,
NAIBRD_DT_STATUS_BIT_LATCHED, NAIBRD_INT_TRIGGER_TYPE_EDGE));
/* Steer interrupts to PCIe */
check_status(naibrd_DT_SetChanMappedInterruptSteering(cardIndex, module,
NAIBRD_DT_STATUS_BIT_LATCHED, NAIBRD_INT_STEERING_PCIE));
/* Assign the interrupt vector */
check_status(naibrd_DT_SetChanMappedInterruptVector(cardIndex, module,
NAIBRD_DT_STATUS_BIT_LATCHED, vector));
/* Enable the interrupt on this channel */
check_status(naibrd_DT_SetChanMappedInterruptEnable(cardIndex, module, chan,
NAIBRD_DT_STATUS_BIT_LATCHED, NAI_TRUE));
-
naibrd_DT_SetChanMappedInterruptTriggerType()— selects edge or level triggering. Edge triggering (NAIBRD_INT_TRIGGER_TYPE_EDGE) fires once when the status transitions; level triggering fires continuously while the status is asserted. Edge triggering is the typical choice for latched status types. -
naibrd_DT_SetChanMappedInterruptSteering()— routes the interrupt to the appropriate bus. UseNAIBRD_INT_STEERING_PCIEfor PCIe-based boards. Other steering options include VME and CPCI, depending on your board’s backplane. Note that steering is set per module and status type, not per channel. -
naibrd_DT_SetChanMappedInterruptVector()— assigns a vector number that the ISR receives when the interrupt fires. Choose a unique vector for each interrupt source you need to distinguish. The sample uses0xB0. Vector assignment is per module and status type. -
naibrd_DT_SetChanMappedInterruptEnable()— enables (or disables) interrupt generation for the specified channel and status type. This is the per-channel enable gate — all other configuration must be in place before enabling.
This is the SSK 2.x "ChanMapped" interrupt pattern. Each API call targets a specific naibrd_dt_chan_mapped_status_type_t value, allowing you to configure different interrupt behavior for different status types on the same module. To monitor multiple status types (for example, BIT faults and overcurrent), repeat the trigger/steering/vector/enable sequence for each status type.
Key Difference from SSK 1.x
The SSK 2.x interrupt setup is significantly simpler than 1.x:
-
SSK 1.x requires a multi-step process:
naibrd_DT_SetIrqConfig(),naibrd_InstallISR(),naibrd_DT_SetInterruptSteering(),naibrd_DT_SetIntVector(), andnaibrd_DT_SetIrqManipulate(). -
SSK 2.x consolidates this into:
naibrd_ConnectISR()(once per card) followed bynaibrd_DT_SetChanMappedInterrupt*()calls for trigger type, steering, vector, and enable.
The 2.x API also introduces per-status-type configuration through the "ChanMapped" parameter, giving you finer-grained control over which status types generate interrupts and how they are delivered.
|
Important
|
Common Errors
|
ISR Callback
The ISR callback is the function that executes when a hardware interrupt fires. It receives the interrupt vector as its only parameter:
static void SampleCallBack(uint32_t vector)
{
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
logMsg("\r\n\r\nInterrupt Received!!! Vector:0x%X\r\n"
"Clear Status to receive new interrupt!!!\r\n",
vector, 0, 0, 0, 0, 0);
#else
naibsp_printf("\r\n\r\nInterrupt Received!!! Vector:0x%X\r\n"
"Clear Status to receive new interrupt!!!\r\n", vector);
#endif
}
Platform-Specific Behavior
The ISR callback contains a platform-specific code path for console output:
-
VxWorks — uses
logMsg()fromlogLib.h. This is a VxWorks-specific deferred logging function that queues the message for output rather than printing directly from interrupt context. ThelogMsg()call requires six variadic arguments even when unused (the trailing zeros). -
Petalinux — uses
naibsp_printf(), a BSP-level print function that is safe to call from interrupt context. It queues messages similarly tologMsg().
In both cases, printing from an ISR is done here for demonstration purposes only. In a production application, your ISR should do minimal work — typically setting a flag or posting to a semaphore — and defer processing to a task-level handler.
|
Note
|
The callback uses naibsp_printf() (BSP layer), not naiif_printf() (application layer). This is intentional — BSP-level print functions are designed for use in interrupt context where the full I/O abstraction layer may not be available.
|
Disconnecting the ISR
When you are finished receiving interrupts, call naibrd_DisconnectISR() to unregister the callback and release interrupt resources for the card:
naiif_printf("\r\nDisconnecting ISR...\r\n");
check_status(naibrd_DisconnectISR(cardIndex));
After disconnecting, no further interrupt callbacks will fire for any status type on the specified card. If you need to resume interrupt handling later, call naibrd_ConnectISR() again with your callback and re-enable the desired interrupts.
|
Important
|
Common Errors
|
Status Display and Clearing
The sample provides two commands for working with latched status: STAT to display the current status of all seven latched types, and CLEAR to reset them. After an interrupt fires on a latched status type, you must clear the latch before a new interrupt of the same type can occur.
Displaying Latched Status
To read the current latched status for a channel, call naibrd_DT_GetChanMappedStatus() with each latched status type. The sample reads all seven types and displays them in a table:
nai_status_bit_t statusBit;
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_MIN_LO_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_MID_RANGE_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_MAX_HI_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_LO_HI_TRANS_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_HI_LO_TRANS_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_BIT_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_OVERCURRENT_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
The seven latched status types and what they indicate:
-
NAIBRD_DT_STATUS_MIN_LO_LATCHED— the input fell below the minimum low threshold. -
NAIBRD_DT_STATUS_MID_RANGE_LATCHED— the input was in the mid-range region. -
NAIBRD_DT_STATUS_MAX_HI_LATCHED— the input exceeded the maximum high threshold. -
NAIBRD_DT_STATUS_LO_HI_TRANS_LATCHED— a low-to-high transition was detected. -
NAIBRD_DT_STATUS_HI_LO_TRANS_LATCHED— a high-to-low transition was detected. -
NAIBRD_DT_STATUS_BIT_LATCHED— a BIT (built-in test) fault was detected. -
NAIBRD_DT_STATUS_OVERCURRENT_LATCHED— an overcurrent condition was detected.
A returned value of 1 indicates the status has been latched (the condition occurred at some point since the last clear). A value of 0 means the condition has not occurred.
Clearing Latched Status
To clear latched status, the sample first reads each status type with naibrd_DT_GetChanMappedStatus(), then clears it with naibrd_DT_ClearChanMappedStatus() only if the status is currently set:
nai_status_t status;
nai_status_bit_t statusBit;
status = check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_BIT_LATCHED, &statusBit));
if (status == NAI_SUCCESS)
{
check_status(naibrd_DT_ClearChanMappedStatus(cardIndex, module, chan,
NAIBRD_DT_STATUS_BIT_LATCHED));
}
The sample repeats this read-then-clear pattern for all seven latched status types. In your own code, you can clear only the specific status types that are relevant to your application.
Clearing a latched status is essential for edge-triggered interrupts. Once a latched status asserts and triggers an interrupt, the latch remains set until explicitly cleared. No new interrupt of the same type will fire until the latch is cleared.
|
Important
|
Common Errors
|
Forcing and Un-forcing a BIT Error
The sample provides a built-in technique for triggering a BIT interrupt without requiring external wiring changes. This is useful for verifying that your interrupt configuration is working correctly.
Force BIT Error (F Command)
To force a BIT error, the sample temporarily reconfigures the channel as an output and drives it high. This creates a condition that the BIT logic detects as a fault:
/* Switch the channel to push-pull output mode */
check_status(naibrd_DT_SetIOFormat(cardIndex, module, chan,
NAIBRD_DT_IOFORMAT_OUTPUT_PUSHPULL));
/* Drive the output high to create a BIT fault condition */
check_status(naibrd_DT_SetOutputState(cardIndex, module, chan,
NAIBRD_DT_STATE_HI));
After executing this command, if the interrupt is configured for NAIBRD_DT_STATUS_BIT_LATCHED, the ISR callback should fire with the assigned vector.
Un-force BIT Error (UF Command)
To restore normal operation after forcing a BIT error, the sample drives the output low and switches the channel back to input mode:
/* Drive the output low first */
check_status(naibrd_DT_SetOutputState(cardIndex, module, chan,
NAIBRD_DT_STATE_LO));
/* Switch back to input mode */
check_status(naibrd_DT_SetIOFormat(cardIndex, module, chan,
NAIBRD_DT_IOFORMAT_INPUT));
Note the order: drive the output low before switching to input mode. This ensures the pin is in a clean state when it returns to input configuration.
|
Important
|
Common Errors
|
Troubleshooting Reference
This table summarizes common errors and symptoms covered in the sections above. For detailed context on each entry, refer to the relevant section. Consult your module’s manual (DT1 Manual) for hardware-specific 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 |
Module not detected at selected slot |
No module installed at the specified slot, incorrect module number entered |
Verify hardware configuration and module slot assignment |
Module not recognized as DT |
Selected slot contains a non-DT module, or module ID not in the supported list |
Verify the slot contains a DT module (DT1-DT5 or a combination module with DT functionality) |
|
Platform does not support hardware interrupts, or interrupt support not enabled |
Verify you are running on Petalinux or VxWorks with interrupt support compiled in. This sample is not available on DEOS. |
Interrupt configured but never fires |
Missing a configuration step (trigger, steering, vector, or enable), or the hardware condition has not occurred |
Verify all five steps are complete. Use the Force BIT command to generate a test interrupt. |
Interrupt fires once but never again |
Latched status not cleared after interrupt |
Call |
Wrong vector received in ISR |
Vector mismatch between configuration and ISR logic |
Verify the vector passed to |
BIT status remains set after un-force |
Force/un-force changes I/O state but does not clear latched status |
Use the |
Channel stuck in output mode |
Application exited between force and un-force |
Manually un-force by calling |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — dt_basic_interrupt.c (SSK 2.x)
/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"
/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_dt.h"
/* naiif include files */
#include "nai_libs/naiif/include/naiif_stdio.h"
/* Common Sample Program include files */
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_menu.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_query.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_access.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_display.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_utils.h"
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
#include "logLib.h"
#endif
static const int8_t *DEF_CONFIG_FILE = (const int8_t *)"default_DT_BasicInterrupt.txt";
/* Function prototypes */
static int32_t Run_DT_BasicInterrupt(int32_t cardIndex, int32_t module, uint32_t modid);
static void Cfg_DT_Channel(int32_t cardIndex, int32_t module, int32_t MaxChannel);
static void Verify_DT_ParamCnt(int32_t paramCnt);
static nai_status_t Display_DT_Status(int32_t paramCnt, int32_t* p_params);
static nai_status_t Clear_DT_Status(int32_t paramCnt, int32_t* p_params);
static nai_status_t Configure_DT_Interrupt(int32_t paramCnt, int32_t* p_params);
static nai_status_t Disconnect_DT_Interrupt(int32_t paramCnt, int32_t* p_params);
static void SampleCallBack(uint32_t vector);
static nai_status_t ForceBIT(int32_t paramCnt, int32_t* p_params);
static nai_status_t UnForceBIT(int32_t paramCnt, int32_t* p_params);
static const int32_t DEF_DT_CARD_INDEX = 0;
static const int32_t DEF_DT_MODULE = 1;
static const int32_t DEF_DT_CHANNEL = 1;
/****** Command Table *******/
enum dt_basic_interrupt_commands
{
DT_BASIC_INTERRUPT_CMD_CONFIGURE,
DT_BASIC_INTERRUPT_CMD_DISCONNECT,
DT_BASIC_INTERRUPT_CMD_STATUS_READ,
DT_BASIC_INTERRUPT_CMD_STATUS_CLEAR,
DT_BASIC_INTERRUPT_CMD_FORCE_BIT,
DT_BASIC_INTERRUPT_CMD_UNFORCE_BIT,
DT_BASIC_INTERRUPT_CMD_COUNT
};
/****** Command Tables *******/
static naiapp_cmdtbl_params_t DT_BasicInterruptMenuCmds[] = {
{"INT", "DT Configure Interrupt", DT_BASIC_INTERRUPT_CMD_CONFIGURE, Configure_DT_Interrupt},
{"D", "DT De-init ISR", DT_BASIC_INTERRUPT_CMD_DISCONNECT, Disconnect_DT_Interrupt},
{"STAT", "DT Display Status", DT_BASIC_INTERRUPT_CMD_STATUS_READ, Display_DT_Status},
{"F", "Force BIT Error", DT_BASIC_INTERRUPT_CMD_FORCE_BIT, ForceBIT},
{"UF", "Un-force BIT Error", DT_BASIC_INTERRUPT_CMD_UNFORCE_BIT, UnForceBIT},
{"CLEAR", "DT Clear Status", DT_BASIC_INTERRUPT_CMD_STATUS_CLEAR, Clear_DT_Status},
};
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t DT_BasicInterrupt(void)
#else
int32_t main(void)
#endif
{
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
bool_t stop = NAI_FALSE;
uint32_t moduleID;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == (bool_t)NAI_TRUE)
{
while (stop != NAI_TRUE)
{
/* Select Card Index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), DEF_DT_CARD_INDEX, &cardIndex);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Select Module */
stop = naiapp_query_ModuleNumber(moduleCnt, DEF_DT_MODULE, &module);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
if ((moduleID != 0))
{
Run_DT_BasicInterrupt(cardIndex, module, moduleID);
naiif_printf("\r\nType Q to quit or Enter to continue:\r\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
}
}
}
naiif_printf("\r\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
static void Verify_DT_ParamCnt(int32_t paramCnt)
{
if (paramCnt != APP_PARAM_COUNT)
{
naiif_printf(" *** Parameter count specified is incorrect!!! ***\r\n");
}
}
static int32_t Run_DT_BasicInterrupt(int32_t cardIndex, int32_t module, uint32_t modid)
{
bool_t bQuit = NAI_FALSE;
int32_t maxchannel;
if (!bQuit)
{
maxchannel = naibrd_DT_GetChannelCount(modid);
if (maxchannel == 0)
{
naiif_printf(" *** Module selection not recognized as DT module. ***\r\n\r\n");
}
else
{
Cfg_DT_Channel(cardIndex, module, maxchannel);
}
}
return cardIndex;
}
static void Cfg_DT_Channel(int32_t cardIndex, int32_t module, int32_t MaxChannel)
{
bool_t bQuit = NAI_FALSE;
bool_t bContinue = NAI_TRUE;
bool_t bCmdFound = NAI_FALSE;
int32_t chan, defaultchan = 1;
int32_t cmd;
naiapp_AppParameters_t dtparams;
p_naiapp_AppParameters_t dtParams = &dtparams;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
while (bContinue)
{
naiif_printf("\r\n\r\n");
naiif_printf("Channel selection\r\n");
naiif_printf("=================\r\n");
defaultchan = DEF_DT_CHANNEL;
bQuit = naiapp_query_ChannelNumber(MaxChannel, defaultchan, &chan);
dtParams->cardIndex = cardIndex;
dtParams->module = module;
dtParams->channel = chan;
naiapp_utils_LoadParamMenuCommands(DT_BASIC_INTERRUPT_CMD_COUNT, DT_BasicInterruptMenuCmds);
while (bContinue)
{
naiapp_display_ParamMenuCommands((int8_t *)"DT Basic Interrupt Menu");
naiif_printf("\r\nType DT command or %c to quit : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
if (bCmdFound)
{
switch (cmd)
{
case DT_BASIC_INTERRUPT_CMD_CONFIGURE:
case DT_BASIC_INTERRUPT_CMD_DISCONNECT:
case DT_BASIC_INTERRUPT_CMD_STATUS_READ:
case DT_BASIC_INTERRUPT_CMD_STATUS_CLEAR:
case DT_BASIC_INTERRUPT_CMD_FORCE_BIT:
case DT_BASIC_INTERRUPT_CMD_UNFORCE_BIT:
DT_BasicInterruptMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)dtParams);
break;
default:
naiif_printf("Invalid command entered\r\n");
break;
}
}
else
{
naiif_printf("Invalid command entered\r\n");
}
}
}
else
{
bContinue = NAI_FALSE;
}
}
}
}
static nai_status_t Display_DT_Status(int32_t paramCnt, int32_t* p_params)
{
p_naiapp_AppParameters_t dtParams = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = dtParams->cardIndex;
int32_t module = dtParams->module;
int32_t chan = dtParams->channel;
nai_status_bit_t statusBit;
Verify_DT_ParamCnt(paramCnt);
naiif_printf("\r\n");
naiif_printf(" -----------Latched Status Channel %d-------------------\r\n", chan);
naiif_printf(" MinLo MidRng MaxHi Low-Hi Hi-Lo BIT OC\r\n");
naiif_printf(" ------- -------- ------ ------- -------- ------ ------\r\n");
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MIN_LO_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MID_RANGE_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MAX_HI_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_LO_HI_TRANS_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_HI_LO_TRANS_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_BIT_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_OVERCURRENT_LATCHED, &statusBit));
naiif_printf(" %3i ", statusBit);
naiif_printf("\r\n\r\n");
return NAI_SUCCESS;
}
static nai_status_t ForceBIT(int32_t paramCnt, int32_t* p_params)
{
p_naiapp_AppParameters_t dtParams = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = dtParams->cardIndex;
int32_t module = dtParams->module;
int32_t chan = dtParams->channel;
check_status(naibrd_DT_SetIOFormat(cardIndex, module, chan, NAIBRD_DT_IOFORMAT_OUTPUT_PUSHPULL));
check_status(naibrd_DT_SetOutputState(cardIndex, module, chan, NAIBRD_DT_STATE_HI));
return NAI_SUCCESS;
}
static nai_status_t UnForceBIT(int32_t paramCnt, int32_t* p_params)
{
p_naiapp_AppParameters_t dtParams = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = dtParams->cardIndex;
int32_t module = dtParams->module;
int32_t chan = dtParams->channel;
check_status(naibrd_DT_SetOutputState(cardIndex, module, chan, NAIBRD_DT_STATE_LO));
check_status(naibrd_DT_SetIOFormat(cardIndex, module, chan, NAIBRD_DT_IOFORMAT_INPUT));
return NAI_SUCCESS;
}
static nai_status_t Clear_DT_Status(int32_t paramCnt, int32_t* p_params)
{
nai_status_t status = NAI_ERROR_NOT_SUPPORTED;
p_naiapp_AppParameters_t dtParams = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = dtParams->cardIndex;
int32_t module = dtParams->module;
int32_t chan = dtParams->channel;
nai_status_bit_t statusBit;
Verify_DT_ParamCnt(paramCnt);
status = check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MIN_LO_LATCHED, &statusBit));
if (status == NAI_SUCCESS)
{
check_status(naibrd_DT_ClearChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MIN_LO_LATCHED));
}
status = check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MID_RANGE_LATCHED, &statusBit));
if (status == NAI_SUCCESS)
{
check_status(naibrd_DT_ClearChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MID_RANGE_LATCHED));
}
status = check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MAX_HI_LATCHED, &statusBit));
if (status == NAI_SUCCESS)
{
check_status(naibrd_DT_ClearChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_MAX_HI_LATCHED));
}
status = check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_LO_HI_TRANS_LATCHED, &statusBit));
if (status == NAI_SUCCESS)
{
check_status(naibrd_DT_ClearChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_LO_HI_TRANS_LATCHED));
}
status = check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_HI_LO_TRANS_LATCHED, &statusBit));
if (status == NAI_SUCCESS)
{
check_status(naibrd_DT_ClearChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_HI_LO_TRANS_LATCHED));
}
status = check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_BIT_LATCHED, &statusBit));
if (status == NAI_SUCCESS)
{
check_status(naibrd_DT_ClearChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_BIT_LATCHED));
}
status = check_status(naibrd_DT_GetChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_OVERCURRENT_LATCHED, &statusBit));
if (status == NAI_SUCCESS)
{
check_status(naibrd_DT_ClearChanMappedStatus(cardIndex, module, chan, NAIBRD_DT_STATUS_OVERCURRENT_LATCHED));
}
if (status == NAI_SUCCESS)
{
naiif_printf("Cleared statuses for channel %d...\r\n", chan);
}
return status;
}
static nai_status_t Configure_DT_Interrupt(int32_t paramCnt, int32_t* p_params)
{
p_naiapp_AppParameters_t dtParams = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = dtParams->cardIndex;
int32_t module = dtParams->module;
int32_t chan = dtParams->channel;
uint32_t vector = 0xB0u;
nai_status_t status;
Verify_DT_ParamCnt(paramCnt);
/* Specify callback function for interrupt type */
status = naibrd_ConnectISR(cardIndex, SampleCallBack);
if (status == NAI_ERROR_NOT_SUPPORTED)
{
naiif_printf("\r\n**Interrupts are either not supported on this platform or not enabled**\r\n");
}
check_status(naibrd_DT_SetChanMappedInterruptTriggerType(cardIndex, module, chan, NAIBRD_DT_STATUS_BIT_LATCHED,
NAIBRD_INT_TRIGGER_TYPE_EDGE));
check_status(naibrd_DT_SetChanMappedInterruptSteering(cardIndex, module, NAIBRD_DT_STATUS_BIT_LATCHED,
NAIBRD_INT_STEERING_PCIE));
check_status(naibrd_DT_SetChanMappedInterruptVector(cardIndex, module, NAIBRD_DT_STATUS_BIT_LATCHED, vector));
check_status(naibrd_DT_SetChanMappedInterruptEnable(cardIndex, module, chan, NAIBRD_DT_STATUS_BIT_LATCHED, NAI_TRUE));
naiif_printf("\r\nInterrupt Configuration\r\n");
naiif_printf("=======================\r\n");
naiif_printf("Card Index:%d\r\n", cardIndex);
naiif_printf("Module Number:%d\r\n", module);
naiif_printf("Channel:%d\r\n", chan);
naiif_printf("Vector:0x%X\r\n", vector);
naiif_printf("Status:LO-HI Transition\r\n");
naiif_printf("\r\n Waiting for LO-HI Transition Latched interrupt on channel %d...\r\n", chan);
return NAI_SUCCESS;
}
static nai_status_t Disconnect_DT_Interrupt(int32_t paramCnt, int32_t* p_params)
{
p_naiapp_AppParameters_t dtParams = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = dtParams->cardIndex;
int32_t module = dtParams->module;
int32_t chan = dtParams->channel;
naiif_printf("\r\nDisconnecting ISR...\r\n");
check_status(naibrd_DisconnectISR(cardIndex));
return NAI_SUCCESS;
}
static void SampleCallBack(uint32_t vector)
{
/* Printing in an ISR is always a bad idea. For demonstration purposes only.
* logMsg & naibsp_printf are a little better since they queue up messages. */
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
logMsg("\r\n\r\nInterrupt Received!!! Vector:0x%X\r\nClear Status to receive new interrupt!!!\r\n",vector,0,0,0,0,0);
#else
naibsp_printf("\r\n\r\nInterrupt Received!!! Vector:0x%X\r\nClear Status to receive new interrupt!!!\r\n", vector);
#endif
}