Integrator Resources

The official home for NAI Support

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

Toggle Components with Visual Button
JavaScript Form Processing

M1553 BC Interrupt

M1553 BC Interrupt Sample Application (SSK 1.x)

Overview

The M1553 BC Interrupt sample application demonstrates how to configure a MIL-STD-1553 Bus Controller (BC) with interrupt-driven message completion notification. Instead of polling for message status, the application installs an Interrupt Service Routine (ISR) that fires each time the BC hardware completes a message transaction. The ISR sets a flag, and the main thread checks that flag to determine which messages were sent and to decode their results.

This sample combines two patterns that are demonstrated separately in other samples:

  • BC scheduling and message sending — building a frame hierarchy with multiple messages at different periodic rates, as shown in the M1553 BC SendMessageWithRetries sample.

  • Interrupt handling — installing an ISR, configuring interrupt steering and vectors, and processing interrupt events in the main thread, as shown in the DT Interrupts sample.

The key difference from module-level interrupts (such as DT or AD threshold interrupts) is the interrupt source. Module-level interrupts are triggered by external signal conditions — a voltage crossing a threshold, a discrete input changing state. BC interrupts are triggered by internal protocol events — specifically, the completion of a 1553 message transaction on the bus. The BC hardware generates an End-of-Message (EOM) interrupt each time it finishes sending a command and receiving (or timing out on) the RT response.

This sample supports the following 1553 module types:

  • FT0 through FTF (4-channel MIL-STD-1553)

  • FTJ / FTK (2-channel MIL-STD-1760)

  • Combination modules CM1, CM5, and CM8

The application detects the installed module variant at runtime using IsFTx1553() and adjusts the available channel count accordingly.

For detailed 1553 protocol specifications, message formats, and hardware register descriptions, see the FTA-FTF Manual. For FTJ/FTK (MIL-STD-1760) specifics, see the FTJ-FTK Manual.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a 1553 module installed (FT0-FTF, FTJ/FTK, or a combination module with 1553 functionality).

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

  • A direct bus connection (PCI, PCIe, or cPCI) between the host and the NAI board. Ethernet connections do not support interrupt delivery for this sample.

Important

Ethernet connections are not supported for this sample. Interrupt-driven operation requires a direct bus connection (PCI, PCIe, or cPCI) between the host processor and the NAI board. Ethernet does not provide the low-latency interrupt path that naibrd_InstallISR() requires. If you need interrupt-like notification over Ethernet, see the Ethernet IDR (Interrupt Driven Response) mechanism described in the DT Interrupts sample.

How to Run

Launch the M1553_BC_Interrupt executable from your build output directory. On startup the application looks for a configuration file (default_1553BC_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 prompts you for a channel number, logical device number, bus selection, and software override preference, then runs the BC schedule for approximately 10 seconds while printing interrupt-triggered message completions to the console.

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

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

  1. Call naiapp_RunBoardMenu() to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_1553BC_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.

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

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

  4. Retrieve the module ID with naibrd_GetModuleID() so downstream code can adapt to the specific 1553 variant installed.

#if defined (__VXWORKS__)
int32_t M1553_BC_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_BC_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:

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

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

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

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

Program Structure

The application entry point is main() (or M1553_BC_Interrupt() on VxWorks). After the board connection is established and a module is selected, control passes to Run_M1553_BC_Interrupt(), which detects the module type and queries the user for a channel number.

Module Detection and Channel Selection

Run_M1553_BC_Interrupt() checks the module ID to confirm that the selected module supports 1553 functionality. If IsFTx1553() returns true, the application allows selection of up to 4 channels:

static bool_t Run_M1553_BC_Interrupt(int32_t cardIndex, int32_t module, uint32_t modid)
{
   bool_t bQuit = FALSE;
   int32_t channel;
   int32_t MaxChannel = 4;

   if (IsFTx1553(modid))
   {
      MaxChannel = 4;
      bQuit = naiapp_query_ChannelNumber(MaxChannel, DEF_M1553_CHANNEL, &channel);
      if (!bQuit)
      {
         bQuit = RunBCInterrupt(cardIndex, module, channel);
      }
   }
   else
      printf("\nThis module does not support 1553 functionality.\n");

   return bQuit;
}

User Input Flow

Once a channel is selected, RunBCInterrupt() collects the remaining configuration from the user through a series of utility function calls:

  1. Get1553LogicalDevNum() — prompts for the logical device number. The default is 1. This number maps the physical channel to a software handle used by all subsequent naibrd_1553_*() calls.

  2. GetBus() — asks "Bus A or B?" The default is Bus A. The selected bus is stored as a control word flag that is OR’d into each message’s control word when the message is created.

  3. Get1553BCSoftwareOverride() — asks whether to override the external BC_DISABLE and M1760 input pins in software. When enabled, the application writes to an auxiliary register to force BC mode regardless of the external pin state. This is useful in bench setups where the hardware pins are not driven.

Device Initialization

After the user has provided all configuration inputs, RunBCInterrupt() initializes the 1553 hardware. This sequence opens the device, optionally overrides external control pins, resets the module, and places it in Bus Controller mode.

Open Device

The first step is to open the 1553 interface on the selected channel and assign it a logical device number:

status = naibrd_1553_Open(cardIndex, module, channel, devnum);
if(status != 0)
{
   printf("Error: naibrd_1553_Open Ch %d, status = %d", channel, status);
   return TRUE;
}

naibrd_1553_Open() binds the physical channel (identified by card index, module slot, and channel number) to a logical device number (devnum). All subsequent naibrd_1553_*() calls use this logical device number to address the channel.

Software Override of External Pins

The module has two external hardware pins that affect BC operation:

  • BC_DISABLE — when asserted externally, this pin prevents the channel from operating as a Bus Controller.

  • M1760 (CHx-STANDARD) — on FTJ/FTK modules, this pin controls the MIL-STD-1760 RT powerup mode.

If these pins are not driven by external hardware (which is typical in bench setups), BC initialization will fail unless the application overrides them in software:

if (bSoftware)
{
   /* Override external BC_DISABLE and M1760 */
   naibrd_1553_WriteAuxReg(devnum, 0x2, 0xA000);
}
else
{
   /* Do not override external BC_DISABLE and M1760 Inputs */
   naibrd_1553_WriteAuxReg(devnum, 0x2, 0);
}

Writing 0xA000 to auxiliary register 0x2 overrides both pins in software, forcing BC operation to be allowed regardless of the external pin state.

Reset and Initialize

The device is reset by toggling auxiliary register 0x1, then initialized in BC mode:

/* Reset Device */
naibrd_1553_WriteAuxReg(devnum, 0x1, 1);
nai_msDelay(1);
naibrd_1553_WriteAuxReg(devnum, 0x1, 0);

/* Initialize 1553 Device(s) */
status = naibrd_1553_Initialize(devnum, NAI_1553_ACCESS_CARD, NAI_1553_MODE_BC, 0, 0, 0);

The reset assert/de-assert sequence with a 1 ms delay clears the device state. naibrd_1553_Initialize() then configures the channel as a Bus Controller. The NAI_1553_MODE_BC parameter is critical — it determines the operating role. Other modes (RT, MT) would configure the channel for different 1553 roles.

Important

Common Errors

  • Device open failure — wrong card/module/channel combination, or the device is already opened by another application. Verify your indices and close any other application using this channel.

  • Initialization failure — the BC_DISABLE pin is preventing BC mode. Enable software override with naibrd_1553_WriteAuxReg(devnum, 0x2, 0xA000).

  • Reset not completing — hardware not responding. Verify the module is powered and seated. Try increasing the post-reset delay.

Interrupt Configuration

This section covers the interrupt setup that distinguishes this sample from polling-based BC samples like M1553 BC SendMessageWithRetries. The interrupt configuration runs after device initialization but before the BC schedule is constructed.

How BC Interrupts Differ from Module-Level Interrupts

In samples like DT Interrupts, interrupts are triggered by external signal conditions — a discrete input changing state, a voltage crossing a threshold. The interrupt source is an I/O event on the module’s physical pins.

BC interrupts are fundamentally different. They are triggered by internal protocol events within the 1553 controller core. When the BC sends a command word on the bus and the RT responds (or the response times out), the 1553 hardware generates an End-of-Message (EOM) interrupt. This interrupt tells the host processor that a message transaction has completed and that the results are available to read.

The practical difference matters for your application design:

  • Module-level interrupts signal that something happened in the external world. Your ISR typically reads the new input state.

  • BC interrupts signal that the BC scheduler has completed a step in its internal schedule. Your ISR sets a flag, and the main thread queries which messages completed and what their results were.

IRQ Configuration

The first step is to configure the interrupt mode on the 1553 core. Level detection with auto-clear means that reading the interrupt status registers automatically clears the pending interrupt:

irqCount = 0;

status = naibrd_1553_SetIrqConfig(devnum, NAI_1553_IRQ_MODE_LEVEL, NAI_1553_IRQ_AUTO_CLEAR);
  • NAI_1553_IRQ_MODE_LEVEL — the interrupt remains asserted as long as the condition is true. This is the standard mode for 1553 BC interrupts.

  • NAI_1553_IRQ_AUTO_CLEAR — reading the interrupt status registers clears the pending interrupt automatically, so you do not need a separate clear step in the status-read path.

Install the ISR

Next, install the Interrupt Service Routine callback function that the system will call when an interrupt fires:

status = naibrd_InstallISR(cardIndex, NAIBRD_IRQ_ID_DONT_CARE, (nai_isr_t)myIsr, NULL);

naibrd_InstallISR() registers myIsr as the callback for interrupts on the specified card. The NAIBRD_IRQ_ID_DONT_CARE parameter tells the system to accept interrupts on any available IRQ line. For onboard applications running on the NAI SBC, use NAIBRD_IRQ_ID_ON_BOARD_0 instead.

The ISR itself is intentionally minimal — it captures the interrupt vector and sets a flag:

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\n", vector, 1, 2, 3, 4, 5);
   /* Clear Interrupt */
   nai_Onboard_ClearInterrupt();
#endif

   receivedVector = vector;

   /* Set the global interrupt flag */
   irqFlag = 1;
   irqCount++;
}

