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

SD Interrupts

SD Interrupts Sample Application (SSK 1.x)

Overview

The SD Interrupts sample application demonstrates how to configure and handle hardware interrupts on Synchro/Resolver-to-Digital (SD) modules using the NAI Software Support Kit (SSK 1.x). The sample configures a signal loss interrupt on a user-selected channel, sets a voltage threshold below which the module reports signal loss, and monitors for that condition in a continuous loop. It supports two interrupt delivery modes controlled by a compile-time flag: ISR mode (hardware interrupt with an installed callback) and polling mode (software polling of latched status registers). Both modes use the same underlying module configuration.

This sample supports the following SD module types: SD1, SD2, SD3, SD4, SD5, and SDP.

SD modules can generate interrupts on several latched status conditions that indicate faults with the input signal or the module’s internal measurement circuitry:

  • NAI_SD_STATUS_SIGNAL_LATCHED — input signal level has dropped below the configured signal loss threshold.

  • NAI_SD_STATUS_BIT_LATCHED — Built-In Test has detected a hardware fault.

  • NAI_SD_STATUS_REF_LATCHED — reference signal has been lost.

  • NAI_SD_STATUS_PHASE_LATCHED — phase lock error detected between the input signal and the reference.

As shipped, the sample monitors only NAI_SD_STATUS_SIGNAL_LATCHED (signal loss) on a single channel. To monitor additional status types, duplicate the configuration sequence in Setup_SD_Interrupt() for each status type you want to track, assigning a unique interrupt vector to each one.

For basic SD channel configuration (mode selection, ratio programming, reference voltage), see the SD BasicOpsMenu sample application guide. For background on interrupt concepts — including edge vs. level triggering, interrupt vector numbering, and steering architecture — see the Interrupts API Guide.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with an SD module installed (SD1 through SD5 or SDP).

  • A synchro or resolver signal source connected to the channel under test.

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

  • To use ISR mode: compile with the RUN_ISR preprocessor macro defined.

How to Run

Launch the SD_Interrupts executable from your build output directory. On startup the application looks for a configuration file (default_SD_Interrupts.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, the application prompts you to select a channel, configures signal loss interrupt monitoring on that channel, and enters a continuous wait loop, printing each interrupt event as it is detected.

To select interrupt delivery mode, rebuild with or without the RUN_ISR preprocessor define:

  • RUN_ISR defined — the application installs a hardware ISR via naibrd_InstallISR(). The ISR fires when the configured status condition occurs, and the main loop processes the event.

  • RUN_ISR not defined (default) — the application polls the latched status register on each loop iteration using naibrd_SD_GetStatusRaw(). No ISR is installed.

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 SD. For details on board connection configuration, see the First Time Setup Guide.

The main() function follows the standard SSK 1.x startup flow:

  1. Call naiapp_RunBoardMenu() to load a saved configuration file or present the interactive board menu. The configuration file (default_SD_Interrupts.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 card index with naiapp_query_CardIndex().

  3. Query the user for module number with naiapp_query_ModuleNumber().

  4. Retrieve the module ID with naibrd_GetModuleID() to verify an SD module is installed at the selected slot.

  5. Retrieve the channel count with naibrd_SD_GetChannelCount() and call Run_SD_Interrupts() to begin interrupt configuration.

#if defined (__VXWORKS__)
int32_t SD_Interrupts(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int32_t numChannels;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  numChannels = naibrd_SD_GetChannelCount(moduleID);
                  Run_SD_Interrupts(cardIndex, module, moduleID, numChannels);
               }
            }
         }
         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;
}

After the board connection succeeds, Run_SD_Interrupts() validates that the selected module has at least one SD channel. If the channel count is zero, the module is not recognized as an SD type and the application prints an error:

void Run_SD_Interrupts(int32_t cardIndex, int32_t module, uint32_t ModuleID,
   int32_t MaxChannel)
{
   if (MaxChannel == 0)
   {
      printf(" *** Module selection not recognized as SD module. ***\n\n");
   }
   else
   {
      Cfg_SD_Interrupt_Channel(cardIndex, module, ModuleID, MaxChannel);
   }
}
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 an SD module. Use the board menu to verify which slots are populated.

  • "Module selection not recognized as SD module" — naibrd_SD_GetChannelCount() returned zero. The module at the selected slot is not an SD type. Select a different module number.

