M1760 RT Interrupt
Edit this on GitLab
M1760 RT Interrupt
Explanation
About This Code
This C application code is provided by North Atlantic Industries (NAI) as an example for interacting with their Embedded Function Modules, specifically utilizing the 1553 communication protocol. Below is a detailed explanation of the code.
Included Header Files
The code includes several header files necessary for its operation:
-
Standard Libraries:
stdio.h
,stdlib.h
,string.h
,time.h
-
NAI Application Includes:
-
naiapp_boardaccess_menu.h
,naiapp_boardaccess_query.h
,naiapp_boardaccess_access.h
,naiapp_boardaccess_display.h
,naiapp_boardaccess_utils.h
-
1553 Protocol Utilities:
nai_1553_utils.h
-
NAI Board Includes:
-
nai.h
,naibrd.h
-
Function-specific includes for
naibrd_1553.h
,naibrd_1760.h
Definitions
Several constants are defined for use within the program:
-
Interrupt Vector and Mask Definitions: Used to configure interrupt mechanisms.
c #define INTERRUPT_VECTOR_ADDEND 0xA0 #define INTERRUPT_TYPE_MASK_HW 0 #define INTERRUPT_TYPE_MASK_BC 0 #define INTERRUPT_TYPE_MASK_RT NAI_1760_RT_INTERRUPT_MASK_IWA1 #define INTERRUPT_TYPE_MASK_MT 0
-
Config File: Path to the configuration file.
c static const int8_t *CONFIG_FILE = (int8_t *)"default_1760_RTInterrupt.txt";
Function Prototypes
Prototypes for the functions used are declared to ensure the correct linkage:
static bool_t Run_M1760_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);
Global Variables
Several global variables are declared for maintaining state information:
static int32_t currDataBlock;
static int16_t deviceNumber;
static volatile int32_t irqFlag;
static int32_t irqCount;
static uint32_t receivedVector;
Main Function
The program entry point is either M1760_RT_Interrupt
or main
depending on the operating system defined (VXWORKS
for VxWorks):
#if defined (__VXWORKS__)
int32_t M1760_RT_Interrupt(void)
#else
int32_t main(void)
#endif
This main function performs the following:
1. Displays and runs the board menu using naiapp_RunBoardMenu()
.
2. Queries the user to get the card index and module number.
3. Calls Run_M1760_RT_Interrupt()
to configure and run the 1553 Remote Terminal (RT) with interrupt handling.
Main processes in Run_M1760_RT_Interrupt
:
- Device Setup:
Configures the 1553 device by obtaining the configuration from the user and calling appropriate NAI functions to initialize hardware and software.
- Interrupt Setup:
Configures and enables interrupts. Sets up interrupt vectors and hooks the ISR (Interrupt Service Routine).
-
Buffer Setup: Establishes buffers for RX and TX communications.
-
Running 1553 RT: Main loop where the RT runs, processes messages, and handles interrupts.
ISR (Interrupt Service Routine)
myIsr
is triggered by an interrupt and:
- Stores the interrupt vector.
- Sets a flag and increments a counter.
Message Processing
ProcessMessages
handles the messages received:
- Polls the RT for a duration.
- When an interrupt occurs, processes the message, decodes it, and displays the content.
This structured setup allows the application to configure and handle extensive 1553 protocol-based communication tasks efficiently, making it suitable for critical aerospace and defense applications.
Important Functions:
- naiapp_RunBoardMenu
: Starts the NAI board configuration menu.
- naiapp_query_CardIndex
, naiapp_query_ModuleNumber
, naiapp_query_ForQuitResponse
: User query functions.
- naibrd_1553_Open
, naibrd_1553_Initialize
, naibrd_1553_SetIrqConfig
, naibrd_InstallISR
, naibrd_1553_SetInterruptSteering
, naibrd_1553_SetIntVector
: Configuration functions.
- naibrd_1553_RtStart
, naibrd_1553_RtStop
: Start and stop the Remote Terminal.
- naibrd_1553_RtMessageGetFromStackRaw
, naibrd_1553_RtMessageDecodeRaw
: Message handling functions.
- naibrd_1553_ClearIntLatch
, naibrd_UninstallISR
, naibrd_1553_Free
: Cleanup functions.
This overview empowers users to understand, modify, and utilize the provided sample code effectively within their specific systems and requirements.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* Common 1553 Sample Program include files */
#include "nai_1553_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_1553.h"
#include "functions/naibrd_1760.h"
#define INTERRUPT_VECTOR_ADDEND 0xA0
#define INTERRUPT_TYPE_MASK_HW 0 /* NAI_1760_HARDWARE_INTERRUPT_MASK_RT1TTM */
#define INTERRUPT_TYPE_MASK_BC 0
#define INTERRUPT_TYPE_MASK_RT NAI_1760_RT_INTERRUPT_MASK_IWA1
#define INTERRUPT_TYPE_MASK_MT 0
static const int8_t *CONFIG_FILE = (int8_t *)"default_1760_RTInterrupt.txt";
/* Function prototypes */
static bool_t Run_M1760_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>
NOTE: This sample code is only intended to be used with FTJ/FTK modules. For FT[1-9] modules, please refer to
the M1553_RT_Interrupt sample code.
The purpose of the M1760_RT_Interrupt is to illustrate the methods to call in the naibrd library to configure
the 1553 channel as a Remote Terminal, legalize the user specified subaddress for both Tx and Rx, and set it up
with interrupts enabled such that when an "interrupt when accessed" 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_1760_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 M1760_RT_Interrupt(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t cardIndex;
int32_t moduleCnt;
int32_t module;
uint32_t moduleID = 0;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
/* Query the user for the card index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
/* Query the user for the module number */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
if (stop != TRUE)
{
moduleID = naibrd_GetModuleID(cardIndex, module);
if ((moduleID != 0))
{
Run_M1760_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_M1760_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;
bool_t bSoftwareRTAddr;
uint16_t hwstatus, rtstatus, bcstatus, mtstatus;
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_PULSE, 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, NULL); /* NAIBRD_IRQ_ID_ON_BOARD_0 for Onboard, NAIBRD_IRQ_ID_DONT_CARE for everything else */
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_InstallISR %d", swResult);
return bQuit;
}
/* Set the Interrupt Steering to Onboard */
swResult = naibrd_1553_SetInterruptSteering( DevNum, NAIBRD_INT_STEERING_ON_BOARD_0 ); /* NAIBRD_INT_STEERING_CPCI_APP, NAIBRD_INT_STEERING_PCIE_APP for PCIe, NAIBRD_INT_STEERING_ON_BOARD_0 for Onboard */
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetInterruptSteering %d", swResult);
return bQuit;
}
/* Set the Interrupt Vector (The vector is set as channel number plus 0xA0) */
swResult = naibrd_1553_SetIntVector( DevNum, INTERRUPT_VECTOR_ADDEND + rtchan );
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetIntVector %d", swResult);
return bQuit;
}
/* Read core status registers to clear statuses */
swResult = naibrd_1760_GetIntStatus(deviceNumber, &hwstatus, &bcstatus, &rtstatus, &mtstatus);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1760_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 */
swResult = naibrd_1760_SetIrqManipulate(DevNum, 0x1, INTERRUPT_TYPE_MASK_HW, INTERRUPT_TYPE_MASK_BC, INTERRUPT_TYPE_MASK_RT, INTERRUPT_TYPE_MASK_MT, NULL);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetIrqManipulate %d", swResult);
return bQuit;
}
/* Start RT */
swResult = naibrd_1553_RtStart(DevNum);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtStart %d", swResult);
return bQuit;
}
/* Process New Messages */
ProcessMessages(duration);
/* Stop RT */
swResult = naibrd_1553_RtStop(DevNum);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtStop %d", swResult);
return bQuit;
}
/* Disable Interrupts */
swResult = naibrd_1760_SetIrqManipulate(DevNum, 0x0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, NULL);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_SetIrqManipulate %d", swResult);
return bQuit;
}
}
else
bContinue = FALSE;
}
/* Uninstall ISR */
swResult = naibrd_UninstallISR(cardIndex);
/* Free 1553 Device */
swResult = naibrd_1553_Free(DevNum);
if(swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_Free %d", swResult);
return bQuit;
}
return bQuit;
}
static void myIsr(void* param, uint32_t vector)
{
#if defined (WIN32)
UNREFERENCED_PARAMETER(param);
UNREFERENCED_PARAMETER(vector);
#endif
#if defined (__VXWORKS__)
/* Get the vector that caused the interrupt */
vector = nai_Onboard_GetInterruptVector();
logMsg("\nvector = %d deviceNumber = %d\n", vector, deviceNumber, 2, 3, 4, 5);
/* Clear Interrupt */
nai_Onboard_ClearInterrupt();
#endif
receivedVector = vector;
/* Set the global interrupt flag */
irqFlag = 1;
irqCount++;
}
static int ProcessMessages(int32_t duration)
{
time_t end;
uint32_t swResult;
int32_t i;
naiDecodedMessageStructure DecodedMsgStruct;
uint16_t wsBuffer[72] = { 0x0000 };
int32_t count = 0;
uint16_t hwstatus, rtstatus, bcstatus, mtstatus;
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_1760_GetIntStatus(deviceNumber, &hwstatus, &bcstatus, &rtstatus, &mtstatus);
if (swResult != NAI_SUCCESS)
{
printf("\nERROR: naibrd_1760_GetIntStatus - %d\n", swResult);
}
if (rtstatus & NAI_1760_RT_INTERRUPT_MASK_IWA1)
{
printf("\nInterrupt When Accessed. IrqCount = %d\n", irqCount);
}
else if (hwstatus & NAI_1760_HARDWARE_INTERRUPT_MASK_RT1TTM)
{
printf("\nTime Tag Match interrupt. IrqCount = %d\n", irqCount);
}
else
{
printf("\nOther interrupt triggered. hwstatus=0x%04X rtstatus=0x%04X bcstatus=0x%04X mtstatus=0x%04X IrqCount=%d\n", hwstatus, rtstatus, bcstatus, mtstatus, irqCount);
}
/* Clear Latch Bit */
swResult = naibrd_1553_ClearIntLatch(deviceNumber);
if (swResult != NAI_SUCCESS)
{
printf("\nERROR: naibrd_1553_ClearIntLatch - %d\n", swResult);
}
/* Get Data */
/* If the stack pointer has updated (new message arrived), read one message at a time */
swResult = naibrd_1553_RtMessageGetFromStackRaw(deviceNumber, wsBuffer, NAI_1553_MAX_MESSAGE_SIZE_RT);
if (swResult < 0)
{
printf("ERROR: naibrd_1553_RtMessageGetFromStackRaw %d\n\n", swResult);
}
else if (swResult > 0)
{
/* Decode Raw Message */
swResult = naibrd_1553_RtMessageDecodeRaw(deviceNumber, wsBuffer, &DecodedMsgStruct);
if (swResult < 0)
{
printf("ERROR: naibrd_1553_RtMessageDecodeRaw %d\n\n", swResult);
}
if ((DecodedMsgStruct.wCommandWord1 & 0x0400) != 0x0400) /* If this is a Rx message */
{
printf("Rx Msg Received\n");
printf("\n\nDecoded Message:\n\n");
printf("Block Status - 0x%04X\n", DecodedMsgStruct.wBlockStatus);
printf("Time Tag - 0x%04X\n", DecodedMsgStruct.wTimeTag);
printf("Command Word - 0x%04X\n", DecodedMsgStruct.wCommandWord1);
printf("Data Word Count - 0x%04X\n", DecodedMsgStruct.wDataWordCount);
printf("Data:");
for (i = 0; i < DecodedMsgStruct.wDataWordCount; i++)
{
if (i % 8 == 0)
{
printf("\n");
}
printf("0x%04X ", DecodedMsgStruct.waData[i]);
}
printf("count: %d\n", count++);
printf("\n\n");
}
else
{
printf("Tx Msg Received\n");
}
}
}
#if defined (__VXWORKS__)
taskDelay(1);
#endif
}
return 1;
}