The ISR stores the received vector in a global variable, sets the irqFlag flag to 1, and increments a counter. All heavy processing — reading status registers, decoding messages, printing results — happens in the main thread, not in the ISR. This is a best practice for ISR design: keep the ISR fast and defer work to the main context.

The global variables used for ISR-to-main-thread communication are:

static volatile int32_t irqFlag;    /* Set to 1 by ISR, cleared by main thread */
static int32_t irqCount;            /* Running count of interrupts received */
static uint32_t receivedVector;     /* Vector value from most recent interrupt */

Note that irqFlag is declared volatile to ensure the compiler does not optimize away reads in the main thread’s polling loop.

Interrupt Steering

Interrupt steering controls which processor or bus receives the interrupt signal. The correct steering value depends on your hardware topology:

status = naibrd_1553_SetInterruptSteering(devnum, NAIBRD_INT_STEERING_CPCI_APP);

Choose the steering constant that matches your connection:

  • NAIBRD_INT_STEERING_CPCI_APP — cPCI backplane to host application processor.

  • NAIBRD_INT_STEERING_PCIE_APP — PCIe connection to host application processor (use this for PPC1-based boards).

  • NAIBRD_INT_STEERING_ON_BOARD_0 — onboard processor 0 (use this for ARM1-based boards running the application locally).

Using the wrong steering value is the most common cause of "interrupts configured but ISR never fires." The interrupt will be generated by the hardware but delivered to the wrong destination.

Interrupt Vector Assignment

Each 1553 channel is assigned a unique interrupt vector so the ISR can identify which channel generated the interrupt:

status = naibrd_1553_SetIntVector(devnum, INTERRUPT_VECTOR_ADDEND + channel);

The vector can be any value between 0x01 and 0xFF. This sample uses 0xA0 + channel as a convention, which produces unique vectors for each channel on a module. If your system uses multiple 1553 modules, ensure that vectors are unique across all modules and channels.

Clear Pending Interrupts

Before enabling interrupts, clear any stale interrupt state left from a previous run:

/* Read core status registers to clear statuses */
status = naibrd_1553_GetIntStatus(devnum, &intStatus1, &intStatus2);

/* Clear Interrupt Latch Bit */
status = naibrd_1553_ClearIntLatch(devnum);

naibrd_1553_GetIntStatus() reads and clears the two interrupt status registers (since auto-clear is enabled). naibrd_1553_ClearIntLatch() resets the module-level interrupt latch. Together, these calls ensure that no spurious interrupt fires the moment you enable the interrupt mask.

Important

