Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

DT BasicInterrupt

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:

  1. 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.

  2. Query the user for a card index with naiapp_query_CardIndex().

  3. Query for a module slot with naiapp_query_ModuleNumber().

  4. 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 uses naibrd_GetModuleID()).

  • Boolean constants are NAI_TRUE / NAI_FALSE (SSK 1.x uses TRUE / FALSE).

  • Console output uses naiif_printf() from the platform abstraction layer (SSK 1.x uses printf() directly).

Important

Common connection errors you may encounter at this stage:

  • No board found — verify that the board is powered on and physically connected. Check that the configuration file lists the correct interface and address.

  • Connection timeout — confirm network settings (for Ethernet connections) or bus configuration (for PCI/PCIe). Firewalls and IP mismatches are frequent causes.

  • Invalid card or module index — indices are zero-based for cards and one-based for modules. Ensure the values you pass match your hardware setup.

  • Module not present at selected slot — the slot you selected does not contain a DT module. Use the board menu to verify which slots are populated.

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:

  1. 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.

  2. Enter a loop that queries for card index and module slot.

  3. Validate the detected module by calling naibrd_GetModuleName() and checking the returned ID. If the ID is zero, no valid module was found.

  4. Call Run_DT_BasicInterrupt() to verify DT channel support and enter the command loop.

  5. 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. Use NAIBRD_INT_STEERING_PCIE for 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 uses 0xB0. 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(), and naibrd_DT_SetIrqManipulate().

  • SSK 2.x consolidates this into: naibrd_ConnectISR() (once per card) followed by naibrd_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

  • NAI_ERROR_NOT_SUPPORTED — the platform does not support hardware interrupts, or interrupt support was not enabled in the board configuration. Verify you are running on Petalinux or VxWorks with interrupt support compiled in.

  • Interrupt configured but never fires — all five steps must be completed in order. A missing trigger type, steering, vector, or enable call will silently prevent delivery. Also verify that the status condition you are monitoring is actually occurring on the hardware.

  • Wrong vector received in ISR — verify that the vector assigned with naibrd_DT_SetChanMappedInterruptVector() matches the value your ISR is checking. If you monitor multiple status types, assign a unique vector to each.

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() from logLib.h. This is a VxWorks-specific deferred logging function that queues the message for output rather than printing directly from interrupt context. The logMsg() 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 to logMsg().

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

  • Interrupts still firing after disconnect — naibrd_DisconnectISR() unregisters the callback but does not disable the individual interrupt enables on the module. If you reconnect an ISR later without reconfiguring, previously enabled interrupts will resume immediately.

  • Calling disconnect without prior connect — if naibrd_ConnectISR() was never called (or returned NAI_ERROR_NOT_SUPPORTED), calling naibrd_DisconnectISR() is harmless but has no effect.

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

  • Interrupt fires once but never again — the latched status was not cleared after the first interrupt. Call naibrd_DT_ClearChanMappedStatus() for the relevant status type to re-arm the interrupt.

  • Status shows 1 but no interrupt received — the interrupt may not be configured for this status type. Verify that trigger type, steering, vector, and enable are all set for the status type you are monitoring.

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

  • BIT status remains latched after un-force — the force/un-force sequence changes the I/O direction and output state but does not clear latched status. Use the CLEAR command (or call naibrd_DT_ClearChanMappedStatus()) to reset the BIT latch after un-forcing.

  • Channel still driving output after test — if the application exits or crashes between force and un-force, the channel remains in output mode. Always un-force before exiting your application. In production code, consider registering a cleanup handler.

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 default_DT_BasicInterrupt.txt 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 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)

NAI_ERROR_NOT_SUPPORTED from naibrd_ConnectISR()

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 naibrd_DT_ClearChanMappedStatus() to clear the latch and re-arm the interrupt

Wrong vector received in ISR

Vector mismatch between configuration and ISR logic

Verify the vector passed to naibrd_DT_SetChanMappedInterruptVector() matches the value your ISR expects

BIT status remains set after un-force

Force/un-force changes I/O state but does not clear latched status

Use the CLEAR command or call naibrd_DT_ClearChanMappedStatus() to reset the BIT latch

Channel stuck in output mode

Application exited between force and un-force

Manually un-force by calling naibrd_DT_SetOutputState() with NAIBRD_DT_STATE_LO then naibrd_DT_SetIOFormat() with NAIBRD_DT_IOFORMAT_INPUT

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
}

Help Bot

X