Program Structure

The SD Interrupts sample is contained in a single source file (SD_Interrupts.c). All configuration, ISR, polling, and event handling logic lives in one file.

Entry Point

main() (or SD_Interrupts() on VxWorks) handles the board connection and module selection loop described above, then calls Run_SD_Interrupts().

Channel Selection

After module validation, Cfg_SD_Interrupt_Channel() prompts the user to select a channel. The default channel is 1. The function then calls Setup_SD_Interrupt() to configure and monitor interrupts on the selected channel:

void Cfg_SD_Interrupt_Channel(int32_t cardIndex, int32_t module,
   uint32_t ModuleID, int32_t MaxChannel)
{
   int32_t chan, defaultchan = 1;

   defaultchan = DEF_SD_CHANNEL;
   naiapp_query_ChannelNumber(MaxChannel, defaultchan, &chan);

   Setup_SD_Interrupt(cardIndex, module, chan, ModuleID);
}

The menu system is a sample convenience — in your own code, pass the channel number directly to the configuration functions.

Global State

The application uses global variables to communicate between the ISR (or polling function) and the main processing loop:

uint32_t irqSDCount = 0;
static uint32_t receivedVector = 0;
static bool_t bReceivedInterrupt = FALSE;
  • irqSDCount — running count of interrupts received.

  • receivedVector — the interrupt vector reported by the most recent event.

  • bReceivedInterrupt — flag set by the ISR or polling function when an interrupt has been detected.

Constants

static const double SIGNAL_LOSS_THREHOLD = 8.0;
static const int32_t MAX_ATTEMPT = 10;
static const uint8_t BAD_STATUS = 1u;
static const int32_t DEF_SD_CHANNEL = 1;
#define SD_SIG_LOSS_INTERRUPT_VECTOR 0x30
  • SIGNAL_LOSS_THREHOLD — the voltage threshold (in volts) below which the module reports signal loss. Adjust this value to match your input signal range. For a 90 V line-to-line synchro signal, a typical threshold is 70% of peak (approximately 63 V). The sample ships with a lower value (8 V) for bench testing with reduced-amplitude signals.

  • MAX_ATTEMPT — maximum number of retries when clearing stale latched status during initialization.

  • BAD_STATUS — the status register value that indicates a fault is present.

  • SD_SIG_LOSS_INTERRUPT_VECTOR — the interrupt vector assigned to signal loss events (0x30). You can change this to any unique value that does not conflict with other modules on the board.

Interrupt Configuration

The Setup_SD_Interrupt() function performs the complete interrupt configuration sequence on a single channel. This section walks through each step.

Step 1: Set Channel Mode

Before configuring interrupts, set the channel’s operating mode. The sample configures synchro mode:

check_status(naibrd_SD_SetChanMode(cardIndex, module, channel, NAI_SD_SYNCHRO));

SD modules support both synchro (NAI_SD_SYNCHRO) and resolver (NAI_SD_RESOLVER) modes. Select the mode that matches your signal source. This setting affects how the module interprets the input signal but does not change the interrupt behavior. Consult your module’s manual for the full list of supported modes.

Step 2: Set Signal Loss Threshold

Configure the voltage threshold below which the module asserts the signal loss status:

check_status(naibrd_SD_SetSigLossThreshold(cardIndex, module, channel, SIGNAL_LOSS_THREHOLD));

When the input signal amplitude drops below this threshold, the module sets the NAI_SD_STATUS_SIGNAL_LATCHED status bit, which triggers the interrupt (once enabled). The threshold is specified in volts. Set this to an appropriate fraction of your expected signal amplitude — typically 70% of the nominal peak voltage. Consult your module’s manual for the valid threshold range.

Step 3: Set Interrupt Vector

Assign a vector value that identifies this interrupt source. The vector is passed to the ISR when the interrupt fires:

check_status(naibrd_SD_SetInterruptVector(cardIndex, module,
   NAI_SD_STATUS_SIGNAL_LATCHED, SD_SIG_LOSS_INTERRUPT_VECTOR));

The vector is set per status type, not per channel. If you monitor multiple status types (signal loss, BIT, reference loss, phase lock), assign a unique vector to each one so your ISR can distinguish them. The sample uses 0x30 for signal loss.