Common Errors

  • ISR never fires — the most common cause is incorrect interrupt steering. Verify that the steering constant matches your physical connection (cPCI, PCIe, or onboard). The second most common cause is using an Ethernet connection, which does not support ISR-based interrupts.

  • ISR fires but vector does not match — another device on the same IRQ line is generating interrupts. Use the vector comparison (receivedVector == INTERRUPT_VECTOR_ADDEND + channel) to filter for your channel.

  • naibrd_InstallISR() fails — the system could not register the ISR. Verify that no other application has already installed an ISR on the same card. On VxWorks, verify that the interrupt stack is large enough.

BC Schedule Configuration

The BC schedule defines what messages are sent, when, and in what order. This sample builds a multi-rate schedule using the standard BC frame hierarchy: data blocks, messages, opcodes, minor frames, and a major frame. For a detailed explanation of each layer in the hierarchy, see the M1553 BC SendMessageWithRetries guide.

Message Rate Design

This sample sends three messages at different periodic rates using a 250 ms minor frame as the base timing unit:

Message Direction RT Addr Subaddress Word Count Rate

MSG1

BC-to-RT

1

1

11

4 Hz (every 250 ms)

MSG2

RT-to-BC

1

2

21

2 Hz (every 500 ms)

MSG3

BC-to-RT

1

8

30

1 Hz (every 1000 ms)

The rate scheduling is achieved by distributing messages across three minor frames, which are then arranged in a specific order within the major frame:

  • Minor Frame 1 (250 ms): MSG1, MSG2, MSG3

  • Minor Frame 2 (250 ms): MSG1, MSG2

  • Minor Frame 3 (250 ms): MSG1 only

The major frame calls these minor frames in the order: MNR1 | MNR3 | MNR2 | MNR3. Over the resulting 1000 ms major frame period:

  • MSG1 appears in every minor frame — sent 4 times (4 Hz).

  • MSG2 appears in MNR1 and MNR2 — sent 2 times (2 Hz).

  • MSG3 appears in MNR1 only — sent 1 time (1 Hz).

Data Block Creation

Each message requires a data block to hold its transmit or receive payload. Three single data blocks are created:

status = naibrd_1553_BcDataBlockCreate(devnum, DBLK1, NAI_1553_BC_DATABLOCK_SINGLE, NULL, 0);
status = naibrd_1553_BcDataBlockCreate(devnum, DBLK2, NAI_1553_BC_DATABLOCK_SINGLE, NULL, 0);
status = naibrd_1553_BcDataBlockCreate(devnum, DBLK3, NAI_1553_BC_DATABLOCK_SINGLE, NULL, 0);

The NAI_1553_BC_DATABLOCK_SINGLE type allocates a single buffer for the data block. The NULL and 0 parameters indicate that no initial data is loaded at creation time — data is written separately before the schedule starts.

Message Creation with EOM Interrupt Enable

Each message is created with the NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED flag OR’d into its control word. This flag is the per-message switch that tells the BC hardware to generate an interrupt when this specific message completes:

/* BC to RT Message 1 */
status = naibrd_1553_BcMessageCreateBcToRt(devnum, MSG1, DBLK1, RT_ADDRESS, RT_SUBADDRESS1,
   WORDCOUNT1, 0, usBus | NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED);

/* RT to BC Message 2 */
status = naibrd_1553_BcMessageCreateRtToBc(devnum, MSG2, DBLK2, RT_ADDRESS, RT_SUBADDRESS2,
   WORDCOUNT2, 0, usBus | NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED);

/* BC to RT Message 3 */
status = naibrd_1553_BcMessageCreateBcToRt(devnum, MSG3, DBLK3, RT_ADDRESS, RT_SUBADDRESS3,
   WORDCOUNT3, 0, usBus | NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED);

The control word flags combine the bus selection (from GetBus()) with the EOM interrupt enable. Without NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED, the BC hardware would not generate an interrupt for that message even though the interrupt system is configured at the device level.

Note that MSG2 uses naibrd_1553_BcMessageCreateRtToBc() — this is an RT-to-BC transfer where the RT sends data to the BC. The BC issues a receive command and the RT responds with data words that are stored in DBLK2.

Opcode and Frame Construction

Opcodes and frames assemble the messages into an executable schedule. First, three EXECUTE_MESSAGE opcodes are created (one per message):

naibrd_1553_BcCommandCreate(devnum, OP1, NAI_1553_OPCODE_EXECUTE_MESSAGE,
   NAI_1553_OPCODE_COND_ALWAYS, MSG1, 0, 0);
naibrd_1553_BcCommandCreate(devnum, OP2, NAI_1553_OPCODE_EXECUTE_MESSAGE,
   NAI_1553_OPCODE_COND_ALWAYS, MSG2, 0, 0);
naibrd_1553_BcCommandCreate(devnum, OP3, NAI_1553_OPCODE_EXECUTE_MESSAGE,
   NAI_1553_OPCODE_COND_ALWAYS, MSG3, 0, 0);

Then the three minor frames are created, each containing a different subset of opcodes. The frame time of 2500 units represents 250 ms (1 unit = 0.1 ms):

/* Minor Frame 1: MSG1, MSG2, MSG3 */
aOpCodes[0] = OP1;
aOpCodes[1] = OP2;
aOpCodes[2] = OP3;
naibrd_1553_BcFrameCreate(devnum, MNR1, NAI_1553_BC_FRAME_MINOR, aOpCodes, 3, 2500, 0);

/* Minor Frame 2: MSG1, MSG2 */
aOpCodes[0] = OP1;
aOpCodes[1] = OP2;
naibrd_1553_BcFrameCreate(devnum, MNR2, NAI_1553_BC_FRAME_MINOR, aOpCodes, 2, 2500, 0);

/* Minor Frame 3: MSG1 only */
aOpCodes[0] = OP1;
naibrd_1553_BcFrameCreate(devnum, MNR3, NAI_1553_BC_FRAME_MINOR, aOpCodes, 1, 2500, 0);

Three CALL_SUBROUTINE opcodes link the minor frames into the major frame:

naibrd_1553_BcCommandCreate(devnum, OP4, NAI_1553_OPCODE_CALL_SUBROUTINE,
   NAI_1553_OPCODE_COND_ALWAYS, MNR1, 0, 0);
naibrd_1553_BcCommandCreate(devnum, OP5, NAI_1553_OPCODE_CALL_SUBROUTINE,
   NAI_1553_OPCODE_COND_ALWAYS, MNR2, 0, 0);
naibrd_1553_BcCommandCreate(devnum, OP6, NAI_1553_OPCODE_CALL_SUBROUTINE,
   NAI_1553_OPCODE_COND_ALWAYS, MNR3, 0, 0);

