M1553 RT HBuff Interrupt
Edit this on GitLab
M1553 RT HBuff Interrupt
Explanation
About the Sample Application Code for NAI Embedded Function Modules
This sample application code, written in C, demonstrates how to configure and interact with North Atlantic Industries (NAI) embedded function modules. Specifically, this application configures a 1553 channel as a Remote Terminal, sets up Host Buffers, and enables interrupts for end-of-message events.
Code Overview
The application utilizes various NAI-specific libraries and functions to interact with the hardware. It allows for querying the user for various input parameters and processes incoming 1553 messages, displaying them in the console.
Header Files
The application includes several common and specific header files:
- naiapp_interrupt.h
- naiapp_interrupt_ether.h
- naiapp_boardaccess_menu.h
- naiapp_boardaccess_query.h
- naiapp_boardaccess_access.h
- naiapp_boardaccess_display.h
- naiapp_boardaccess_utils.h
- nai_1553_utils.h
- nai.h
- naibrd.h
- naibrd_1553.h
Constants and Definitions
Key constants and definitions used throughout the application:
- INTERRUPT_VECTOR_ADDEND
: Offset added to the channel number to create an interrupt vector.
- INTERRUPT_TYPE_MASK
: Mask defining end-of-message interrupt type.
- CONFIG_FILE
: Configuration file used by the application.
- Data Block IDs and default parameters for the Remote Terminal.
Global Variables
Global variables used include:
- currDataBlock
: Represents the current data block ID.
- deviceNumber
: Logical device number.
- irqFlag
: Indicates if an interrupt has occurred.
- irqCount
: Counts the number of interrupts.
- receivedVector
: Stores the received interrupt vector.
Main Function
The main logic is encapsulated in the main()
function, which sets up the application, queries user input, and initiates the execution loop.
Key Functions
Run_M1553_RT_Interrupt
This function configures the 1553 Remote Terminal and handles the interrupt setup. It performs the following tasks:
- Associates card and module numbers with a logical device number.
- Initializes the device.
- Configures interrupts, hooking an ISR (myIsr
) to handle them.
- Sets up data buffers for receiving and transmitting messages.
- Enters a loop to process incoming messages.
myIsr
This is the Interrupt Service Routine (ISR) that gets called when an interrupt occurs. It does the following:
- Clears the interrupt status.
- Handles data from the 1553 bus by calling naibrd_1553_RtStkToHbuf32
.
- Sets global flags to indicate an interrupt was serviced.
ProcessMessages
This function polls for messages within a specified duration. It does the following: - Checks for interrupts. - Retrieves and decodes 1553 messages. - Displays the decoded messages in the console. - Clears interrupt status and latch bits.
Additional Utility Functions
Other utility functions handle user input and configuration tasks:
- naiapp_query_CardIndex
- naibrd_GetModuleCount
- naiapp_query_ModuleNumber
- naibrd_GetModuleID
These functions query the user for necessary information such as card index, module number, and configure the device accordingly.
Functionality
The application configures the 1553 channel, sets up data buffers, and enables interrupts. It processes incoming 1553 messages, displaying relevant information in the console. It uses NAI-specific APIs to manage and interact with the hardware.
Conclusion
This sample code provides a comprehensive example of setting up and using NAI embedded function modules, specifically handling the 1553 protocol with interrupts. The provided comments and structure make it a useful reference for developers working with NAI hardware.
#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;
}