SD Interrupts
Edit this on GitLab
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_ISRpreprocessor 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_ISRdefined — the application installs a hardware ISR vianaibrd_InstallISR(). The ISR fires when the configured status condition occurs, and the main loop processes the event. -
RUN_ISRnot defined (default) — the application polls the latched status register on each loop iteration usingnaibrd_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:
-
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. -
Query the user for card index with
naiapp_query_CardIndex(). -
Query the user for module number with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleID()to verify an SD module is installed at the selected slot. -
Retrieve the channel count with
naibrd_SD_GetChannelCount()and callRun_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:
|
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
|
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
|
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:
-
Prints the interrupt vector and running count.
-
Reads the raw latched status register with
naibrd_SD_GetStatusRaw()to display which channels have signal loss. -
Clears the latched status with
naibrd_SD_ClearStatus()on the configured channel. -
Resets the
bReceivedInterruptflag 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
|
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" |
|
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 |
Spurious interrupt on startup |
Stale latched status from a previous run. |
Clear all latched status before enabling interrupts. The sample’s retry loop in |
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. |
|
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