Finally, the major frame sequences the minor frames: MNR1 → MNR3 → MNR2 → MNR3:

aOpCodes[0] = OP4;   /* Minor Frame 1 */
aOpCodes[1] = OP6;   /* Minor Frame 3 */
aOpCodes[2] = OP5;   /* Minor Frame 2 */
aOpCodes[3] = OP6;   /* Minor Frame 3 */
status = naibrd_1553_BcFrameCreate(devnum, MJR, NAI_1553_BC_FRAME_MAJOR, aOpCodes, 4, 0, 0);

The major frame time is set to 0, which means the minor frame times (250 ms each) control the schedule timing. If you set a non-zero value here, it would override all minor frame times to the same duration.

Important

Common Errors

  • Frame hierarchy error (BcStart fails) — all referenced opcodes, frames, messages, and data blocks must be created before calling naibrd_1553_BcStart(). A missing component causes a startup failure.

  • Unexpected message rates — verify the minor frame arrangement in the major frame. The order MNR1 | MNR3 | MNR2 | MNR3 is essential to achieving the 4/2/1 Hz rate distribution.

  • No EOM interrupts despite schedule running — verify that NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED is included in the control word for each message that should generate an interrupt.

Schedule Execution and Interrupt Processing

With the schedule built and interrupts configured, the application writes initial data to the transmit data blocks, enables the EOM interrupt mask, and starts the BC.

Loading Data Blocks

Before starting the schedule, the application writes data into the transmit data blocks. DBLK1 gets incrementing values and DBLK3 gets a constant pattern:

/* Load BC data block 1 with incremental data */
for (i = 0; i < WORDCOUNT1; i++)
{
   aData[i] = increment++;
}
status = naibrd_1553_BcDataBlockWrite(devnum, DBLK1, aData, WORDCOUNT1, 0);

/* Load BC data block 3 with 0xBBCC */
for (i = 0; i < WORDCOUNT3; i++)
{
   aData[i] = 0xBBCC;
}
status = naibrd_1553_BcDataBlockWrite(devnum, DBLK3, aData, WORDCOUNT3, 0);

DBLK2 is not written because MSG2 is an RT-to-BC transfer — the RT fills this data block when it responds. In your own application, you would update data blocks between schedule runs to send new data on each cycle.

Enabling the EOM Interrupt Mask

The EOM interrupt mask is enabled just before starting the BC. naibrd_1553_SetIrqManipulate() configures which interrupt types the 1553 core will generate:

status = naibrd_1553_SetIrqManipulate(devnum, 0x1, INTERRUPT_TYPE_MASK, myIsr);

The parameters are:

  • 0x1 — enable (1) or disable (0) the specified interrupt type.

  • INTERRUPT_TYPE_MASK — set to NAI_1553_INT_REG1_MASK_BC_END_OF_MESSAGE, which selects the BC End-of-Message interrupt. Other mask values (such as NAI_1553_INT_REG1_MASK_TIME_TAG_ROLLOVER) select different interrupt sources.

  • myIsr — the ISR function pointer. This parameter is required for DDC compatibility but is not used by the NAI implementation since the ISR was already installed via naibrd_InstallISR().

Starting the BC

The BC is started with NAI_1553_BC_FRAME_RUN_FOREVER, which tells the scheduler to loop the major frame continuously until explicitly stopped:

status = naibrd_1553_BcStart(devnum, MJR, NAI_1553_BC_FRAME_RUN_FOREVER);

Once started, the hardware executes the frame hierarchy autonomously. The host processor is free to do other work — it only needs to respond when the ISR signals that an interrupt has occurred.

Main Thread Interrupt Processing Loop

The main thread polls the irqFlag global in a loop, processing interrupts as they arrive. The loop runs for approximately 10 seconds (1000 iterations with a 10 ms delay):

while (counter > 0)
{
   if (irqFlag)
   {
      irqFlag = 0;

      /* Check the Interrupt Vector to identify which device generated the interrupt */
      printf("\nReceived Vector: 0x%08X", receivedVector);

      /* If the vector value matches our channel... */
      if (receivedVector == (INTERRUPT_VECTOR_ADDEND + channel))
      {
         /* Read to clear status registers */
         status = naibrd_1553_GetIntStatus(devnum, &intStatus1, &intStatus2);

         /* Clear Latch Bit */
         status = naibrd_1553_ClearIntLatch(devnum);

         /* Check if this is a BC End of Message interrupt */
         if (intStatus1 & NAI_1553_INT_STS_REG1_MASK_BC_CONTROL_WORD_END_OF_MESSAGE)
         {
            printf("\nBC End Of Message (EOM) interrupt triggered. IrqCount = %d\n", irqCount);

            /* Check each message for completion */
            for (msgIdx = 0; msgIdx < NUM_MSGS; msgIdx++)
            {
               status = naibrd_1553_BcMessageGetByIdDecoded(devnum, msgList[msgIdx],
                  &DecodedMsgStruct, 1);
               if (status == 1)
               {
                  /* Message complete -- display results */
                  printf("Control Word: 0x%04X\n", DecodedMsgStruct.wBcControlWord);
                  printf("Command Word: 0x%04X\n", DecodedMsgStruct.wCommandWord1);
                  printf("Block Status: 0x%04X\n", DecodedMsgStruct.wBlockStatus);
                  printf("Time Tag: 0x%04X\n", DecodedMsgStruct.wTimeTag);
                  printf("Word Count: 0x%04X\n", DecodedMsgStruct.wDataWordCount);
                  printf("RT Status Word: 0x%04X\n", DecodedMsgStruct.wStatus1);
                  printf("Data:");
                  for (i = 0; i < DecodedMsgStruct.wDataWordCount; i++)
                  {
                     if (i % 8 == 0)
                        printf("\n");
                     printf("0x%04X ", DecodedMsgStruct.waData[i]);
                  }
                  printf("\n\n");
               }
            }
         }
         else
         {
            printf("\nOther interrupt triggered. status1=0x%04X status2=0x%04X IrqCount=%d\n",
               intStatus1, intStatus2, irqCount);
         }
      }
      else
      {
         printf("\n0x%08X is NOT my interrupt vector!\n", receivedVector);
      }
   }

   nai_msDelay(10);
   counter--;
}

