M1553 RT Recv FIFO
Edit this on GitLab
M1553 RT Recv FIFO Sample Application (SSK 2.x)
Overview
The M1553 RT Recv FIFO sample application demonstrates how to configure a MIL-STD-1553 channel as a Remote Terminal (RT) and receive messages using Message FIFO mode with the NAI Software Support Kit (SSK 2.x). This sample is functionally similar to the standard RT Recv sample, but uses the hardware FIFO to capture and decode messages instead of the RT command stack.
The application configures a channel as an RT in FIFO mode, legalizes a user-selected subaddress for Tx, Rx, and Broadcast messages, and sets up double-buffered Rx data blocks and two alternating Tx data blocks. While the RT is running, it periodically reads the FIFO for new messages and updates Tx buffer data. An optional internal loopback test verifies hardware operation before starting.
|
Note
|
FIFO mode is available for the FTA-FTF modules only. |
For detailed 1553 protocol specifications, message formats, and hardware register descriptions, see the FTA-FTF Manual.
For the SSK 1.x version, see M1553 RT Receive FIFO (SSK 1.x).
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with a 1553 module installed (FTA-FTF).
-
SSK 2.x installed on your development host.
-
The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.
-
A Bus Controller on the same 1553 bus to send commands to this RT.
How to Run
Launch the m1553_rt_recv_fifo executable from your build output directory. On startup the application looks for a configuration file (default_1553_rt_recv_fifo.txt). Once connected, the application prompts for RT channel, RT address, subaddress, logical device number, and RT address source. It runs an optional internal loopback test, then enters a loop where the user specifies a duration for the RT to run.
Board Connection and Module Selection
|
Note
|
This startup sequence is common to all NAI sample applications. |
The main() function follows the standard SSK 2.x startup flow: board menu, card index query, module selection, and module ID retrieval.
|
Important
|
Common Connection Errors
|
Program Structure
RT Initialization in FIFO Mode
result = naibrd_1553_Init(DevNum, NAIBRD_1553_ACCESS_CARD,
NAIBRD_1553_MODE_RT | NAIBRD_1553_MESSAGE_FIFO_MODE, 0, 0, 0);
Optional Internal Loopback Test
Before starting, the sample runs an internal loopback test to verify hardware:
result = naibrd_1553_InternalLoopback(cardIndex, module, rtchan, &busAPassed, &busBPassed);
naiif_printf("Bus A Internal Loopback Test %s\r\n", busAPassed ? "PASSED" : "FAILED");
naiif_printf("Bus B Internal Loopback Test %s\r\n", busBPassed ? "PASSED" : "FAILED");
Processing Messages via FIFO
The ProcessMessages() function polls the FIFO every 10 ms:
result = naibrd_1553_GetMsgFIFOCount(DevNum, &fifoCount);
if (fifoCount > 0)
{
memset(fifoData, 0, sizeof(fifoData));
result = naibrd_1553_ReadMsgFIFO(DevNum, fifoCount, fifoData);
do
{
result = naibrd_1553_DecodeFIFOMsg(fifoData, currBlockIndex, &nextBlockIndex, &DecodedMsgStruct);
if (result == 0)
{
/* Check command word bit 10 for Rx vs Tx */
if ((DecodedMsgStruct.commandWord1 & 0x0400) != 0x0400)
/* Rx message -- display data */
else
/* Tx message -- display info */
}
currBlockIndex = nextBlockIndex;
} while (result == NAI_SUCCESS);
}
The decoded message type uses naibrd_1553_msgstructFIFO_t instead of naibrd_1553_msgstruct_t used in the non-FIFO RT sample.
Troubleshooting Reference
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
|
Channel already open, invalid indices |
Verify indices, ensure no other application holds the channel |
FIFO mode not supported |
Module is FTJ/FTK (1760) |
FIFO mode is only available on FTA-FTF modules |
Internal loopback test fails |
Hardware fault, module not properly seated |
Reseat the module, verify power supply |
FIFO full during operation |
High message rate from BC |
Reduce BC message rate or poll FIFO more frequently |
RT does not respond to BC |
Wrong RT address, subaddress not legalized |
Verify RT address matches BC target, check subaddress mapping |
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_recv_fifo.c (SSK 2.x)
/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"
/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_1553.h"
#include "nai_libs/naibrd/include/functions/naibrd_1553_assisted.h"
#include "nai_libs/naibrd/include/functions/naibrd_1553_1760_status.h"
/* naiif include files */
#include "nai_libs/naiif/include/naiif.h"
#include "nai_libs/naiif/include/naiif_stdio.h"
/* Common Sample Program include files */
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_menu.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_query.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_access.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_display.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_utils.h"
/* Common 1553 Sample Program include files */
#include "nai_sample_apps/naiapp_src/board_modules/1553/m1553_common_utils/m1553_common_utils.h"
static const int8_t *DEF_CONFIG_FILE = (int8_t *)"default_1553_rt_recv_fifo.txt";
/* Function prototypes */
static bool_t Run_M1553_RT_Receive_FIFO(int32_t cardIndex, int32_t module, uint32_t modid);
static int32_t UpdateTxDataBlock(uint16_t DevNum, naibrd_1553_rt_subaddress_t Subaddress);
static int32_t UpdateTxBuffer(uint16_t DevNum, uint16_t nDataBlkID);
static int32_t ProcessMessages(uint16_t DevNum, naibrd_1553_rt_subaddress_t Subaddress, int32_t duration);
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 uint16_t DATA_BLOCK_ID_BCST = 4;
static const int32_t DEF_RT_CHANNEL = 1;
static const int16_t DEF_RT_DEV_NUM = 1;
static const uint16_t DEF_RT_ADDRESS = 1;
static const uint16_t DEF_RT_SUBADDR = 2;
static const uint16_t RTBC_WORDCNT = 32;
/* Global Variables */
static int32_t currDataBlock;
/**************************************************************************************************************/
/** \defgroup M1553_RT_Receive_FIFO
\brief This sample application demonstrates how to configure a channel as a Remote Terminal and receive messages in FIFO mode.
The purpose of the M1553_RT_Receive_FIFO is to illustrate the methods to call in the naibrd library to configure
the 1553 channel as a Remote Terminal, legalize Subaddress 2 for Tx, Rx and Broadcast messages, and set it
up to receive data using double buffers and transmit data from two alternating Tx buffers (active and
inactive). If a Rx message is received, the received data and message information will be displayed via
message FIFO. If a Tx message is received, the data in the active Tx buffer will be sent to the bus. While
the RT is running, Tx buffer data will be updated periodically by incrementing all 32 data words of Tx data.
If a Tx message is received, the message information will be displayed via message FIFO.
Note: FIFO mode is available for the FTA-FTF only.
The main steps include:
- Querying the user for the card index and module number.
- Configuring the channel for Remote Terminal functionality in FIFO mode.
- Starting the RT to start receiving messages.
- Displaying any messages received by the RT, while periodically updating the TX buffer.
*/
/**************************************************************************************************************/
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t m1553_rt_recv_fifo(void)
#else
int32_t main(void)
#endif
{
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
bool_t stop = NAI_FALSE;
uint32_t moduleID = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == (bool_t)NAI_TRUE)
{
while (stop != NAI_TRUE)
{
/* Select Card Index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Select Module */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
if (stop != NAI_TRUE)
{
check_status(naibrd_GetModuleName(cardIndex, module, &moduleID));
if ((moduleID != 0))
{
Run_M1553_RT_Receive_FIFO(cardIndex, module, moduleID);
}
}
}
naiif_printf("\r\nType Q to quit or Enter key to restart application:\r\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
naiif_printf("\r\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_Receive_FIFO(int32_t cardIndex, int32_t module, uint32_t modid)
{
/* Variables */
bool_t bQuit = NAI_FALSE;
int32_t rtchan;
naibrd_1553_rt_address_t rtaddr;
naibrd_1553_rt_subaddress_t sa = DEF_RT_SUBADDR;
uint16_t DevNum = 0;
int32_t result;
bool_t bContinue = NAI_TRUE;
int32_t duration;
bool_t bSoftwareRTAddr;
bool_t busAPassed, busBPassed;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
/* Get Card, Module, Channel Numbers and Open a Handle */
bQuit = Get1553RTCfg(modid, DEF_RT_CHANNEL, DEF_RT_ADDRESS, &rtchan, &rtaddr);
if (bQuit)
{
return bQuit;
}
naiif_printf("Enter Subaddress\r\n");
bQuit = Get1553Address(NAIBRD_1553_RT_SA_31_MODECODE, DEF_RT_SUBADDR, &sa);
/* Get Logical Device # */
bQuit = Get1553LogicalDevNum(DEF_RT_DEV_NUM, (int16_t*)&DevNum);
if (bQuit)
{
return bQuit;
}
/* OPTIONAL: Loopback Test to verify hardware operation */
result = naibrd_1553_InternalLoopback(cardIndex, module, rtchan, &busAPassed, &busBPassed);
if (result == NAI_SUCCESS)
{
naiif_printf("Bus A Internal Loopback Test %s\r\n", busAPassed ? "PASSED" : "FAILED");
naiif_printf("Bus B Internal Loopback Test %s\r\n", busBPassed ? "PASSED" : "FAILED");
}
/* Associate Card, Module and Channel Numbers with the Logical Device # */
result = naibrd_1553_Open(cardIndex, module, rtchan, DevNum);
if (result)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_Open %d", result);
return bQuit;
}
/* Initialize Device */
result = naibrd_1553_Init(DevNum, NAIBRD_1553_ACCESS_CARD, NAIBRD_1553_MODE_RT | NAIBRD_1553_MESSAGE_FIFO_MODE, 0, 0, 0);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_Init %d", result);
return bQuit;
}
/* Get RT Address Source from user */
bQuit = Get1553RTAddressSource(NAI_TRUE, &bSoftwareRTAddr);
if (bQuit)
{
return bQuit;
}
if (bSoftwareRTAddr)
{
/* Set RTAD_SW_EN and RT_ADR_LAT in software */
result = naibrd_1553_WriteAuxRegister(DevNum, NAIBRD_1553_AUX_ADDRESS_MISC_BITS, 0x0018);
result = naibrd_1553_RtSetAddrSrc(DevNum, NAIBRD_1553_RT_ADDR_SOURCE_INTERNAL);
/* Set RT address */
result = naibrd_1553_RtSetAddr(DevNum, rtaddr);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtSetAddr %d", result);
return bQuit;
}
}
else
{
/* Unset RTAD_SW_EN and set RT_ADR_LAT in software */
result = naibrd_1553_WriteAuxRegister(DevNum, NAIBRD_1553_AUX_ADDRESS_MISC_BITS, 0x0008);
result = naibrd_1553_RtSetAddrSrc(DevNum, NAIBRD_1553_RT_ADDR_SOURCE_EXTERNAL);
}
if (modid == NAIBRD_MODULE_ID_FT8)
{
/* Simplex Enable (for internal NAI testing only, do not enable) */
/*naibrd_1553_WriteAuxRegister(DevNum, 0x3, 0x4000);*/
/*naibrd_1553_WriteAuxRegister(DevNum, 0xF, 0x1);*/
}
/* Create a Rx Buffer data block and map to the desired subaddress */
result = naibrd_1553_RtDataBlkCreate(DevNum, DATA_BLOCK_ID_RX, NAIBRD_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtDatBlkCreate %d", result);
return bQuit;
}
result = naibrd_1553_RtDataBlkMapToSA(DevNum, DATA_BLOCK_ID_RX, sa, NAIBRD_1553_RT_MESSAGE_TYPE_RX,
NAIBRD_1553_RT_DATABLOCK_IRQ_NONE, 1);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtDatBlkMapToSA %d", result);
return bQuit;
}
/* Create a Broadcast Rx Buffer data block and map to the desired subaddress */
result = naibrd_1553_RtDataBlkCreate(DevNum, DATA_BLOCK_ID_BCST, NAIBRD_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtDatBlkCreate %d", result);
return bQuit;
}
result = naibrd_1553_RtDataBlkMapToSA(DevNum, DATA_BLOCK_ID_BCST, sa, NAIBRD_1553_RT_MESSAGE_TYPE_BROADCAST,
NAIBRD_1553_RT_DATABLOCK_IRQ_NONE, 1);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtDatBlkMapToSA %d", result);
return bQuit;
}
/* Create two Tx Buffer data blocks and map the first to the desired subaddress */
result = naibrd_1553_RtDataBlkCreate(DevNum, DATA_BLOCK_ID_TX1, NAIBRD_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtDatBlkCreate %d", result);
return bQuit;
}
result = naibrd_1553_RtDataBlkCreate(DevNum, DATA_BLOCK_ID_TX2, NAIBRD_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtDatBlkCreate %d", result);
return bQuit;
}
result = naibrd_1553_RtDataBlkMapToSA(DevNum, DATA_BLOCK_ID_TX1, sa, NAIBRD_1553_RT_MESSAGE_TYPE_TX,
NAIBRD_1553_RT_DATABLOCK_IRQ_NONE, 1);
if (result < 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtDatBlkMapToSA %d", result);
return bQuit;
}
currDataBlock = DATA_BLOCK_ID_TX1;
while (bContinue)
{
naiif_printf("\r\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);
}
result = naibrd_1553_ClearMsgFIFO(DevNum);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_ClearMsgFIFO %d", result);
return bQuit;
}
/* Start RT */
result = naibrd_1553_RtStart(DevNum);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtStart %d", result);
return bQuit;
}
/* Process New Messages */
ProcessMessages(DevNum, sa, duration);
/* Stop RT */
result = naibrd_1553_RtStop(DevNum);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_RtStop %d", result);
return bQuit;
}
}
else
bContinue = NAI_FALSE;
}
/* Free 1553 Device */
result = naibrd_1553_Free(DevNum);
if (result != 0)
{
bQuit = NAI_TRUE;
naiif_printf("Error: naibrd_1553_Free %d", result);
return bQuit;
}
return bQuit;
}
static int32_t UpdateTxDataBlock(uint16_t DevNum, naibrd_1553_rt_subaddress_t Subaddress)
{
/* Update Data in TX Data Block */
if (currDataBlock == DATA_BLOCK_ID_TX1)
{
UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX2);
/* Change data pointer to block 2 */
naibrd_1553_RtTxDataBlkSwap(DevNum, DATA_BLOCK_ID_TX2, Subaddress);
currDataBlock = DATA_BLOCK_ID_TX2;
}
else
{
UpdateTxBuffer(DevNum, DATA_BLOCK_ID_TX1);
/* Change data pointer to block 1 */
naibrd_1553_RtTxDataBlkSwap(DevNum, DATA_BLOCK_ID_TX1, Subaddress);
currDataBlock = DATA_BLOCK_ID_TX1;
}
return 0;
}
static int32_t ProcessMessages(uint16_t DevNum, naibrd_1553_rt_subaddress_t Subaddress, int32_t duration)
{
int32_t counter_mS = 0, end_mS = 0, period_mS = 0;
int32_t result;
int32_t i;
uint32_t fifoCount;
int32_t currBlockIndex = 0, nextBlockIndex = 0;
naibrd_1553_msgstructFIFO_t DecodedMsgStruct;
uint32_t fifoData[1024];
int32_t count = 0;
bool_t FIFOfullStatusBit;
end_mS = counter_mS + duration*1000;
period_mS = counter_mS + 1000;
while (counter_mS < end_mS)
{
/* Update Tx Data Block periodically */
if (counter_mS > period_mS)
{
UpdateTxDataBlock(DevNum, Subaddress);
period_mS = counter_mS + 1000;
}
result = naibrd_1553_GetMsgFIFOCount(DevNum, &fifoCount);
if (result != 0)
{
naiif_printf("Error: naibrd_1553_GetMsgFIFOCount %d", result);
return NAI_TRUE;
}
else
{
if (fifoCount > 0)
{
currBlockIndex = 0;
/* This is necessary because otherwise, fifoData array gets used over and over without getting zero'ed out. */
/* When the array gets decoded, old data may get decoded unintentionally */
memset(fifoData, 0, sizeof(fifoData));
/* Read Message FIFO */
result = naibrd_1553_ReadMsgFIFO(DevNum, fifoCount, fifoData);
if (result != 0)
{
naiif_printf("Error: naibrd_1553_ReadMsgFIFO %d", result);
return NAI_TRUE;
}
else
{
/* Read Messages */
do
{
result = naibrd_1553_DecodeFIFOMsg(fifoData, currBlockIndex, &nextBlockIndex, &DecodedMsgStruct);
if (result == 0)
{
if ((DecodedMsgStruct.commandWord1 & 0x0400) != 0x0400) /* If this is a Rx message */
{
naiif_printf("Rx Msg Received\r\n");
naiif_printf("\r\n\r\nDecoded Message:\r\n\r\n");
naiif_printf("Block Status - 0x%04X\r\n", DecodedMsgStruct.blockStatus);
naiif_printf("Time Tag - 0x%04X\r\n", DecodedMsgStruct.timeTag);
naiif_printf("Command Word - 0x%04X\r\n", DecodedMsgStruct.commandWord1);
naiif_printf("Data Word Count - 0x%04X\r\n", DecodedMsgStruct.dataWordCount);
naiif_printf((DecodedMsgStruct.dataWordCount > 0) ? ("Data:") : (""));
for (i = 0; i < DecodedMsgStruct.dataWordCount; i++)
{
if (i % 8 == 0)
{
naiif_printf("\r\n");
}
naiif_printf("0x%04X ", DecodedMsgStruct.data[i]);
}
naiif_printf("count: %d\r\n", count++);
naiif_printf("\r\n\r\n");
}
else
{
naiif_printf("Tx Msg Received\r\n");
naiif_printf("\r\n\r\nDecoded Message:\r\n\r\n");
naiif_printf("Block Status - 0x%04X\r\n", DecodedMsgStruct.blockStatus);
naiif_printf("Time Tag - 0x%04X\r\n", DecodedMsgStruct.timeTag);
naiif_printf("Command Word - 0x%04X\r\n", DecodedMsgStruct.commandWord1);
naiif_printf("Data Word Count - 0x%04X\r\n", DecodedMsgStruct.dataWordCount);
naiif_printf("count: %d\r\n", count++);
naiif_printf("\r\n\r\n");
}
}
else if(result != NAIBRD_1553_CMD_NO_MSG_TO_DECODE)
{
naiif_printf("Error: naibrd_1553_DecodeFIFOMsg %d", result);
return NAI_TRUE;
}
/*** IMPORTANT !!! ***/
currBlockIndex = nextBlockIndex;
naibrd_msDelay(1);
} while (result == NAI_SUCCESS);
}
result = naibrd_1553_GetMsgFIFOFullStatus(DevNum, NAIBRD_1553_STATUS_REALTIME, &FIFOfullStatusBit);
if (result == NAI_SUCCESS)
{
naiif_printf("FIFO status: %d", FIFOfullStatusBit);
naiif_printf((FIFOfullStatusBit == NAI_TRUE) ? " Full\r\n" : " Not full\r\n");
}
else
{
naiif_printf("Error: naibrd_1553_GetMsgFIFOFullStatus %d", result);
return NAI_TRUE;
}
}
}
naibrd_msDelay(10);
counter_mS += 10;
}
return 1;
}
static int32_t UpdateTxBuffer(uint16_t DevNum, uint16_t nDataBlkID)
{
static uint16_t wBuffer[32] = { 0x0000 };
uint16_t i = 0x0000;
uint32_t result;
/* Increment Tx buffer data */
for (i = 0; i < 32; i++)
{
wBuffer[i] += 1;
}
/* Write new data to Tx buffer */
result = naibrd_1553_RtDataBlkWrite(DevNum, nDataBlkID, wBuffer, RTBC_WORDCNT, 0);
if (result < 0)
{
naiif_printf("Error: naibrd_1553_RtDatBlkWrite %d\r\n\r\n", result);
return 0;
}
else
{
naiif_printf("New data written to Tx Buffer\r\n\r\n");
}
return 1;
}