Step 4: Set Trigger Type (Edge/Level)

Configure whether the interrupt fires on a status transition (edge) or remains asserted while the condition is active (level):

check_status(naibrd_SD_SetEdgeLevelInterrupt(cardIndex, module, channel,
   NAI_SD_STATUS_SIGNAL_LATCHED, NAI_SD_EDGE_INTERRUPT));

The sample uses NAI_SD_EDGE_INTERRUPT, which fires once when the signal loss condition is first detected. This is appropriate for fault notification — you want to know when signal loss occurs, not be continuously interrupted while the signal remains absent. For conditions you need to track as long as they persist, consider level triggering instead. See the Interrupts API Guide for a detailed comparison of edge vs. level triggering.

Step 5: Set Interrupt Steering

Configure how the interrupt signal is routed to your application:

naibrd_SD_SetInterruptSteering(cardIndex, module,
   NAI_SD_STATUS_SIGNAL_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_0);

The sample steers interrupts to the on-board processor (NAIBRD_INT_STEERING_ON_BOARD_0). Modify the steering parameter to match your hardware configuration:

  • NAIBRD_INT_STEERING_ON_BOARD_0 — handled locally on the board’s processor.

  • NAIBRD_INT_STEERING_CPCI_APP — routed to the CompactPCI backplane host.

  • NAIBRD_INT_STEERING_PCIE_APP — routed to the PCIe host.

Steering is set per status type. All channels sharing the same status type use the same steering destination.

Step 6: Install ISR (ISR Mode Only)

When RUN_ISR is defined, the application installs a hardware ISR after configuring the interrupt parameters:

#if defined (RUN_ISR)
naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_ON_BOARD_0,
   (nai_isr_t)MySDIsr, NULL);
#endif

naibrd_InstallISR() registers the MySDIsr callback to handle hardware interrupts from the board. The NAIBRD_IRQ_ID_ON_BOARD_0 parameter matches the steering destination configured in the previous step. If you change the steering, update the IRQ ID accordingly.

Step 7: Clear Stale Latched Status

Before enabling interrupts, clear any latched status from a previous run to prevent a spurious interrupt on startup:

retryCnt = 0;
do
{
   check_status(naibrd_SD_ClearStatus(cardIndex, module, channel,
      NAI_SD_STATUS_SIGNAL_LATCHED));
   naibrd_Wait(1000);
   check_status(naibrd_SD_GetStatus(cardIndex, module, channel,
      NAI_SD_STATUS_SIGNAL_LATCHED, &SigLossStatus));
} while ((retryCnt < MAX_ATTEMPT) && (SigLossStatus == BAD_STATUS));

The function clears the status register, waits 1000 milliseconds, and then reads it back to confirm the status has cleared. If the status persists after MAX_ATTEMPT retries, the signal loss condition is currently active on the hardware (the input signal is below the threshold). In that case, the application prints an error and does not enable the interrupt — there is no point waiting for a signal loss interrupt when signal loss is already present.

Step 8: Enable the Interrupt

Once the latched status is confirmed clear, enable the interrupt:

check_status(naibrd_SD_SetInterruptEnable(cardIndex, module, channel,
   NAI_SD_STATUS_SIGNAL_LATCHED, TRUE));

After this call, the module will generate an interrupt (or set the latched status for polling) whenever the input signal drops below the configured threshold.

Important

Common Errors

  • NAI_ERROR_NOT_SUPPORTED — the selected module does not support the specified status type. Verify you are using an SD module (SD1-SD5 or SDP) and that the status type is valid for your module’s firmware revision.

  • "ERROR: SD Signal Loss Status is set" — the signal loss condition is currently active on the hardware. The input signal is below the configured threshold. Verify that a valid synchro or resolver signal is connected to the channel under test, and that the threshold is set appropriately for your signal level.

  • No interrupts fire after configuration — ensure you cleared any latched status from a previous run before enabling interrupts. Also verify that interrupt steering matches your hardware bus configuration.

  • Wrong threshold for your signal — the sample ships with a threshold of 8 V, which is suitable for low-voltage bench testing. For production use with 90 V line-to-line synchro signals, set the threshold to approximately 63 V (70% of 90 V). Consult your module’s manual for the valid threshold range.

ISR Mechanism

