M1553 RT Interrupt
Edit this on GitLab
M1553 RT Interrupt Sample Application (SSK 1.x)
Overview
The M1553 RT Interrupt sample application demonstrates how to configure a MIL-STD-1553 channel as a Remote Terminal (RT) with interrupt-driven message notification using the NAI Software Support Kit (SSK 1.x). Instead of continuously polling the RT stack for new messages, this sample configures the 1553 module to generate an End of Message (EOM) interrupt each time the RT completes a bus transaction. The application installs an interrupt service routine (ISR), and the main processing loop waits for the ISR to set a flag before reading and decoding messages from the RT stack.
The key interrupt API calls demonstrated are:
-
naibrd_1553_SetIrqConfig()— configures the interrupt mode (level-triggered) and auto-clear behavior. -
naibrd_InstallISR()— installs the application’s ISR on the board. -
naibrd_1553_SetInterruptSteering()— routes the interrupt to the correct processor or bus. -
naibrd_1553_SetIntVector()— assigns an interrupt vector to the 1553 channel. -
naibrd_1553_SetIrqManipulate()— enables or disables specific interrupt types (e.g., EOM).
This sample supports the following 1553 module types:
-
4-channel modules: FT0 through FT9 and FTA through FTF
-
2-channel 1760 modules: FTJ and FTK
-
Combination modules: CM1, CM5, and CM8
|
Note
|
This application requires a direct hardware connection (PCI/PCIe or onboard processor). Ethernet communication does not support interrupt delivery and will not work with this sample. |
For detailed register maps and module-specific behavior, refer to the FTA-FTF Manual and FTJ-FTK Manual.
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with a supported 1553 module installed, connected via PCI/PCIe or running on an onboard processor.
-
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.
How to Run
Launch the M1553_RT_Interrupt executable from your build output directory. On startup the application looks for a configuration file (default_1553_RTInterrupt.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 walks you through RT-specific settings (channel, RT address, subaddress, Rx buffer type) and then configures interrupts, sets up data blocks, and enters a timed monitoring loop that waits for interrupt-driven message notification.
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 1553. |
The main() function follows a standard SSK 1.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_1553_RTInterrupt.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear. -
Query the user for a card index with
naiapp_query_CardIndex(). -
Query for a module slot with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleID()so downstream code can adapt to the specific 1553 variant installed. -
If a valid module is found, call
Run_M1553_RT_Interrupt()to begin RT configuration and interrupt-driven message processing.
#if defined (__VXWORKS__)
int32_t M1553_RT_Interrupt(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
uint32_t moduleID = 0;
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))
{
Run_M1553_RT_Interrupt(cardIndex, module, moduleID);
}
}
}
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;
}
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
Entry Point
The program entry point is main() on most platforms or M1553_RT_Interrupt() on VxWorks. After the board connection and module selection described above, the application calls Run_M1553_RT_Interrupt(), which handles device setup, interrupt configuration, buffer setup, and the message processing loop.
Global Variables
The sample uses several global variables to communicate between the ISR and the main processing loop:
-
deviceNumber— stores the logical device number so the processing loop can reference it. -
irqFlag— a volatile flag set by the ISR to signal that an interrupt has been received. The processing loop polls this flag. -
irqCount— running count of interrupts received. -
receivedVector— the interrupt vector received by the ISR, used for diagnostic display. -
currDataBlock— tracks which Tx data block is currently active.
User Input Flow
Once inside Run_M1553_RT_Interrupt(), the application collects RT operating parameters through a series of utility functions:
-
Get1553RTCfg()— prompts for the 1553 channel number and RT address. The defaults are channel 3 and RT address 1. -
Get1553Address()— prompts for the subaddress to legalize for Tx and Rx traffic. Valid subaddresses are 1 through 31. The default is subaddress 2. -
Get1553LogicalDevNum()— prompts for a logical device number. The default is device 3. -
Get1553RTAddressSource()— asks whether to set the RT address in software or use the hardware address pins. -
Get1553RxBufferType()— prompts the user to select the Rx data block buffering mode: single buffer, double buffer, or circular buffer. Double buffering is the default.
|
Note
|
The menu system is a sample convenience — in your own code, call these API functions directly with your desired values. |
RT Address Configuration
The RT address can be set from two sources: software control or hardware address pins. The application calls Get1553RTAddressSource() to let the user choose, then executes the corresponding code path. Both paths write to auxiliary register 0x2 but with different bit masks.
Software Addressing
Set the RTAD_SW_EN and RT_ADR_LAT bits (value 0x0018) in auxiliary register 0x2 via naibrd_1553_WriteAuxReg(), then program the desired address with naibrd_1553_RtSetAddress(). This gives the application full control over the RT address.
Hardware Pin Addressing
Set only the RT_ADR_LAT bit (value 0x0008) in auxiliary register 0x2 via naibrd_1553_WriteAuxReg(). The RT address is read from the module’s external address pins. The application does not call naibrd_1553_RtSetAddress() in this mode.
Source Code
if (bSoftwareRTAddr)
{
/* Set RTAD_SW_EN and RT_ADR_LAT in software */
swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0018);
/* Set RT address */
swResult = naibrd_1553_RtSetAddress(DevNum, rtaddr);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtSetAddress %d", swResult);
return bQuit;
}
}
else
{
/* Unset RTAD_SW_EN and set RT_ADR_LAT in software */
swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0008);
}
For complete register bit definitions, refer to the FTA-FTF Manual.
|
Important
|
|
Interrupt Configuration
The interrupt setup in this sample involves five steps that must be completed before starting the RT. The order matters — configure the interrupt mode first, install the ISR, set the steering, assign the vector, and then clear any stale status before enabling interrupts.
Step 1: Configure Interrupt Mode
To configure the 1553 core’s interrupt behavior, call naibrd_1553_SetIrqConfig() with level-triggered mode and auto-clear:
swResult = naibrd_1553_SetIrqConfig(DevNum, NAI_1553_IRQ_MODE_LEVEL, NAI_1553_IRQ_AUTO_CLEAR);
NAI_1553_IRQ_MODE_LEVEL configures level-triggered interrupts (the interrupt line stays asserted until cleared). NAI_1553_IRQ_AUTO_CLEAR means that reading the interrupt status registers automatically clears them, which simplifies the ISR logic.
Step 2: Install the ISR
To install your interrupt service routine on the board, call naibrd_InstallISR():
swResult = naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_DONT_CARE, (nai_isr_t)myIsr, NULL);
NAIBRD_IRQ_ID_DONT_CARE lets the library select the appropriate IRQ ID automatically. For onboard processor applications, use NAIBRD_IRQ_ID_ON_BOARD_0 instead. The NULL parameter is a user context pointer passed to the ISR — this sample does not use it.
Step 3: Set Interrupt Steering
To route the interrupt to the correct destination, call naibrd_1553_SetInterruptSteering():
swResult = naibrd_1553_SetInterruptSteering(DevNum, NAIBRD_INT_STEERING_CPCI_APP);
The steering constant must match your hardware configuration:
-
NAIBRD_INT_STEERING_CPCI_APP— for cPCI backplane interrupt delivery. -
NAIBRD_INT_STEERING_PCIE_APP— for PCIe interrupt delivery (use with PPC1 onboard processor). -
NAIBRD_INT_STEERING_ON_BOARD_0— for onboard processor interrupt delivery (use with ARM1).
Using the wrong steering constant is a common source of "interrupts not firing" issues.
Step 4: Set Interrupt Vector
To assign a unique interrupt vector to this 1553 channel, call naibrd_1553_SetIntVector():
swResult = naibrd_1553_SetIntVector(DevNum, INTERRUPT_VECTOR_ADDEND + rtchan);
The vector is computed as 0xA0 + channel_number. This allows each channel on a multi-channel module to have a distinct vector, so the ISR can identify which channel generated the interrupt.
Step 5: Clear Stale Status
Before enabling interrupts, clear any stale interrupt status from previous operations:
/* Read core status registers to clear statuses */
swResult = naibrd_1553_GetIntStatus(DevNum, &status1, &status2);
/* Clear Interrupt Latch Bit */
swResult = naibrd_1553_ClearIntLatch(DevNum);
naibrd_1553_GetIntStatus() reads and clears the interrupt status registers (because auto-clear is enabled). naibrd_1553_ClearIntLatch() clears the module-level interrupt latch bit. Skipping this step can cause a spurious interrupt immediately after enabling.
|
Important
|
|
Buffer Types and Data Block Configuration
This section covers how the sample creates and maps data blocks for Rx and Tx traffic on the configured subaddress.
Rx Data Block Creation and Mapping
The sample creates a single Rx data block and maps it to the chosen subaddress with the EOM interrupt flag set:
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_RX, nDataBlockType, NULL, 0);
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_RX, sa,
NAI_1553_RT_MESSAGE_TYPE_RX, NAI_1553_RT_DATABLOCK_IRQ_END_OF_MESSAGE, 1);
The NAI_1553_RT_DATABLOCK_IRQ_END_OF_MESSAGE flag in the mapping call tells the hardware to generate an EOM interrupt whenever a message completes on this subaddress. The final argument (1) legalizes the subaddress.
Tx Data Block Creation and Mapping
The sample creates two single-type Tx data blocks and maps the first as the active Tx block:
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX1, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX2, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_TX1, sa,
NAI_1553_RT_MESSAGE_TYPE_TX, 0, 1);
currDataBlock = DATA_BLOCK_ID_TX1;
TX1 is mapped as the active block. The Tx mapping does not use the EOM interrupt flag (set to 0) because the interrupt is already configured on the Rx mapping for this subaddress. currDataBlock tracks which block is active for potential swap operations.
|
Important
|
|
Interrupt Service Routine
The ISR (myIsr) is called by the hardware when an interrupt fires. It performs minimal work to avoid blocking:
static void myIsr(void* param, uint32_t vector)
{
#if defined (WIN32)
UNREFERENCED_PARAMETER(param);
UNREFERENCED_PARAMETER(vector);
#endif
#if defined (__VXWORKS__)
vector = nai_Onboard_GetInterruptVector();
logMsg("\nvector = %d deviceNumber = %d\n", vector, deviceNumber, 2, 3, 4, 5);
nai_Onboard_ClearInterrupt();
#endif
receivedVector = vector;
/* Set the global interrupt flag */
irqFlag = 1;
irqCount++;
}
The ISR stores the received vector, sets the irqFlag global, and increments the interrupt counter. All message reading and decoding is deferred to the main processing loop. On VxWorks, the ISR must explicitly retrieve the vector and clear the interrupt via platform-specific calls.
|
Note
|
Keep ISR code minimal. Heavy processing (file I/O, printf, lengthy computations) inside an ISR can cause system instability. This sample correctly defers all message processing to the main loop. |
Message Processing Loop
The ProcessMessages() function is the core runtime loop. It runs for a user-specified duration (default 5 seconds), polling the irqFlag global variable to detect when the ISR has signaled a new interrupt.
Enabling Interrupts
Before starting the RT, the sample enables EOM interrupts with naibrd_1553_SetIrqManipulate():
swResult = naibrd_1553_SetIrqManipulate(DevNum, 0x1, INTERRUPT_TYPE_MASK, myIsr);
The first parameter (0x1) enables interrupts. INTERRUPT_TYPE_MASK is defined as NAI_1553_INT_STS_REG1_MASK_END_OF_MESSAGE, selecting the EOM interrupt type. The myIsr parameter is passed for DDC compatibility but is not used by the NAI implementation (the ISR was already installed via naibrd_InstallISR()).
Interrupt-Driven Processing Flow
When irqFlag is set by the ISR, the processing loop:
-
Resets
irqFlagto 0. -
Displays the received interrupt vector.
-
Reads and clears the interrupt status registers with
naibrd_1553_GetIntStatus(). -
Identifies the interrupt type (EOM, time tag rollover, or other) from the status bits.
-
Clears the interrupt latch bit with
naibrd_1553_ClearIntLatch(). -
Reads the message from the RT stack with
naibrd_1553_RtMessageGetFromStackRaw(). -
Decodes the raw message with
naibrd_1553_RtMessageDecodeRaw().
while (time(NULL) < end)
{
if (irqFlag)
{
irqFlag = 0;
printf("\nReceived Vector: 0x%08X", receivedVector);
swResult = naibrd_1553_GetIntStatus(deviceNumber, &status1, &status2);
if (status1 & NAI_1553_INT_STS_REG1_MASK_END_OF_MESSAGE)
{
printf("\nEnd Of Message interrupt triggered. IrqCount = %d\n", irqCount);
}
swResult = naibrd_1553_ClearIntLatch(deviceNumber);
swResult = naibrd_1553_RtMessageGetFromStackRaw(deviceNumber, wsBuffer, NAI_1553_MAX_MESSAGE_SIZE_RT);
if (swResult > 0)
{
swResult = naibrd_1553_RtMessageDecodeRaw(deviceNumber, wsBuffer, &DecodedMsgStruct);
/* ... display decoded message ... */
}
}
}
Disabling Interrupts
After the processing loop completes, the sample disables interrupts by calling naibrd_1553_SetIrqManipulate() with the enable flag set to 0x0 and a mask of 0xFFFFFFFF (all interrupt types):
swResult = naibrd_1553_SetIrqManipulate(DevNum, 0x0, 0xFFFFFFFF, myIsr);
Cleanup
After the main loop exits, the sample uninstalls the ISR and frees the 1553 device:
swResult = naibrd_UninstallISR(cardIndex);
swResult = naibrd_1553_Free(DevNum);
Always uninstall the ISR before freeing the device. Failing to uninstall the ISR can cause the system to call a stale function pointer if another interrupt fires after the device is freed.
Message Type Discrimination
The command word’s TR bit (bit 0x0400) distinguishes Rx from Tx messages. When the bit is 0, the BC sent data to the RT (Rx). When the bit is 1, the BC requested data from the RT (Tx). The sample prints different fields depending on direction — Rx messages include the full data payload, while Tx messages display only a brief notification.
Decoded Fields
Each decoded message (naiDecodedMessageStructure) contains:
-
Block Status (
wBlockStatus) — hardware status flags for the message transfer. -
Time Tag (
wTimeTag) — hardware timestamp of when the message was received. -
Command Word (
wCommandWord1) — the 1553 command word containing the RT address, subaddress, TR bit, and word count. -
Data Word Count (
wDataWordCount) — number of data words in the message. -
Payload (
waData[]) — the actual data words (displayed for Rx messages only).
|
Important
|
|
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 for hardware-specific diagnostic procedures.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found or connection timeout |
Board not powered, missing configuration file, network issue |
Verify hardware and configuration file. If file doesn’t exist, configure and save from board menu. |
Module not recognized as 1553 |
Selected module is not FT-series or CM with 1553 |
Verify module type at the selected slot. |
Device open or initialization failure |
Wrong card/module/channel, or device already in use |
Verify parameters. Close other applications using this channel. |
RT address mismatch |
RT address doesn’t match what BC is targeting |
Confirm address set via |
RT address source conflict |
Software address set but hardware pin mode active, or vice versa |
Match |
Interrupts not firing |
Wrong steering constant, ISR not installed, or Ethernet connection |
Verify steering matches hardware. Use |
Spurious interrupts on startup |
Stale interrupt status from previous run |
Clear status with |
ISR never called |
|
Install ISR before starting the RT. Verify the ISR function signature matches |
No messages appearing |
RT not started, subaddress not legalized, or BC not sending |
Verify |
Subaddress not legalized |
Data block mapped without legalization flag |
Set |
Data block creation or mapping failure |
Invalid block type, ID, or subaddress out of range |
Verify block type constants and subaddress range (1-30 for data, 0/31 for mode codes). |
Interrupts fire but no messages |
Interrupt is time tag rollover or other non-EOM type |
Check |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — M1553_RT_Interrupt.c (SSK 1.x)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.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"
/* Common 1553 Sample Program include files */
#include "nai_1553_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_1553.h"
#define INTERRUPT_VECTOR_ADDEND 0xA0
#define INTERRUPT_TYPE_MASK NAI_1553_INT_STS_REG1_MASK_END_OF_MESSAGE /* NAI_1553_INT_STS_REG1_MASK_TIME_TAG_ROLLOVER */ /* NAI_1553_INT_STS_REG1_MASK_END_OF_MESSAGE */
#define INT_FILTER_VALUE 0x30
static const int8_t *CONFIG_FILE = (int8_t *)"default_1553_RTInterrupt.txt";
/* Function prototypes */
static bool_t Run_M1553_RT_Interrupt(int32_t cardIndex, int32_t module, uint32_t modid);
static int32_t ProcessMessages(int32_t duration);
static void myIsr(void* param, uint32_t vector);
static const uint16_t DATA_BLOCK_ID_TX1 = 1;
static const uint16_t DATA_BLOCK_ID_TX2 = 2;
static const uint16_t DATA_BLOCK_ID_RX = 3;
static const int32_t DEF_RT_CHANNEL = 3;
static const int16_t DEF_RT_DEV_NUM = 3;
static const uint8_t DEF_RT_ADDRESS = 1;
static const uint8_t DEF_RT_SUBADDR = 2;
static const uint16_t DEF_RT_RX_BUF_TYPE = NAI_1553_RT_DATABLOCK_DOUBLE;
/* Global Variables */
static int32_t currDataBlock;
static int16_t deviceNumber;
static volatile int32_t irqFlag;
static int32_t irqCount;
static uint32_t receivedVector;
/**************************************************************************************************************/
/**
<summary>
The purpose of the M1553_RT_Interrupt is to illustrate the methods to call in the naibrd library to configure
the 1553 channel as a Remote Terminal, legalize the user specified subaddress for both Tx and Rx, and set it up
with interrupts enabled such that when an end of message interrupt is triggered, the received 1553 message is
displayed in the console. (NOTE: interrupt steering should be set in accordance with the onboard processor type,
where steering is set to NAIBRD_INT_STEERING_PCIE_APP for PPC1 and NAIBRD_INT_STEERING_ON_BOARD_0 for ARM1).
Ethernet communication will not work with this application.
The following routines are called to configure and enable interrupts on the 1553 and hook the interrupt service
routine (ISR).
- naibrd_1553_SetIrqConfig
- naibrd_1553_SetIrqManipulate
- naibrd_InstallISR
- naibrd_1553_SetInterruptSteering
- naibrd_1553_SetIntVector
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 1553 routines.
- ConfigDevice
- DisplayDeviceCfg
- GetBoardSNModCfg
- CheckModule
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t M1553_RT_Interrupt(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
uint32_t moduleID = 0;
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))
{
Run_M1553_RT_Interrupt(cardIndex, module, moduleID);
}
}
}
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;
}
static bool_t Run_M1553_RT_Interrupt(int32_t cardIndex, int32_t module, uint32_t modid)
{
/* Variables */
bool_t bQuit = FALSE;
int32_t rtchan;
uint8_t rtaddr;
uint8_t sa = DEF_RT_SUBADDR;
int16_t DevNum = 0;
int32_t swResult;
uint16_t nDataBlockType = 0;
bool_t bContinue = TRUE;
int32_t duration;
uint16_t status1, status2;
bool_t bSoftwareRTAddr;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
/*************************/
/*** 1553 DEVICE SETUP ***/
/*************************/
/* Get Card, Module, Channel Numbers and Open a Handle */
bQuit = Get1553RTCfg(modid, DEF_RT_CHANNEL, DEF_RT_ADDRESS, &rtchan, &rtaddr);
if (bQuit)
{
return bQuit;
}
printf("Enter Subaddress\n");
bQuit = Get1553Address(31, DEF_RT_SUBADDR, &sa);
/* Get Logical Device # */
bQuit = Get1553LogicalDevNum(DEF_RT_DEV_NUM, &DevNum);
if (bQuit)
{
return bQuit;
}
deviceNumber = DevNum;
irqFlag = 0;
/* Associate Card, Module and Channel Numbers with the Logical Device # */
swResult = naibrd_1553_Open(cardIndex, module, rtchan, DevNum);
if(swResult)
{
bQuit = TRUE;
printf("Error: naibrd_1553_Open %d", swResult);
return bQuit;
}
/* Initialize Device */
swResult = naibrd_1553_Initialize(DevNum,NAI_1553_ACCESS_CARD,NAI_1553_MODE_RT,0,0,0);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_Initialize %d", swResult);
return bQuit;
}
if (modid == NAI_MODULE_ID_FT8)
{
/* Simplex Enable */
naibrd_1553_WriteAuxReg(DevNum, 0x3, 0x4000);
}
/* Get RT Address Source from user */
bQuit = Get1553RTAddressSource(TRUE, &bSoftwareRTAddr);
if (bQuit)
{
return bQuit;
}
if (bSoftwareRTAddr)
{
/* Set RTAD_SW_EN and RT_ADR_LAT in software */
swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0018);
/* Set RT address */
swResult = naibrd_1553_RtSetAddress(DevNum, rtaddr);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtSetAddress %d", swResult);
return bQuit;
}
}
else
{
/* Unset RTAD_SW_EN and set RT_ADR_LAT in software */
swResult = naibrd_1553_WriteAuxReg(DevNum, 0x2, 0x0008);
}
/***********************/
/*** INTERRUPT SETUP ***/
/***********************/
/* Reset Interrupt counter */
irqCount = 0;
/* Setup Interrupts in Core with Level Detection and Auto Clear (read clears interrupt statuses) */
swResult = naibrd_1553_SetIrqConfig(DevNum, NAI_1553_IRQ_MODE_LEVEL, NAI_1553_IRQ_AUTO_CLEAR);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetIrqConfig %d", swResult);
return bQuit;
}
/* Hook the interrupt service routine */
swResult = naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_DONT_CARE, (nai_isr_t)myIsr, NULL); /* NAIBRD_IRQ_ID_ON_BOARD_0 for Onboard, NAIBRD_IRQ_ID_DONT_CARE for everything else */
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_InstallISR %d", swResult);
return bQuit;
}
/* Set the Interrupt Steering to Onboard */
swResult = naibrd_1553_SetInterruptSteering( DevNum, NAIBRD_INT_STEERING_CPCI_APP ); /* NAIBRD_INT_STEERING_CPCI_APP, NAIBRD_INT_STEERING_PCIE_APP for PCIe, NAIBRD_INT_STEERING_ON_BOARD_0 for Onboard */
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetInterruptSteering %d", swResult);
return bQuit;
}
/* Set the Interrupt Vector (The vector is set as channel number plus 0xA0) */
swResult = naibrd_1553_SetIntVector( DevNum, INTERRUPT_VECTOR_ADDEND + rtchan );
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetIntVector %d", swResult);
return bQuit;
}
/* Read core status registers to clear statuses */
swResult = naibrd_1553_GetIntStatus(DevNum, &status1, &status2);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_GetIntStatus %d", swResult);
return bQuit;
}
/* Clear Interrupt Latch Bit */
swResult = naibrd_1553_ClearIntLatch(DevNum);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_ClearIntLatch %d", swResult);
return bQuit;
}
/*************************/
/*** 1553 BUFFER SETUP ***/
/*************************/
/* Select Single Buffer, Double Buffer or Circular Buffer for Rx Messages */
bQuit = Get1553RxBufferType(DEF_RT_RX_BUF_TYPE, &nDataBlockType);
if (bQuit)
{
return bQuit;
}
/* Create a Rx Buffer data block and map to the desired subaddress */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_RX, nDataBlockType, NULL, 0);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_RX, sa, NAI_1553_RT_MESSAGE_TYPE_RX, NAI_1553_RT_DATABLOCK_IRQ_END_OF_MESSAGE, 1);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
/* Create two Tx Buffer data blocks and map the first to the desired subaddress */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX1, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DATA_BLOCK_ID_TX2, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DATA_BLOCK_ID_TX1, sa, NAI_1553_RT_MESSAGE_TYPE_TX, 0, 1);
if(swResult < 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
currDataBlock = DATA_BLOCK_ID_TX1;
/*******************/
/*** RUN 1553 RT ***/
/*******************/
while (bContinue)
{
printf("\nType duration (in seconds) to run RT or %c to quit (default: 5) : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
duration = 5;
if (inputResponseCnt > 0)
{
duration = (int)atol((const char*)inputBuffer);
}
/* Enable Subadddress EOM Interrupts (myIsr is only used here for compatibility with DDC, it is not used in the function) */
swResult = naibrd_1553_SetIrqManipulate(DevNum, 0x1, INTERRUPT_TYPE_MASK, myIsr);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetIrqManipulate %d", swResult);
return bQuit;
}
/* Start RT */
swResult = naibrd_1553_RtStart(DevNum);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtStart %d", swResult);
return bQuit;
}
/* Process New Messages */
ProcessMessages(duration);
/* Stop RT */
swResult = naibrd_1553_RtStop(DevNum);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtStop %d", swResult);
return bQuit;
}
/* Disable Interrupts */
swResult = naibrd_1553_SetIrqManipulate(DevNum, 0x0, 0xFFFFFFFF, myIsr);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetIrqManipulate %d", swResult);
return bQuit;
}
}
else
bContinue = FALSE;
}
/* Uninstall ISR */
swResult = naibrd_UninstallISR(cardIndex);
/* Free 1553 Device */
swResult = naibrd_1553_Free(DevNum);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_Free %d", swResult);
return bQuit;
}
return bQuit;
}
static void myIsr(void* param, uint32_t vector)
{
#if defined (WIN32)
UNREFERENCED_PARAMETER(param);
UNREFERENCED_PARAMETER(vector);
#endif
#if defined (__VXWORKS__)
/* Get the vector that caused the interrupt */
vector = nai_Onboard_GetInterruptVector();
logMsg("\nvector = %d deviceNumber = %d\n", vector, deviceNumber, 2, 3, 4, 5);
/* Clear Interrupt */
nai_Onboard_ClearInterrupt();
#endif
receivedVector = vector;
/* Set the global interrupt flag */
irqFlag = 1;
irqCount++;
}
static int ProcessMessages(int32_t duration)
{
time_t end;
uint32_t swResult;
int32_t i;
naiDecodedMessageStructure DecodedMsgStruct;
uint16_t wsBuffer[72] = { 0x0000 };
int32_t count = 0;
uint16_t status1, status2;
end = time(NULL) + duration;
/* While looping for the user specified duration of time, poll on the global irqFlag and if it is set (interrupt received), */
/* reset the flag, clear the interrupt status registers, clear interrupt latch bit and process new 1553 message, if any. */
while (time(NULL) < end)
{
if (irqFlag)
{
irqFlag = 0;
/* Display the Interrupt Vector */
printf("\nReceived Vector: 0x%08X", receivedVector);
/* Read to clear status registers */
swResult = naibrd_1553_GetIntStatus(deviceNumber, &status1, &status2);
if (swResult != NAI_SUCCESS)
{
printf("\nERROR: naibrd_1553_GetIntStatus - %d\n", swResult);
}
if (status1 & NAI_1553_INT_STS_REG1_MASK_END_OF_MESSAGE)
{
printf("\nEnd Of Message interrupt triggered. IrqCount = %d\n", irqCount);
}
else if (status1 & NAI_1553_INT_STS_REG1_MASK_TIME_TAG_ROLLOVER)
{
printf("\nTime Tag Rollover interrupt triggered. IrqCount = %d\n", irqCount);
}
else
{
printf("\nOther interrupt triggered. status1=0x%04X status2=0x%04X IrqCount=%d\n", status1, status2, irqCount);
}
/* Clear Latch Bit */
swResult = naibrd_1553_ClearIntLatch(deviceNumber);
if (swResult != NAI_SUCCESS)
{
printf("\nERROR: naibrd_1553_ClearIntLatch - %d\n", swResult);
}
/* Get Data */
/* If the stack pointer has updated (new message arrived), read one message at a time */
swResult = naibrd_1553_RtMessageGetFromStackRaw(deviceNumber, wsBuffer, NAI_1553_MAX_MESSAGE_SIZE_RT);
if (swResult < 0)
{
printf("ERROR: naibrd_1553_RtMessageGetFromStackRaw %d\n\n", swResult);
}
else if (swResult > 0)
{
/* Decode Raw Message */
swResult = naibrd_1553_RtMessageDecodeRaw(deviceNumber, wsBuffer, &DecodedMsgStruct);
if (swResult < 0)
{
printf("ERROR: naibrd_1553_RtMessageDecodeRaw %d\n\n", swResult);
}
if ((DecodedMsgStruct.wCommandWord1 & 0x0400) != 0x0400) /* If this is a Rx message */
{
printf("Rx Msg Received\n");
printf("\n\nDecoded Message:\n\n");
printf("Block Status - 0x%04X\n", DecodedMsgStruct.wBlockStatus);
printf("Time Tag - 0x%04X\n", DecodedMsgStruct.wTimeTag);
printf("Command Word - 0x%04X\n", DecodedMsgStruct.wCommandWord1);
printf("Data Word Count - 0x%04X\n", DecodedMsgStruct.wDataWordCount);
printf("Data:");
for (i = 0; i < DecodedMsgStruct.wDataWordCount; i++)
{
if (i % 8 == 0)
{
printf("\n");
}
printf("0x%04X ", DecodedMsgStruct.waData[i]);
}
printf("count: %d\n", count++);
printf("\n\n");
}
else
{
printf("Tx Msg Received\n");
}
}
}
#if defined (__VXWORKS__)
taskDelay(1);
#endif
}
return 1;
}