M1553 RT HBuff Interrupt
Edit this on GitLab
M1553 RT HBuff Interrupt Sample Application (SSK 1.x)
Overview
The M1553 RT HBuff Interrupt sample application demonstrates how to configure a MIL-STD-1553 channel as a Remote Terminal (RT) with both host buffer-based message management and interrupt-driven notification using the NAI Software Support Kit (SSK 1.x). This sample combines the host buffer message path (stack-to-host-buffer copy, message count, decoded retrieval) with hardware interrupts so that the application only processes messages when the hardware signals that new data has arrived. The ISR performs the stack-to-host-buffer transfer inside the interrupt context, ensuring messages are captured as quickly as possible. The main loop then reads decoded messages from the host buffer at its own pace.
The key 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). -
naibrd_1553_RtStkToHbuf32()— copies messages from the RT stack to the host buffer (called inside the ISR). -
naibrd_1553_RTGetHBufMsgCount()— returns the number of messages waiting in the host buffer. -
naibrd_1553_RtGetHBufMsgDecoded()— retrieves and decodes the next message, reporting any stack or host buffer losses. -
naibrd_1553_RtHbuffInstall()/naibrd_1553_RtHbuffUnInstall()— allocates and releases the host buffer.
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_HBuff_Interrupt executable from your build output directory. On startup the application looks for a configuration file (default_1553_RT_HBuff_Interrupt.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 the host buffer, and enters a timed monitoring loop that waits for interrupt-driven message notification and decodes messages from the host buffer.
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_RT_HBuff_Interrupt.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 host buffer message processing.
#if defined (__VXWORKS__)
int32_t M1553_RT_HBuff_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_HBuff_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, host buffer installation, 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 ISR can pass it tonaibrd_1553_RtStkToHbuf32(). -
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. NAI_1553_IRQ_AUTO_CLEAR means that reading the interrupt status registers automatically clears them.
Step 2: Install the ISR
To install your interrupt service routine on the board, call naibrd_InstallISR(). This sample passes a pointer to DevNum as the user context so the ISR can access the device number:
swResult = naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_ON_BOARD_0, (nai_isr_t)myIsr, &DevNum);
NAIBRD_IRQ_ID_ON_BOARD_0 is used because this sample is designed for onboard processor operation. The &DevNum parameter is a user context pointer that the ISR dereferences to get the logical device number for the naibrd_1553_RtStkToHbuf32() call.
Step 3: Set Interrupt Steering
To route the interrupt to the onboard processor, call naibrd_1553_SetInterruptSteering():
swResult = naibrd_1553_SetInterruptSteering(DevNum, NAIBRD_INT_STEERING_ON_BOARD_0);
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.
Step 5: Clear Stale Status
Before enabling interrupts, clear any stale interrupt status from previous operations:
swResult = naibrd_1553_GetIntStatus(DevNum, &status1, &status2);
swResult = naibrd_1553_ClearIntLatch(DevNum);
|
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 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;
|
Important
|
|
Two-Stage Message Path with ISR-Driven Transfer
This sample combines the host buffer message path with interrupt-driven stack transfer. The key difference from the polling-based M1553_RT_HBuff sample is that the stack-to-host-buffer transfer happens inside the ISR rather than in the main loop.
Why Transfer in the ISR?
By calling naibrd_1553_RtStkToHbuf32() inside the ISR, messages are moved from the hardware stack to the host buffer at the earliest possible moment — immediately when the interrupt fires. This minimizes the window during which the hardware stack could overflow, which is especially important under high message rates.
Stage 1: RT Stack to Host Buffer (in ISR)
When the hardware generates an EOM interrupt, the ISR calls naibrd_1553_RtStkToHbuf32() to copy all pending messages from the RT stack into the host buffer:
static void myIsr(void* param, uint32_t vector)
{
int32_t swResult;
#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;
swResult = naibrd_1553_RtStkToHbuf32(*(int16_t*)param);
if (swResult < 0)
{
printf("Error: naibrd_1553_RtStkToHbuf32 called in ISR, failed %d", swResult);
}
irqFlag = 1;
irqCount++;
}
The ISR dereferences the param pointer (which was set to &DevNum when the ISR was installed) to get the logical device number. After the stack-to-host-buffer transfer, it sets the irqFlag to signal the main loop.
Stage 2: Host Buffer Read (in Main Loop)
The main processing loop waits for irqFlag, then reads decoded messages from the host buffer. The host buffer can hold up to 131,072 words, installed via naibrd_1553_RtHbuffInstall(DevNum, NAI_1553_MAX_SIZE_OF_HOST_BUFFER).
Host Buffer Install/Uninstall
The host buffer is installed before starting the RT and uninstalled after stopping:
/* Create Host Buffer */
swResult = naibrd_1553_RtHbuffInstall(DevNum, NAI_1553_MAX_SIZE_OF_HOST_BUFFER);
/* Start RT */
swResult = naibrd_1553_RtStart(DevNum);
/* ... process messages ... */
/* Stop RT */
swResult = naibrd_1553_RtStop(DevNum);
/* Uninstall Host Buffer */
swResult = naibrd_1553_RtHbuffUnInstall(DevNum);
Call naibrd_1553_RtHbuffInstall() before naibrd_1553_RtStart(). Call naibrd_1553_RtHbuffUnInstall() after naibrd_1553_RtStop(). Failing to uninstall the host buffer before reinitializing the device may leak allocated resources.
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 and completed the stack-to-host-buffer transfer.
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(). -
Checks the host buffer message count with
naibrd_1553_RTGetHBufMsgCount(). -
If messages are available, decodes the next message with
naibrd_1553_RtGetHBufMsgDecoded().
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\n", irqCount);
}
swResult = naibrd_1553_ClearIntLatch(deviceNumber);
dwMsgCountGet = naibrd_1553_RTGetHBufMsgCount(deviceNumber);
if (dwMsgCountGet >= 1)
{
swResult = naibrd_1553_RtGetHBufMsgDecoded(deviceNumber, &sMsg, &dwMsgCount,
&dwStkLost, &dwHBufLost, NAI_1553_RT_MESSAGE_LOC_NEXT_PURGE);
/* ... display decoded message ... */
}
}
Loss Tracking
Both dwStkLost and dwHBufLost are returned by naibrd_1553_RtGetHBufMsgDecoded(). A nonzero value in either field means the application is not keeping up with incoming traffic. Stack losses indicate messages were overwritten in the hardware FIFO before RtStkToHbuf32() could transfer them (even with ISR-driven transfer, this can happen under extreme message rates). Host buffer losses indicate the host buffer filled before the application could read messages out.
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 show only header fields.
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).
Disabling Interrupts and Cleanup
After the processing loop completes, the sample disables interrupts, uninstalls the host buffer, uninstalls the ISR, and frees the device:
swResult = naibrd_1553_RtHbuffUnInstall(DevNum);
swResult = naibrd_1553_SetIrqManipulate(DevNum, 0x0, 0xFFFFFFFF, myIsr);
/* ... after main loop exits ... */
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.
|
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 |
RtStkToHbuf32 fails in ISR |
|
Pass |
No messages in host buffer |
Host buffer not installed before |
Call |
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). |
Messages lost in RT stack |
ISR latency too high, or extreme message rate |
Reduce BC message rate. Verify ISR is not blocked by other interrupt handlers. |
Messages lost in host buffer |
Host buffer full before messages are read |
Increase buffer size at install time or process messages faster. |
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_HBuff_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_interrupt.h"
#include "include/naiapp_interrupt_ether.h"
#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 */
static const int8_t *CONFIG_FILE = (int8_t *)"default_1553_RT_HBuff_Interrupt.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_HBuff_Interrupt is to illustrate the methods to call in the naibrd library to configure
the 1553 channel as a Remote Terminal, utilize Rt Host Buffers, legalize Subaddress 2 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
- naibrd_1553_RtStkToHbuf32
- naibrd_1553_RTGetHBufMsgCount
- naibrd_1553_RtGetHBufMsgDecoded
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_HBuff_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_ON_BOARD_0, (nai_isr_t)myIsr, &DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_InstallISR %d", swResult);
return bQuit;
}
/* Set the Interrupt Steering to Onboard */
/* NAIBRD_INT_STEERING_CPCI_APP, NAIBRD_INT_STEERING_PCIE_APP for PCIe, NAIBRD_INT_STEERING_ON_BOARD_0 for Onboard */
swResult = naibrd_1553_SetInterruptSteering( DevNum, NAIBRD_INT_STEERING_ON_BOARD_0);
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;
}
/* Create Host Buffer */
swResult = naibrd_1553_RtHbuffInstall(DevNum, NAI_1553_MAX_SIZE_OF_HOST_BUFFER);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtHbuffInstall %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;
}
swResult = naibrd_1553_RtHbuffUnInstall(DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtHbuffUnInstall %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)
{
int32_t swResult;
#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;
swResult = naibrd_1553_RtStkToHbuf32(*(int16_t*)param);
if (swResult < 0)
{
printf("Error: naibrd_1553_RtStkToHbuf32 called in ISR, failed %d", swResult);
}
else
{
printf("\nnaibrd_1553_RtStkToHbuf32 was called in ISR, passed\n");
}
/* Set the global interrupt flag */
irqFlag = 1;
irqCount++;
}
static int ProcessMessages(int32_t duration)
{
time_t end;
uint32_t swResult;
int32_t i;
int32_t count = 0;
uint16_t status1, status2;
naiDecodedMessageStructure sMsg;
uint32_t dwStkLost = 0;
uint32_t dwHBufLost = 0;
uint32_t dwMsgCount = 0;
uint32_t dwMsgCountGet = 0;
uint32_t dwCurCount = 0;
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\n", irqCount);
}
else if (status1 & NAI_1553_INT_STS_REG1_MASK_TIME_TAG_ROLLOVER)
{
printf("\nTime Tag Rollover interrupt triggered. IrqCount = %d\n\n", irqCount);
}
else
{
printf("\nOther interrupt triggered. status1=0x%04X status2=0x%04X IrqCount=%d\n\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 message count */
dwMsgCountGet = naibrd_1553_RTGetHBufMsgCount(deviceNumber);
if (swResult < 0)
{
printf("\nERROR: naibrd_1553_RTGetHBufMsgCount - %d\n", swResult);
}
if (dwMsgCountGet >= 1)
{
printf("/nCount = %d\n", dwMsgCountGet);
/* Decode Raw Message */
swResult = naibrd_1553_RtGetHBufMsgDecoded(deviceNumber, &sMsg, &dwMsgCount, &dwStkLost, &dwHBufLost, NAI_1553_RT_MESSAGE_LOC_NEXT_PURGE);
if (swResult < 0)
{
printf("Error: naibrd_1553_RtGetHBufMsgDecoded %d\n\n", swResult);
return 0;
}
/* Message Lost */
if ((dwStkLost > 0) || (dwHBufLost > 0))
{
printf("Number of msgs lost %d\n", (int)(dwStkLost + dwHBufLost));
}
/* Message Found */
if (dwMsgCount)
{
++dwCurCount;
if ((sMsg.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", sMsg.wBlockStatus);
printf("Time Tag - 0x%04X\n", sMsg.wTimeTag);
printf("Command Word - 0x%04X\n", sMsg.wCommandWord1);
printf("Data Word Count - 0x%04X\n", sMsg.wDataWordCount);
printf("Data:");
for (i = 0; i < sMsg.wDataWordCount; i++)
{
if (i % 8 == 0)
{
printf("\n");
}
printf("0x%04X ", sMsg.waData[i]);
}
printf("count: %d\n", count++);
printf("\n\n");
}
else
{
printf("Tx Msg Received\n");
printf("\n\nDecoded Message:\n\n");
printf("Block Status - 0x%04X\n", sMsg.wBlockStatus);
printf("Time Tag - 0x%04X\n", sMsg.wTimeTag);
printf("Command Word - 0x%04X\n", sMsg.wCommandWord1);
printf("Data Word Count - 0x%04X\n", sMsg.wDataWordCount);
printf("count: %d\n", count++);
printf("\n\n");
}
}
}
nai_msDelay(10);
}
#if defined (__VXWORKS__)
taskDelay(1);
#endif
}
return 1;
}