The sample supports two interrupt delivery modes, selected at compile time by the RUN_ISR preprocessor define.

ISR Mode (RUN_ISR Defined)

When RUN_ISR is defined, the MySDIsr callback fires each time the hardware generates an interrupt. The ISR is lightweight — it records the vector, determines which condition triggered the event, and signals the main loop:

void MySDIsr(void* param, uint32_t vector)
{
   irqSDCount++;

   receivedVector = vector;
   switch (vector)
   {
      case SD_SIG_LOSS_INTERRUPT_VECTOR:
         bReceivedInterrupt = TRUE;
         break;
      default:
         printf("Unknown Interrupt, Vector:0x%02X, SD irqCount:%d\n",
            vector, irqSDCount);
         break;
   }
}

The switch statement matches the received vector against the known signal loss vector (0x30). If the vector matches, it sets bReceivedInterrupt to signal the main loop. An unknown vector is logged to the console — this typically means another module on the board is generating interrupts with a conflicting vector value.

On VxWorks, the ISR signature differs slightly. The ISR must retrieve the vector manually and clear the interrupt at the hardware level:

#if defined (__VXWORKS__)
void MySDIsr(uint32_t nVector)
{
   irqSDCount++;
   unsigned int vector = nai_Onboard_GetInterruptVector();
   nai_Onboard_ClearInterrupt();
   /* ... same switch logic ... */
}
#endif

If you monitor additional status types (BIT, reference loss, phase lock), add a case for each vector value you assigned. This lets the ISR distinguish which condition triggered the interrupt.

Polling Mode (RUN_ISR Not Defined)

When RUN_ISR is not defined, no ISR is installed. Instead, the main loop calls checkForStatusChange() on each iteration to poll the latched status register:

static void checkForStatusChange(int cardIndex, int module)
{
   uint32_t SigLossStatus;
   check_status(naibrd_SD_GetStatusRaw(cardIndex, module,
      NAI_SD_STATUS_SIGNAL_LATCHED, &SigLossStatus));
   if (SigLossStatus != 0)
   {
      irqSDCount++;
      receivedVector = SD_SIG_LOSS_INTERRUPT_VECTOR;
      bReceivedInterrupt = TRUE;
   }
}

naibrd_SD_GetStatusRaw() reads the raw latched status register for all channels at once. If any bit is set (any channel has signal loss), the function sets the bReceivedInterrupt flag and populates the vector so the main loop can process the event using the same code path as ISR mode.

Polling mode is useful for development and debugging because it does not require ISR installation or specific bus interrupt routing. However, it introduces latency proportional to the polling interval. For production systems that require prompt interrupt response, use ISR mode.

Important

Common Errors

  • ISR never fires — verify that interrupt steering matches your hardware bus. The sample uses NAIBRD_INT_STEERING_ON_BOARD_0 (on-board processor). If you are running from a host over cPCI, change steering to NAIBRD_INT_STEERING_CPCI_APP.

  • Unexpected vector in ISR — the ISR received a vector that does not match SD_SIG_LOSS_INTERRUPT_VECTOR. This typically means another module on the same board is generating interrupts with a conflicting vector. Assign unique vectors per module and per status type.

  • Polling detects no events — the signal loss condition has not occurred. Disconnect or attenuate the synchro/resolver signal below the threshold to trigger the condition. Verify that the interrupt enable was set successfully.

Event Processing and Status Clearing

The main loop in Setup_SD_Interrupt() continuously checks the bReceivedInterrupt flag and processes events as they arrive:

while (bContinue)
{
#if !defined (RUN_ISR)
   checkForStatusChange(cardIndex, module);
#endif
   if (bReceivedInterrupt)
   {
      printf("SD Signal Loss Interrupt, Vector:0x%02X, SD irqCount:%d\n",
         receivedVector, irqSDCount);

      /* Read and display the raw latched status */
      check_status(naibrd_SD_GetStatusRaw(cardIndex, module,
         NAI_SD_STATUS_SIGNAL_LATCHED, &SigLossStatus));
      printf("Signal Loss Status = 0x%0X\n", SigLossStatus);

      /* Clear the latched status so the next interrupt can fire */
      check_status(naibrd_SD_ClearStatus(cardIndex, module, channel,
         NAI_SD_STATUS_SIGNAL_LATCHED));
      bReceivedInterrupt = FALSE;
   }
}