The processing flow for each interrupt is:

  1. Clear the flag — set irqFlag back to 0 so the next interrupt can be detected.

  2. Verify the vector — compare receivedVector against the expected value (0xA0 + channel). If it does not match, the interrupt was generated by a different device on the same IRQ line.

  3. Read and clear status — call naibrd_1553_GetIntStatus() to read the two interrupt status registers (which also clears them due to auto-clear mode), then naibrd_1553_ClearIntLatch() to reset the module-level latch.

  4. Check the interrupt type — test intStatus1 against NAI_1553_INT_STS_REG1_MASK_BC_CONTROL_WORD_END_OF_MESSAGE to confirm this is an EOM interrupt.

  5. Decode completed messages — iterate through all messages in the schedule and call naibrd_1553_BcMessageGetByIdDecoded() for each. A return value of 1 means the message has completed since the last check. The naiDecodedMessageStructure provides the command word, block status, time tag, RT status word, and data payload.

Decoded Message Fields

When naibrd_1553_BcMessageGetByIdDecoded() returns 1 (message complete), the naiDecodedMessageStructure contains:

Field Description

wBcControlWord

The BC control word that was used when creating this message (bus selection, EOM interrupt enable, etc.).

wCommandWord1

The 1553 command word sent on the bus (RT address, subaddress, word count, T/R bit).

wBlockStatus

The BC’s record of what happened: message attempted, channel/retry status, error bits. Consult the FTA-FTF Manual for bit definitions.

wTimeTag

A hardware time stamp indicating when the message completed (in 0.1 ms units).

wDataWordCount

The number of 16-bit data words in the message payload.

wStatus1

The RT status word (if the RT responded). Contains message error, busy, service request, and other RT status bits.

waData[]

The data payload. For BC-to-RT messages, this is the data that was sent. For RT-to-BC messages, this is the data received from the RT.

Stopping the BC

After the 10-second run completes, the application stops the scheduler:

status = naibrd_1553_BcStop(devnum);

The application then offers the user the option to run the schedule again or quit. On quit, it frees the device:

status = naibrd_1553_Free(devnum);

Always call naibrd_1553_Free() when you are done with the device to release the logical device number and associated resources.

Important

Common Errors

  • Missed interrupts — if the main thread’s processing takes longer than the interval between EOM interrupts, some interrupt events may be coalesced (the flag is a single bit, not a queue). For high-rate schedules, consider using a dedicated interrupt processing thread or increasing the polling frequency.

  • Stale message data — naibrd_1553_BcMessageGetByIdDecoded() returns 1 only once per message completion. If you call it again before the next completion, it returns 0. Do not call it in a tight loop expecting repeated results.

  • No RT response — if no RT is connected or the RT address is wrong, the block status word will indicate "no response." The EOM interrupt still fires (the message transaction completed with a timeout), but the data will not be valid.

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, incorrect or missing configuration file, network issue

Verify hardware is powered and connected. If the configuration file exists, check interface and address. If not, configure and save from board menu.

Module not recognized as 1553

Selected module is not an FT-series or CM with 1553. IsFTx1553() returned false.

Verify the module type installed at the selected slot. Use the board menu to check module IDs.

Device open failure

Wrong card/module/channel combination, or device already opened by another application

Verify card index, module number, and channel number. Close any other application using this channel.

Initialization failure (BC mode)

BC_DISABLE pin preventing BC mode

Enable software override (WriteAuxReg(0x2, 0xA000)) to take control of BC_DISABLE and M1760 pins.

ISR never fires

Wrong interrupt steering constant, or using Ethernet connection (not supported for ISR interrupts)

Verify steering matches your connection type (cPCI, PCIe, or onboard). Use a direct bus connection.

ISR fires but vector does not match

Another device on the same IRQ line, or vector assignment does not match the expected value

Verify the vector value passed to naibrd_1553_SetIntVector() matches what the ISR checks. Ensure unique vectors across all channels.

EOM interrupt not triggered despite schedule running

NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED not set in message control word, or EOM mask not enabled

Verify the EOM flag is OR’d into the message control word at creation time. Verify naibrd_1553_SetIrqManipulate() is called with the correct mask.

No RT response (block status shows timeout)

RT not powered, wrong RT address, bus not connected, or bus not terminated

Verify RT is operational and address matches. Check physical bus connections and 120-ohm termination at both ends.

Missed interrupts / coalesced events

Main thread processing slower than interrupt rate; flag-based signaling loses events

Increase polling frequency, reduce per-interrupt processing time, or move interrupt handling to a dedicated thread.

Frame hierarchy error (BcStart fails)

Not all referenced opcodes, frames, messages, or data blocks were created before start

Create all components (data blocks, messages, opcodes, minor frames, major frame) before calling BcStart().

Wrong message rates

Minor frames arranged in wrong order in major frame

Verify the major frame sequence: MNR1 → MNR3 → MNR2 → MNR3. Each minor frame must contain the correct opcode subset.

BC_DISABLE pin preventing BC mode

External hardware signal blocking BC operation; software override not enabled

Set naibrd_1553_WriteAuxReg(devnum, 0x2, 0xA000) to override. See FTA-FTF Manual Miscellaneous Bits register.

Full Source

The complete source for this sample is provided below for reference. The sections above explain each part in detail.

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

#if defined (__VXWORKS__)
 #include "taskLib.h"
#endif
/* 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"
#include "BC/nai_1553_bc_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_REG1_MASK_BC_END_OF_MESSAGE	   /* NAI_1553_INT_REG1_MASK_TIME_TAG_ROLLOVER */	   /* NAI_1553_INT_REG1_MASK_BC_END_OF_MESSAGE */

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

/* Function prototypes */
static bool_t Run_M1553_BC_Interrupt(int32_t cardIndex, int32_t module, uint32_t modid);
static bool_t RunBCInterrupt(int32_t cardIndex, int32_t module, int32_t channel);
static void myIsr(void* param, uint32_t vector);

/* define message constants */
#define MSG1         1
#define MSG2         2
#define MSG3         3
#define NUM_MSGS     3

/* define opcodes */
#define OP1          1
#define OP2          2
#define OP3          3
#define OP4          4
#define OP5          5
#define OP6          6

/* define frame constants */
#define MNR1         1
#define MNR2         2
#define MNR3         3
#define MJR          4

/* define data block numbers */
#define DBLK1        1
#define DBLK2        2
#define DBLK3        3

#define DEF_M1553_CARD_INDEX                 0
#define DEF_M1553_MODULE                     1
#define DEF_M1553_CHANNEL                    1
#define DEF_M1553_DEVNUM                     1

#define RT_ADDRESS                           1

