M1760 RT Program EEPROM
Edit this on GitLab
M1760 RT Program EEPROM Sample Application (SSK 1.x)
Overview
The M1760 RT Program EEPROM sample application demonstrates how to configure a MIL-STD-1553 channel as a Remote Terminal (RT), set up data blocks for multiple subaddresses, and save that configuration to the module’s serial EEPROM so the RT auto-initializes on the next power cycle using the NAI Software Support Kit (SSK 1.x). After a successful EEPROM program, the module will respond to BC commands within 100ms of power-up without requiring any software initialization.
The sample configures the RT with:
-
Subaddress 2 — Rx double buffer for receiving data from the BC.
-
Subaddress 15 — Rx double buffer for receiving data from the BC.
-
Subaddress 23 — Tx single buffer (with a second buffer for optional ping-pong), pre-loaded with test data (
0xBEEF+ offset) that the BC can request.
After the RT configuration is built, the sample starts and immediately stops the RT (the start/stop cycle ensures the configuration is committed to device RAM), then copies the entire configuration to EEPROM using the same unlock/EECOPY/READY sequence demonstrated in the M1760 EEPROM Copy sample.
|
Note
|
This sample is only supported on FTJ and FTK modules. Other 1553 modules do not have 1760 EEPROM functionality. For module-specific details, refer to the FTJ-FTK Manual. |
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an FTJ or FTK module installed.
-
SSK 1.x installed on your development host.
-
The sample applications built. Refer to the SSK 1.x build instructions for your platform if you have not already compiled them.
How to Run
Launch the M1760_RT_Program_EEPROM executable from your build output directory. On startup the application looks for a configuration file (default_1760_RTProgramEEPROM.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 for RT channel and address, configures the RT with data blocks on subaddresses 2, 15, and 23, and programs the configuration to EEPROM.
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 1760. |
The main() function follows a standard SSK 1.x startup flow:
-
Call
naiapp_RunBoardMenu()to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_1760_RTProgramEEPROM.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear. -
Query the user for a card index with
naiapp_query_CardIndex(). -
Query for a module slot with
naiapp_query_ModuleNumber(). -
Retrieve the module ID with
naibrd_GetModuleID(). -
Call
Run_M1760_RT_Program_EEPROM()to perform the RT configuration and EEPROM programming.
#if defined (__VXWORKS__)
int32_t M1760_RT_Program_EEPROM(void)
#else
int32_t main(void)
#endif
{
bool_t bQuit = FALSE;
int32_t cardIndex = -1;
int32_t module = 0;
int32_t moduleCount = 0;
uint32_t modid = 0u;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (!bQuit)
{
bQuit = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
bQuit = naibrd_GetModuleCount(cardIndex, &moduleCount);
bQuit = naiapp_query_ModuleNumber(moduleCount, 1, &module);
modid = naibrd_GetModuleID(cardIndex, module);
}
bQuit = Run_M1760_RT_Program_EEPROM(cardIndex, module, modid);
printf("Type %c to exit program or Enter key to restart application: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
naiapp_access_CloseAllOpenCards();
return 0;
}
|
Important
|
Common connection errors you may encounter at this stage:
|
Program Structure
The entry point is main() on most platforms, or M1760_RT_Program_EEPROM() on VxWorks. Both resolve to the same logic.
The application flow is linear — it configures the RT, programs the EEPROM, and exits. There is no monitoring loop because the purpose is to write the configuration, not to operate the RT at runtime.
User Input Sequence
After the board connection is established, Run_M1760_RT_Program_EEPROM() collects configuration through a series of prompts:
-
RT channel and address —
Get1553RTCfg()asks for the 1553 channel (default: 1) and RT address (default: 1). -
Logical device number —
Get1553LogicalDevNum()assigns a logical device handle for the naibrd API (default: 1).
Device Initialization
Opening and Initializing
swResult = naibrd_1553_Open(cardIndex, module, rtchan, DevNum);
swResult = naibrd_1553_Initialize(DevNum, NAI_1553_ACCESS_CARD, NAI_1553_MODE_RT, 0, 0, 0);
The device is initialized in standard RT mode. The RT address is read back to confirm it was set correctly:
swResult = naibrd_1553_RtGetAddress(DevNum, &usData);
printf("RT Address set to %d\n\n", usData);
On 1760 modules, the RT address is typically determined by external hardware pins. naibrd_1553_RtGetAddress() reads the current address from the device, confirming what the hardware has latched.
|
Important
|
Common initialization issues you may encounter:
|
RT Data Block Configuration
The sample creates data blocks for three subaddresses to demonstrate a typical RT configuration that you might want to persist in EEPROM.
Subaddresses 2 and 15 — Rx Double Buffers
Two Rx double buffers are created and mapped to subaddresses 2 and 15 for receiving data from the BC:
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DBLK_SA2, NAI_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DBLK_SA2, 2, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DBLK_SA15, NAI_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DBLK_SA15, 15, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);
Double buffering prevents data corruption when the BC sends data while the previous message is being read. After the EEPROM is programmed, the module will respond with clear status to Rx messages on these subaddresses within 100ms of power-up.
Subaddress 23 — Tx Buffers with Pre-loaded Data
Two Tx single buffers are created for subaddress 23. The first is mapped as the active Tx buffer; the second is available for runtime ping-pong buffering:
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DBLK_SA23_1, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DBLK_SA23_2, NAI_1553_RT_DATABLOCK_SINGLE_32, NULL, 0);
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DBLK_SA23_1, 23, NAI_1553_RT_MESSAGE_TYPE_TX, 0, 1);
The Tx buffer is pre-loaded with test data so that when the BC requests a Tx from subaddress 23, the RT responds with known data:
for (i = 0; i < 32; i++)
{
txData[i] = (uint16_t)(0xBEEF + i);
}
swResult = naibrd_1553_RtDataBlockWrite(DevNum, DBLK_SA23_1, txData, 32, 0);
This data (0xBEEF, 0xBEF0, 0xBEF1, …) will be stored in EEPROM along with the rest of the configuration, so the RT will transmit it immediately after auto-initialization on the next power cycle.
|
Important
|
Common data block issues you may encounter:
|
RT Start/Stop Cycle
Before copying to EEPROM, the sample starts and immediately stops the RT:
swResult = naibrd_1553_RtStart(DevNum);
/* Stop RT - For EEPROM copy to work, the RT must not be running. */
swResult = naibrd_1553_RtStop(DevNum);
The start/stop cycle is required to commit the RT configuration into the device’s internal RAM in a format that the EEPROM copy can capture. The RT must not be running during the EEPROM copy operation — the stop call ensures this.
EEPROM Programming Sequence
The EEPROM copy follows the same three-step sequence as the M1760 EEPROM Copy sample: unlock, pulse EECOPY, and wait for READY.
Step 1: Unlock the EEPROM
swResult = naibrd_1760_SetEEPROMUnlock(DevNum);
The serial EEPROM is write-protected by default. This unlocks it for the copy operation.
Step 2: Pulse the EECOPY Signal
swResult = naibrd_1760_SetEECOPY(DevNum, TRUE);
nai_msDelay(10);
swResult = naibrd_1760_SetEECOPY(DevNum, FALSE);
Driving EECOPY high triggers the HI-6131 to begin copying registers and RAM to the serial EEPROM. The 10ms high pulse gives the hardware time to latch the request. Driving it low allows the copy to proceed autonomously.
Step 3: Wait for Completion
do
{
nai_msDelay(1000);
swResult = naibrd_1760_GetDeviceReady(DevNum, &ready);
} while (!ready);
printf("Copy Complete\n");
The READY signal returns high when the EEPROM copy is finished. Do not use the device for any other operations while READY is low.
What Happens on Next Power Cycle
After a successful EEPROM program, the FTJ/FTK module will auto-initialize on the next power cycle:
-
The RT will come up at the address that was latched when the EEPROM was programmed.
-
Subaddresses 2 and 15 will be legalized for Rx with double buffers.
-
Subaddress 23 will be legalized for Tx with the pre-loaded data.
-
The RT will respond with clear status to BC commands within approximately 100ms of power-up.
This eliminates the need for software initialization in the deployed system, which is critical for applications where the RT must be operational before the host processor has fully booted.
|
Important
|
Common EEPROM programming issues you may encounter:
|
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 the FTJ-FTK Manual for hardware-specific diagnostic procedures.
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No board found or connection timeout |
Board not powered, missing configuration file, network issue |
Verify hardware and configuration. If file doesn’t exist, configure and save from board menu. |
Device open or initialization failure |
Wrong card/module/channel, or device already in use |
Verify parameters. Close other applications using this channel. |
RT address reads as 0 |
External address pins not connected or not latched |
Verify hardware pin configuration on the FTJ/FTK module. |
Data block creation failure |
Device out of memory for data blocks |
Reduce number of data blocks or buffer sizes. |
EEPROM unlock failure |
Device not properly initialized |
Ensure |
EECOPY hangs — READY never goes high |
EEPROM not unlocked, or device state invalid |
Verify unlock succeeded. Power cycle the board and retry. |
RT not auto-initializing after reboot |
EEPROM copy did not complete, or RT address pins changed |
Confirm READY went high. Verify address pin settings match the programmed configuration. |
Tx data not present after EEPROM auto-init |
Data not written to buffer before EEPROM copy |
Call |
EEPROM copy fails — RT was still running |
|
Always stop the RT before performing the EEPROM copy. |
Full Source
The complete source for this sample is provided below for reference. The sections above explain each part in detail.
Full Source — M1760_RT_Program_EEPROM.c (SSK 1.x)
#include <stdio.h>
#include <ctype.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"
static const int8_t *CONFIG_FILE = (int8_t *)"default_1760_RTProgramEEPROM.txt";
/* Function prototypes */
static bool_t Run_M1760_RT_Program_EEPROM(int32_t cardIndex, int32_t module, uint32_t modid);
#define DBLK_SA2 1
#define DBLK_SA15 2
#define DBLK_SA23_1 3
#define DBLK_SA23_2 4
#define DEF_RT_CHANNEL 1
#define DEF_RT_DEV_NUM 1
#define DEF_RT_ADDRESS 1
/**************************************************************************************************************/
/**
<summary>
The purpose of the M1760_RT_Program_EEPROM is to illustrate the methods to call in the naibrd library to configure
the FTJ or FTK channel as a Remote Terminal, create buffers and legalize Subaddresses 2 and 15 for Rx messages,
create buffers and legalize Subaddress 23 for Tx messages and copy the current configuration to the module EEPROM
so that when the module is rebooted, the channel will auto-initialize with this configuration. With this configuration,
the channel will respond with clear status (within 100 ms from power-up) to Rx messages on subaddresses 2 and 15.
Additionally, the channel will respond with clear status and data to Tx messages on subaddress 23.
This application demonstrates the usage of the following naibrd 1553 routines.
- naibrd_1553_GetChannelCount
- naibrd_1553_Open
- naibrd_1553_Initialize
- naibrd_1553_RtGetAddress
- naibrd_1553_RtDataBlockCreate
- naibrd_1553_RtDataBlockMapToSubaddress
- naibrd_1553_RtDataBlockWrite
- naibrd_1553_RtStart
- naibrd_1553_RtStop
- naibrd_1760_SetEEPROMUnlock
- naibrd_1760_SetEECOPY
- naibrd_1760_GetDeviceReady
- naibrd_1553_Free
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_Program_EEPROM(void)
#else
int32_t main(void)
#endif
{
bool_t bQuit = FALSE;
int32_t cardIndex = -1;
int32_t module = 0;
int32_t moduleCount = 0;
uint32_t modid = 0u;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (!bQuit)
{
bQuit = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
bQuit = naibrd_GetModuleCount(cardIndex, &moduleCount);
bQuit = naiapp_query_ModuleNumber(moduleCount, 1, &module);
modid = naibrd_GetModuleID(cardIndex, module);
}
bQuit = Run_M1760_RT_Program_EEPROM(cardIndex, module, modid);
printf("Type %c to exit program or Enter key to restart application: ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
naiapp_access_CloseAllOpenCards();
return 0;
}
static bool_t Run_M1760_RT_Program_EEPROM(int32_t cardIndex, int32_t module, uint32_t modid)
{
/* Variables */
bool_t bQuit = FALSE;
int32_t rtchan;
uint8_t rtaddr;
int16_t DevNum = 0;
int32_t swResult;
uint16_t usData;
uint16_t txData[32];
int32_t i;
bool_t ready;
/* Get Card, Module, Channel Numbers and Open a Handle */
bQuit = Get1553RTCfg(modid, DEF_RT_CHANNEL, DEF_RT_ADDRESS, &rtchan, &rtaddr);
if (bQuit)
{
return bQuit;
}
/* Get Logical Device # */
bQuit = Get1553LogicalDevNum(DEF_RT_DEV_NUM, &DevNum);
if (bQuit)
{
return bQuit;
}
/* 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;
}
/* Read RT Address */
swResult = naibrd_1553_RtGetAddress(DevNum, &usData);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtGetAddress %d", swResult);
return bQuit;
}
printf("RT Address set to %d\n\n", usData);
/* Create a Rx Double Buffer and map to subaddress 2 */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DBLK_SA2, NAI_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DBLK_SA2, 2, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
/* Create a Rx Double Buffer and map to subaddress 15 */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DBLK_SA15, NAI_1553_RT_DATABLOCK_DOUBLE, NULL, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockCreate %d", swResult);
return bQuit;
}
swResult = naibrd_1553_RtDataBlockMapToSubaddress(DevNum, DBLK_SA15, 15, NAI_1553_RT_MESSAGE_TYPE_RX, 0, 1);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
/* Create two Tx Single Buffers and map the first buffer to subaddress 23. The second buffer may be used during operation */
/* for software-controlled ping pong buffering between the first and second buffer */
swResult = naibrd_1553_RtDataBlockCreate(DevNum, DBLK_SA23_1, 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, DBLK_SA23_2, 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, DBLK_SA23_1, 23, NAI_1553_RT_MESSAGE_TYPE_TX, 0, 1);
if (swResult < 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockMapToSubaddress %d", swResult);
return bQuit;
}
/* Load the Tx Buffer with data that will be requested from the Bus Controller */
for (i = 0; i < 32; i++)
{
txData[i] = (uint16_t)(0xBEEF + i);
}
swResult = naibrd_1553_RtDataBlockWrite(DevNum, DBLK_SA23_1, txData, 32, 0);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtDataBlockWrite %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;
}
/* Stop RT - For EEPROM copy to work, the RT must not be running. */
swResult = naibrd_1553_RtStop(DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_RtStop %d", swResult);
return bQuit;
}
/* Copy the RT configuration to EEPROM for auto-initialization */
swResult = naibrd_1760_SetEEPROMUnlock(DevNum);
if (swResult != NAI_SUCCESS)
{
printf("Error: naibrd_1760_SetEEPROMUnlock %d", swResult);
return TRUE;
}
printf("\nSerial EEPROM Unlock Successful.");
swResult = naibrd_1760_SetEECOPY(DevNum, TRUE);
if (swResult != NAI_SUCCESS)
{
printf("Error: naibrd_1760_SetEECOPY %d", swResult);
}
printf("\nDriving EECOPY input high.");
nai_msDelay(10);
swResult = naibrd_1760_SetEECOPY(DevNum, FALSE);
if (swResult != NAI_SUCCESS)
{
printf("Error: naibrd_1760_SetEECOPY %d", swResult);
return TRUE;
}
printf("\nDriving EECOPY input low.");
printf("\nWait until READY output goes high for EEPROM copy completion...");
do
{
nai_msDelay(1000);
swResult = naibrd_1760_GetDeviceReady(DevNum, &ready);
} while (!ready);
printf("Copy Complete\n");
/* Free 1553 Device */
swResult = naibrd_1553_Free(DevNum);
if (swResult != 0)
{
bQuit = TRUE;
printf("Error: naibrd_1553_Free %d", swResult);
return bQuit;
}
return bQuit;
}