When an event is detected, the loop:

  1. Prints the interrupt vector and running count.

  2. Reads the raw latched status register with naibrd_SD_GetStatusRaw() to display which channels have signal loss.

  3. Clears the latched status with naibrd_SD_ClearStatus() on the configured channel.

  4. Resets the bReceivedInterrupt flag so the next event can be captured.

Clearing Latched Status

Subsequent interrupts will not fire until the previous latched status has been cleared. In your own application, you must call naibrd_SD_ClearStatus() after handling each interrupt. Failing to clear the latched status will prevent all subsequent interrupts of the same type from firing.

The raw status register (naibrd_SD_GetStatusRaw()) returns a bitmask where each bit corresponds to a channel. This lets you determine which specific channels have the fault condition active, even though the interrupt was configured on a single channel.

Important

Common Errors

  • Only one interrupt is ever received — you forgot to clear the latched status after handling the event. Call naibrd_SD_ClearStatus() after processing each interrupt.

  • Spurious interrupt on startup — latched status from a previous run was not cleared before enabling interrupts. Always clear status before calling naibrd_SD_SetInterruptEnable(). The sample demonstrates this with the retry loop in Setup_SD_Interrupt().

Troubleshooting Reference

The following table summarizes errors and symptoms covered in preceding sections along with additional diagnostics. Consult your module’s manual for hardware-specific diagnostic procedures.

Error / Symptom Possible Causes Suggested Resolution

No board found

Board not powered or not connected. Configuration file has wrong interface or address.

Verify physical connection and power. Delete the configuration file and re-run to enter settings from scratch.

Connection timeout

Network misconfiguration, firewall blocking traffic, or incorrect bus settings.

Confirm IP settings for Ethernet connections. Check PCI/PCIe bus enumeration for local connections.

Module not present at selected slot

The selected slot does not contain an SD module.

Use the board menu to list populated slots and select the correct module number.

"Module selection not recognized as SD module"

naibrd_SD_GetChannelCount() returned zero. The module at the selected slot is not an SD type.

Select a slot containing an SD1-SD5 or SDP module.

"ERROR: SD Signal Loss Status is set"

The input signal is currently below the signal loss threshold, or no signal is connected.

Connect a valid synchro or resolver signal. Verify the threshold voltage is appropriate for your signal level.

No interrupts fire

Interrupt steering does not match hardware bus. Interrupt enable not set. Signal loss condition has not occurred.

Verify steering matches your connection type (on-board, cPCI, PCIe). Confirm enable returned success. Disconnect or attenuate the signal to trigger signal loss.

Only one interrupt received

Latched status not cleared after handling.

Call naibrd_SD_ClearStatus() after processing each event.

Spurious interrupt on startup

Stale latched status from a previous run.

Clear all latched status before enabling interrupts. The sample’s retry loop in Setup_SD_Interrupt() demonstrates this.

Unexpected vector in ISR

Another module is generating interrupts with a conflicting vector value.

Assign unique vector values per module and per status type. Verify vector assignments across all modules on the board.

NAI_ERROR_NOT_SUPPORTED

Module does not support the specified status type, or firmware revision is too old.

Verify module type is SD1-SD5 or SDP. Check firmware revision against the module manual requirements.

Polling mode detects nothing

The monitored condition (signal loss) has not occurred on the hardware.

Disconnect or attenuate the synchro/resolver signal below the threshold. Verify the correct status type and threshold are configured.

Threshold too high or too low

Signal loss triggers immediately on startup, or never triggers when signal is removed.

Set the threshold to approximately 70% of your nominal signal amplitude. Consult your module’s manual for the valid range.

Full Source

Full Source — SD_Interrupts.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_sd.h"
#include "advanced/nai_ether_adv.h"

static const int8_t *CONFIG_FILE = (const int8_t *)"default_SD_Interrupts.txt";

/*static const double SIGNAL_LOSS_THREHOLD = 63.0;   70% of 90V*/
static const double SIGNAL_LOSS_THREHOLD = 8.0;  /* 70% of 90V*/

static const int32_t MAX_ATTEMPT = 10;
static const uint8_t  BAD_STATUS = 1u;