#define RT_SUBADDRESS1                       1  /* Subaddress for Message 1 */
#define RT_SUBADDRESS2                       2  /* Subaddress for Message 2 */
#define RT_SUBADDRESS3                       8  /* Subaddress for Message 3 */

#define WORDCOUNT1                           11 /* Data Word count for Message 1 */
#define WORDCOUNT2                           21 /* Data Word count for Message 2 */
#define WORDCOUNT3                           30 /* Data Word count for Message 3 */

/* Global Variables */
static volatile int32_t irqFlag;
static int32_t irqCount;
static uint32_t receivedVector;

/**************************************************************************************************************/
/**
<summary>
The purpose of the M1553_BC_Interrupt is to illustrate the methods to call in the naibrd library to configure
the 1553 channel as a Bus Controller and to send various messages at different periodic rates. Specifically,
Message 1 is sent at a rate of 4 Hz (every 250 ms), Message 2 is sent at a rate of 2 Hz (every 500 ms) and
Message 3 is sent at a rate of 1 Hz (every 1000 ms). Three 250 ms minor frames are used to manage the periodicity
of these messages. Minor Frame 1 contains Messages 1, 2 and 3. Minor Frame 2 contains Messages 1 and 2 only. Minor
Frame 3 only contains Message 1. By chaining these frames together in the following order:

Minor Frame 1 | Minor Frame 3 | Minor Frame 2 | Minor Frame 3

Message 1 is sent every 250 ms, Message 2 is sent every 500 ms and Message 3 is sent every 1000 ms.

This application also demonstrates configuration and utilization of interrupts to signal the host processor
whenever a 1553 message is sent out. The interrupt service callback routine sets a global flag to indicate a BC
end-of-message interrupt has been generated by the BC channel. When this occurs, the while loop in the main thread
checks each 1553 message in the schedule to see if it was sent out. (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_BC_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_BC_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_BC_Interrupt(int32_t cardIndex, int32_t module, uint32_t modid)
{
   bool_t bQuit = FALSE;
   int32_t channel;
   int32_t MaxChannel = 4;

   if (IsFTx1553(modid))
   {
      MaxChannel = 4;
      bQuit = naiapp_query_ChannelNumber(MaxChannel, DEF_M1553_CHANNEL, &channel);
      if (!bQuit)
      {
         bQuit = RunBCInterrupt(cardIndex, module, channel);
      }
   }
   else
      printf("\nThis module does not support 1553 functionality.\n");

   return bQuit;
}

static bool_t RunBCInterrupt(int32_t cardIndex, int32_t module, int32_t channel)
{
   int32_t i;
   bool_t bQuit = FALSE;
   uint32_t usBus;
   nai_1553_t status;
   uint16_t increment = 0;
   uint16_t aData[32] = {0};
   int16_t aOpCodes[20] = { 0 };
   bool_t bContinue = TRUE;
   int16_t devnum;
   naiDecodedMessageStructure DecodedMsgStruct;
   bool_t bSoftware;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
   uint16_t intStatus1, intStatus2;
   int32_t counter = 1000;
   int16_t msgList[NUM_MSGS] = {MSG1, MSG2, MSG3};
   int32_t msgIdx;

   /* Get the Logical Device Number */
   bQuit = Get1553LogicalDevNum(DEF_M1553_DEVNUM, &devnum);
   if (!bQuit)
   {
      /* Which bus are we firing on? */
      bQuit = GetBus(&usBus);
      if (!bQuit)
      {
         bQuit = Get1553BCSoftwareOverride(TRUE, &bSoftware);
         if (!bQuit)
         {
            /* Open 1553 Device(s) */
            status = naibrd_1553_Open(cardIndex, module, channel, devnum);
            if(status != 0)
            {
               printf("Error: naibrd_1553_Open Ch %d, status = %d", channel, status);
               return TRUE;
            }

            if (bSoftware)
            {
               /* Override external BC_DISABLE and M1760 (In order to configure as BC, this needs to */
               /* be set if BC_DISABLE and M1760 pins are not driven high) */
               naibrd_1553_WriteAuxReg(devnum, 0x2, 0xA000);
            }
            else
            {
               /* Do not override external BC_DISABLE and M1760 Inputs */
               naibrd_1553_WriteAuxReg(devnum, 0x2, 0);
            }

            /* Reset Device */
            naibrd_1553_WriteAuxReg(devnum, 0x1, 1);
            nai_msDelay(1);
            naibrd_1553_WriteAuxReg(devnum, 0x1, 0);

            /* Initialize 1553 Device(s) */
            status = naibrd_1553_Initialize(devnum, NAI_1553_ACCESS_CARD,NAI_1553_MODE_BC,0,0,0);
            if(status != 0)
            {
               printf("Error: naibrd_1553_Initialize Ch %d, status = %d", channel, status);
               return TRUE;
            }

            /***********************/
            /*** INTERRUPT SETUP ***/
            /***********************/
            /* Reset Interrupt counter */
            irqCount = 0;

            /* Setup Interrupts in Core with Level Detection and Auto Clear (read clears interrupt statuses) */
            status = naibrd_1553_SetIrqConfig(devnum, NAI_1553_IRQ_MODE_LEVEL, NAI_1553_IRQ_AUTO_CLEAR);
            if(status != 0)
            {
               bQuit = TRUE;
               printf("Error: naibrd_1553_SetIrqConfig  %d", status);
               return bQuit;
            }

            /* Hook the interrupt service routine */
            status = 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(status != 0)
            {
               bQuit = TRUE;
               printf("Error: naibrd_InstallISR  %d", status);
               return bQuit;
            }

            /* Set the Interrupt Steering to Onboard */
            status = 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(status != 0)
            {
               bQuit = TRUE;
               printf("Error: naibrd_1553_SetInterruptSteering  %d", status);
               return bQuit;
            }

            /* Associate the device with a unique interrupt vector (The vector can be any    */
            /* value between 0x01 and 0xFF). In this case, we use an arbitrary value given   */
            /* by INTERRUPT_VECTOR_ADDEND plus the BC channel number. If more than one       */
            /* channel is used in a system, the assigned vector values should be different   */
            /* across all channels so they are uniquely identified.                          */
            status = naibrd_1553_SetIntVector( devnum, INTERRUPT_VECTOR_ADDEND + channel );
            if(status != 0)
            {
               bQuit = TRUE;
               printf("Error: naibrd_1553_SetIntVector  %d", status);
               return bQuit;
            }

            /* Read core status registers to clear statuses */
            status = naibrd_1553_GetIntStatus(devnum, &intStatus1, &intStatus2);
            if(status != 0)
            {
               bQuit = TRUE;
               printf("Error: naibrd_1553_GetIntStatus  %d", status);
               return bQuit;
            }

            /* Clear Interrupt Latch Bit */
            status = naibrd_1553_ClearIntLatch(devnum);
            if(status != 0)
            {
               bQuit = TRUE;
               printf("Error: naibrd_1553_ClearIntLatch  %d", status);
               return bQuit;
            }

            /*************************/
            /*** BC SCHEDULE SETUP ***/
            /*************************/
            /* Create BC Data Block 1 */
            status = naibrd_1553_BcDataBlockCreate(devnum, DBLK1, NAI_1553_BC_DATABLOCK_SINGLE, NULL, 0);
            if(status != 0)
            {
               printf("Error: naibrd_1553_BcDataBlockCreate Ch %d, status = %d", channel, status);
               return TRUE;
            }

            /* Create BC Data Block 2 */
            status = naibrd_1553_BcDataBlockCreate(devnum, DBLK2, NAI_1553_BC_DATABLOCK_SINGLE, NULL, 0);
            if(status != 0)
            {
               printf("Error: naibrd_1553_BcDataBlockCreate Ch %d, status = %d", channel, status);
               return TRUE;
            }

            /* Create BC Data Block 3 */
            status = naibrd_1553_BcDataBlockCreate(devnum, DBLK3, NAI_1553_BC_DATABLOCK_SINGLE, NULL, 0);
            if(status != 0)
            {
               printf("Error: naibrd_1553_BcDataBlockCreate Ch %d, status = %d", channel, status);
               return TRUE;
            }

            /* Create BC to RT Message 1 */
            status = naibrd_1553_BcMessageCreateBcToRt(devnum, MSG1, DBLK1, RT_ADDRESS, RT_SUBADDRESS1, WORDCOUNT1, 0, usBus | NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcMessageCreateBcToRt status = %d", status);
               return TRUE;
            }

            /* Create RT to BC Message 2 */
            status = naibrd_1553_BcMessageCreateRtToBc(devnum, MSG2, DBLK2, RT_ADDRESS, RT_SUBADDRESS2, WORDCOUNT2, 0, usBus | NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcMessageCreateRtToBc status = %d", status);
               return TRUE;
            }

            /* Create BC to RT Message 3 */
            status = naibrd_1553_BcMessageCreateBcToRt(devnum, MSG3, DBLK3, RT_ADDRESS, RT_SUBADDRESS3, WORDCOUNT3, 0, usBus | NAI_1553_BC_CTRL_END_OF_MESSAGE_INTERRUPT_ENABLED);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcMessageCreateBcToRt status = %d", status);
               return TRUE;
            }

            /* Create Execute Message Command 1 */
            status = naibrd_1553_BcCommandCreate(devnum, OP1, NAI_1553_OPCODE_EXECUTE_MESSAGE, NAI_1553_OPCODE_COND_ALWAYS, MSG1, 0, 0);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcCommandCreate status = %d", status);
               return TRUE;
            }

            /* Create Execute Message Command 2 */
            status = naibrd_1553_BcCommandCreate(devnum, OP2, NAI_1553_OPCODE_EXECUTE_MESSAGE, NAI_1553_OPCODE_COND_ALWAYS, MSG2, 0, 0);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcCommandCreate status = %d", status);
               return TRUE;
            }

            /* Create Execute Message Command 3 */
            status = naibrd_1553_BcCommandCreate(devnum, OP3, NAI_1553_OPCODE_EXECUTE_MESSAGE, NAI_1553_OPCODE_COND_ALWAYS, MSG3, 0, 0);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcCommandCreate status = %d", status);
               return TRUE;
            }

            /* Create Minor Frame 1 */
            aOpCodes[0] = OP1;      /* Execute Message 1 Command */
            aOpCodes[1] = OP2;      /* Execute Message 2 Command */
            aOpCodes[2] = OP3;      /* Execute Message 3 Command */
            status = naibrd_1553_BcFrameCreate(devnum, MNR1, NAI_1553_BC_FRAME_MINOR, aOpCodes, 3, 2500, 0);     /* 2500 for 250 ms minor frame (1 unit is 0.1 ms) */
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcFrameCreate status = %d", status);
               return TRUE;
            }

            /* Create Minor Frame 2 */
            aOpCodes[0] = OP1;      /* Execute Message 1 Command */
            aOpCodes[1] = OP2;      /* Execute Message 2 Command */
            status = naibrd_1553_BcFrameCreate(devnum, MNR2, NAI_1553_BC_FRAME_MINOR, aOpCodes, 2, 2500, 0);     /* 2500 for 250 ms frame */
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcFrameCreate status = %d", status);
               return TRUE;
            }

            /* Create Minor Frame 3 */
            aOpCodes[0] = OP1;      /* Execute Message 1 Command */
            status = naibrd_1553_BcFrameCreate(devnum, MNR3, NAI_1553_BC_FRAME_MINOR, aOpCodes, 1, 2500, 0);     /* 2500 for 250 ms frame */
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcFrameCreate status = %d", status);
               return TRUE;
            }

            /* Create Call Subroutine Command 1 */
            status = naibrd_1553_BcCommandCreate(devnum, OP4, NAI_1553_OPCODE_CALL_SUBROUTINE, NAI_1553_OPCODE_COND_ALWAYS, MNR1, 0, 0);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcCommandCreate status = %d", status);
               return TRUE;
            }

            /* Create Call Subroutine Command 2 */
            status = naibrd_1553_BcCommandCreate(devnum, OP5, NAI_1553_OPCODE_CALL_SUBROUTINE, NAI_1553_OPCODE_COND_ALWAYS, MNR2, 0, 0);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcCommandCreate status = %d", status);
               return TRUE;
            }

            /* Create Call Subroutine Command 3 */
            status = naibrd_1553_BcCommandCreate(devnum, OP6, NAI_1553_OPCODE_CALL_SUBROUTINE, NAI_1553_OPCODE_COND_ALWAYS, MNR3, 0, 0);
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcCommandCreate status = %d", status);
               return TRUE;
            }

            /* Create Major Frame */
            aOpCodes[0] = OP4;   /* Minor Frame 1 */
            aOpCodes[1] = OP6;   /* Minor Frame 3 */
            aOpCodes[2] = OP5;   /* Minor Frame 2 */
            aOpCodes[3] = OP6;   /* Minor Frame 3 */
            status = naibrd_1553_BcFrameCreate(devnum,MJR,NAI_1553_BC_FRAME_MAJOR,aOpCodes,4,0,0); /* If frameTime is set here to a value */
                                                                                                   /* other than zero, this value will    */
                                                                                                   /* override the minor frame times that */
                                                                                                   /* were set using the _BcFrameCreate() */
                                                                                                   /* function and set all minor frame    */
                                                                                                   /* times to the same duration.         */
            if (status != 0)
            {
               printf("Error: naibrd_1553_BcFrameCreate status = %d", status);
               return TRUE;
            }

            while (bContinue)
            {
               /* Load BC data block 1 with incremental data */
               for (i = 0; i < WORDCOUNT1; i++)
               {
                  aData[i] = increment++;
               }
               status = naibrd_1553_BcDataBlockWrite(devnum, DBLK1, aData, WORDCOUNT1, 0);
               if (status != 0)
               {
                  printf("Error: naibrd_1553_BcDataBlockWrite status = %d", status);
                  return TRUE;
               }

               /* Load BC data block 3 with 0xBBCC */
               for (i = 0; i < WORDCOUNT3; i++)
               {
                  aData[i] = 0xBBCC;
               }
               status = naibrd_1553_BcDataBlockWrite(devnum, DBLK3, aData, WORDCOUNT3, 0);
               if (status != 0)
               {
                  printf("Error: naibrd_1553_BcDataBlockWrite status = %d", status);
                  return TRUE;
               }

               /* Enable BC EOM Interrupts (myIsr is only used here for compatibility with DDC, it is not used in the function) */
               status = naibrd_1553_SetIrqManipulate(devnum, 0x1, INTERRUPT_TYPE_MASK, myIsr);
               if(status != 0)
               {
                  printf("Error: naibrd_1553_SetIrqManipulate  %d", status);
                  return TRUE;
               }

               /* Start BC */
               status = naibrd_1553_BcStart(devnum,MJR,NAI_1553_BC_FRAME_RUN_FOREVER);
               if (status != 0)
               {
                  printf("Error: naibrd_1553_BcStart status = %d", status);
                  return TRUE;
               }

               counter = 1000;

               printf("BC Running for approximately 10 seconds...\n");

               /* Run the schedule for approximately 10 seconds */
               while (counter > 0)
               {
                  if (irqFlag)
                  {
                     irqFlag = 0;

                     /* Check the Interrupt Vector to identify which device (1553 channel) generated the interrupt */
                     printf("\nReceived Vector: 0x%08X", receivedVector);

                     /* If the vector value matches the vector that we assigned to the BC channel... */
                     if (receivedVector == (INTERRUPT_VECTOR_ADDEND + channel))
                     {
                        /* Read to clear status registers */
                        status = naibrd_1553_GetIntStatus(devnum, &intStatus1, &intStatus2);
                        if (status != NAI_SUCCESS)
                        {
                           printf("\nERROR: naibrd_1553_GetIntStatus - %d\n", status);
                        }

                        /* Clear Latch Bit */
                        status = naibrd_1553_ClearIntLatch(devnum);
                        if (status != NAI_SUCCESS)
                        {
                           printf("\nERROR: naibrd_1553_ClearIntLatch - %d\n", status);
                        }

                        /* If BC End of Message Interrupt triggered... */
                        if (intStatus1 & NAI_1553_INT_STS_REG1_MASK_BC_CONTROL_WORD_END_OF_MESSAGE)
                        {
                           printf("\nBC End Of Message (EOM) interrupt triggered. IrqCount = %d\n", irqCount);

                           /* The BC schedule contains three messages (MSG1, MSG2, MSG3). Check which message(s) have been sent (EOM). */
                           for (msgIdx = 0; msgIdx < NUM_MSGS; msgIdx++)
                           {
                              /* Call this function to check message complete on each message (MSG1, MSG2, MSG3). */
                              status = naibrd_1553_BcMessageGetByIdDecoded(devnum, msgList[msgIdx], &DecodedMsgStruct, 1);
                              if (status == 1)
                              {
                                 /* Message complete. Display Message information, including 1553 data. */
                                 printf("Control Word: 0x%04X\n", DecodedMsgStruct.wBcControlWord);
                                 printf("Command Word: 0x%04X\n", DecodedMsgStruct.wCommandWord1);
                                 printf("Block Status: 0x%04X\n", DecodedMsgStruct.wBlockStatus);
                                 printf("Time Tag: 0x%04X\n", DecodedMsgStruct.wTimeTag);
                                 printf("Word Count: 0x%04X\n", DecodedMsgStruct.wDataWordCount);
                                 printf("RT Status Word: 0x%04X\n", DecodedMsgStruct.wStatus1);
                                 printf("Data:");
                                 for (i = 0; i < DecodedMsgStruct.wDataWordCount; i++)
                                 {
                                    if (i % 8 == 0)
                                    {
                                       printf("\n");
                                    }
                                    printf("0x%04X ", DecodedMsgStruct.waData[i]);
                                 }
                                 printf("\n\n");
                              }
                           }
                        }
                        /* If interrupt was NOT BC End of Message Interrupt... */
                        else
                        {
                           printf("\nOther interrupt triggered. status1=0x%04X status2=0x%04X IrqCount=%d\n", intStatus1, intStatus2, irqCount);
                        }
                     }
                     else
                     {
                        printf("\n0x%08X is NOT my interrupt vector!\n", receivedVector);
                     }
                  }

                  nai_msDelay(10);
                  counter--;
               }

               /* Stop BC (This call is not necessary here since transmission of the major frame should have completed by now) */
               status = naibrd_1553_BcStop(devnum);
               if (status != 0)
               {
                  printf("Error: naibrd_1553_BcStop status = %d", status);
                  return TRUE;
               }

               printf("BC Halted.\n");

               printf("\nPress any key to run the BC schedule again or Q to quit.");
               bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
               if (bQuit)
               {
                  bContinue = FALSE;
               }
            }
         }
      }
   }

   /* Free 1553 Device */
   status = naibrd_1553_Free(devnum);
   if (status != 0)
   {
      printf("Error: naibrd_1553_Free status = %d", status);
      return TRUE;
   }

   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\n", vector, 1, 2, 3, 4, 5);
   /* Clear Interrupt */
   nai_Onboard_ClearInterrupt();
#endif

   receivedVector = vector;

   /* Set the global interrupt flag */
   irqFlag = 1;
   irqCount++;
}

Help Bot

X