/* Function prototypes */
void Run_SD_Interrupts(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel);
void Cfg_SD_Interrupt_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel);
void Setup_SD_Interrupt(int32_t cardIndex, int32_t module, uint32_t channel, uint32_t ModuleID);
#if !defined (RUN_ISR)
static void checkForStatusChange(int cardIndex, int module);
#endif

#if defined (__VXWORKS__)
void MySDIsr(uint32_t nVector);
#else
void MySDIsr(void* param, uint32_t vector);
#endif
uint32_t irqSDCount = 0;
static uint32_t receivedVector = 0;
static bool_t bReceivedInterrupt = FALSE;

static const int32_t DEF_SD_CHANNEL = 1;

#define SD_SIG_LOSS_INTERRUPT_VECTOR        0x30

//#define RUN_ISR						/* Un-Comment to use ISR, else Poll */

/**************************************************************************************************************/
/**
<summary>
The purpose of the SD_Interrupts is to illustrate the methods to call in the naibrd library to perform configuration
and handle SD Interrupts.

The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd SD routines.
 - ClearDeviceCfg
 - QuerySystemCfg
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - SaveDeviceCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SD_Interrupts(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int32_t numChannels;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  numChannels = naibrd_SD_GetChannelCount(moduleID);
                  Run_SD_Interrupts(cardIndex, module, moduleID, numChannels);
               }
            }
         }

         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   printf("\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();

   return 0;
}

/**************************************************************************************************************/
/**
<summary>
Run_SD_Interrupts prompts the user for the card, module and channel to use for the application and calls
Cfg_SD_Interrupt_Channel if the card, module, channel is valid for as a discrete module.
</summary>
*/
/**************************************************************************************************************/
void Run_SD_Interrupts(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel)
{
   if (MaxChannel == 0)
   {
      printf(" *** Module selection not recognized as SD module. ***\n\n");
   }
   else
   {
      Cfg_SD_Interrupt_Channel(cardIndex, module, ModuleID, MaxChannel);
   }
}

/**************************************************************************************************************/
/**
<summary>
Cfg_SD_Interrupt_Channel querying the user for the channel to generate and handle SD interrupts.
</summary>
*/
/**************************************************************************************************************/
void Cfg_SD_Interrupt_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel)
{

   int32_t chan, defaultchan = 1;

   printf("\nSD Signal Loss Interrupt Test for high voltage 90VLL module:");
   printf("\nThe signal loss threshold voltage is set to 70%%(63V) of the input SD signal.");
   printf("\nEnsure a validated SD signal is applied to the device under test(DUT). ");
   printf("    \r\n\r\n");
   printf("Channel selection \r\n");
   printf("================= \r\n");
   defaultchan = DEF_SD_CHANNEL;
   naiapp_query_ChannelNumber(MaxChannel, defaultchan, &chan);

   Setup_SD_Interrupt(cardIndex, module, chan, ModuleID);
#if Debug
   printf("\nType %c to quit : ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {

   }
   else
      bContinue = FALSE;
#endif
}

void Setup_SD_Interrupt(int32_t cardIndex, int32_t module, uint32_t channel, uint32_t ModuleID)
{
   bool_t bContinue = TRUE;
   bool_t bQuit = FALSE;

   uint32_t SigLossStatus;
   int32_t retryCnt = 0;

   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nIn Setup_SD_Interrupt, card:%d, module:%d, channel:%d, mid:%x", cardIndex, module, channel, ModuleID);

   /*set up SD mode: SYN*/
   printf("\nSetup Syn mode");
   check_status(naibrd_SD_SetChanMode(cardIndex, module, channel, NAI_SD_SYNCHRO));
   /*set up SD signal loss threshold*/
   printf("\nSetup Signal Threshold");
   check_status(naibrd_SD_SetSigLossThreshold(cardIndex, module, channel, SIGNAL_LOSS_THREHOLD));
   /*set up SD signal loss interrupt vector*/
   printf("\nSetup Interrupt Vector");
   check_status(naibrd_SD_SetInterruptVector(cardIndex, module, NAI_SD_STATUS_SIGNAL_LATCHED, SD_SIG_LOSS_INTERRUPT_VECTOR));
   /* Set the Interrupt Type (Edge/Level) */
   printf("\nSetup Interrupt Edge/Level");
   check_status(naibrd_SD_SetEdgeLevelInterrupt(cardIndex, module, channel, NAI_SD_STATUS_SIGNAL_LATCHED, NAI_SD_EDGE_INTERRUPT));
   /* Set the Interrupt Steering */
   printf("\nSetup Interrupt Steering");
   naibrd_SD_SetInterruptSteering(cardIndex, module, NAI_SD_STATUS_SIGNAL_LATCHED, NAIBRD_INT_STEERING_ON_BOARD_0);
#if defined (RUN_ISR)
   /* Install the ISR */
   printf("\nSetup Interrupt ISR");
   naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_ON_BOARD_0, (nai_isr_t)MySDIsr, NULL);
#endif
   /*clear any latch signal loss interrupt by writing to the signal loss status register */
   retryCnt = 0;
   do
   {
      printf("\nSetup Read Signal Loss Status");
      check_status(naibrd_SD_ClearStatus(cardIndex, module, channel, NAI_SD_STATUS_SIGNAL_LATCHED));
      naibrd_Wait(1000);
      check_status(naibrd_SD_GetStatus(cardIndex, module, channel, NAI_SD_STATUS_SIGNAL_LATCHED, &SigLossStatus));
   } while ((retryCnt < MAX_ATTEMPT) && (SigLossStatus == BAD_STATUS));

   printf("\nSetup Signal Loss Status cleared");
   if (SigLossStatus == BAD_STATUS)
   {
      printf("\nERROR: SD Signal Loss Status is set\n");
   }
   else
   {
      /* Enable BIT Interrupts */
      check_status(naibrd_SD_SetInterruptEnable(cardIndex, module, channel, NAI_SD_STATUS_SIGNAL_LATCHED, TRUE));

      printf("\n*** Waiting for Signal Loss Interrupt***\n");
      while (bContinue)
      {
#if !defined (RUN_ISR)
         checkForStatusChange(cardIndex, module);
#endif
         if (bReceivedInterrupt)
         {
            printf("SD Signal Loss Interrupt, Vector:0x%02X, SD irqCount:%d\n", receivedVector, irqSDCount);
            /*Show Status*/
            check_status(naibrd_SD_GetStatusRaw(cardIndex, module, NAI_SD_STATUS_SIGNAL_LATCHED, &SigLossStatus));
            printf("Signal Loss Status = 0x%0X\n", SigLossStatus);
            /*Clear Signal Loss*/
            check_status(naibrd_SD_ClearStatus(cardIndex, module, channel, NAI_SD_STATUS_SIGNAL_LATCHED));
            bReceivedInterrupt = FALSE;

            printf("\nType %c to quit. Enter to Continue.", NAI_QUIT_CHAR);
            bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
            printf("\n*** Waiting for Signal Loss Interrupt***\n");
            if (bQuit)
               bContinue = FALSE;
         }
      }
   }
}

#if defined (RUN_ISR)
/*****************************/
/* Interrupt Service Routine */
/*****************************/
#if defined (__VXWORKS__)
void MySDIsr(uint32_t nVector)
#else
void MySDIsr(void* param, uint32_t vector)
#endif
{
   irqSDCount++;

#if defined (__VXWORKS__)
   /* Get the vector that caused the interrupt */
   unsigned int vector = nai_Onboard_GetInterruptVector();
   /* Clear Interrupt */
   nai_Onboard_ClearInterrupt();
#endif

   /* Determine what interrupt was received */
   receivedVector = vector;
   switch (vector)
   {
      case SD_SIG_LOSS_INTERRUPT_VECTOR:
         bReceivedInterrupt = TRUE;
         break;
      default:
         printf("Unknown Interrupt, Vector:0x%02X, SD irqCount:%d\n", vector, irqSDCount);
         break;
   }
}
#else
static void checkForStatusChange(int cardIndex, int module)
{
   uint32_t SigLossStatus;
   check_status(naibrd_SD_GetStatusRaw(cardIndex, module, NAI_SD_STATUS_SIGNAL_LATCHED, &SigLossStatus));
   if (SigLossStatus != 0)
   {
      irqSDCount++;
      receivedVector = SD_SIG_LOSS_INTERRUPT_VECTOR;
      bReceivedInterrupt = TRUE;
   }
}
#endif

Help Bot

X