I am trying to use MapPhysicalMemory and UnMapPhysicalMemory functions to
control a single function, MIL-STD-1553 board for PC ISA
systems (ASF-PC by SBS Tecnologies, Inc.). The ASF-PC is mapped into the
upper memory space of conventional memory at an available 32K x 16-bit word
boundary. I am attaching a documentation file for your reference.
Note that when the board is installed in conventional memory space, only
a 32K block of 16 bit words of control registers and RAM is accessable at
one time. Access to the second 32K block of memory is possible through a
bank select mechanism that iscontrolled by an on-board I/O Register. See
section 4, System Operation, for a description of the ASF-PC I/O Register.
This register manages the functionality of the ASF-PC. The
base address <@location D0000h>, interrupt level (IR11), and I/O Register
address <@location 350h> are selected using switches on the board.
The system I am using is running Windows 95 and I have excluded these memory
addresses from use by other software. Since the card might not respond fast
enough for block addressing I have tried putting in delays of varying lengths
between each word access. This did not make the code work.
The code I am using was written in MS Visual C++ version 1.5 using MFC as
a 16-bit application and I am porting it to be built in VC++ Version 6.0
as a 32-bit application. The ReadRam and WriteRam functions are used because
they worked but the mapping functions used involved setting up a memory map
with an IMPORT statement in a definition file (.def) as follows:
IMPORTS __1553D000Selector = KERNEL.__D000h
and defined in the source as:
extern "C" WORD _1553D000Selector; // Windows-exported selector
for segment D000 in conventional memory. Defined in ".DEF" file
Then using the following typedef statement:
typedef UINT FAR* LP1553;
the map address was established as follows:
LP1553 m_baseCardAddress = (LP1553)MAKELONG(0, &_1553D000Selector);
This address was then used to write RAM in a function as follows:
void C1553::WriteRam(UINT wordoffset, UINT wordval)
{
m_baseCardAddress[wordoffset] = wordval;
}
and to read RAM in a function as follows:
UINT C1553::ReadRam(UINT wordoffset)
{ return(m_baseCardAddress[wordoffset]); }
where the variables were defined as:
UINT wordval;
UINT wordoffset;
Simple enough yet only one problem. This functionality is not available
with Version 6.0. I am building this in VC++ 6.0 because I want to build
it as a DLL from which I can export functions to call from it to avoid any
operator interaction and speed up execution time. It is also one of the
standard platforms adopted by our department (along with LW/CVI of course).
These are the definitions and variables:
#define BASEPORT1553 0x350 // I/O Port of 1553 card
#define CONTROL_REG 0x00 // ASF Control Register
#define CURRENT_COMMAND_REG 0x02 // ASF Current Command
Block Rg
#define HIGH_PRIORITY_EN_REG 0x07 // ASF High Prior Interrupt
Reg
#define HOST_CONTROL_REG 0x1E // ASF Host Control Register
#define INT_LOG_LIST_POINTER_REG 0x06 // ASF Intrpt Log List
Pntr Reg
#define POLLING_COMPARE_REG 0x03 // ASF Polling Compare
Register
#define STATUS_REG 0x01 // ASF Status Register
#define VARIABLE_VOLT_REG 0x1D // ASF Variable Voltage
DAC Reg
#define NOSTATUSWORD 0xFFFF // Default when no status
word
#define SINGLEMESSAGEADDRESS 0x0020 // Location to load single
msg this message is to be placed
#define COMMANDBLOCKSTARTADDRESS 0x0060
#define DATALISTSTARTADDRESS 256 * 8 + COMMANDBLOCKSTARTADDRESS
#define INTLOGBASEADDRESS 0x7F00 // Interrupt Log List starting
#define INTLOGMAXADDRESS 0x7FFF // and ending address
typedef unsigned short int USINT;
typedef unsigned long int ULINT;
struct message1553
{
UINT controlword;
UINT commandword[2];
UINT statusword[2];
UINT dataword[32];
UINT headpointer;
UINT tailpointer;
};
int m_mapHandle;
char * m_ptrPhysicalAddr;
ULINT m_baseCardAddress; // Base address of TIK RAM;
short m_baseport; // I/O Port of 1553 card
UINT m_controlreg; // Control register contents
UINT m_numBytes; // Number of bytes to map
The following calls are made in the C1553 constructor:
GetBaseMemAndPort(); // Get base mem & port
address
if (CVILowLevelSupportDriverLoaded ())
{
m_numBytes = 0xffff;
MapPhysicalMemory (m_baseCardAddress, m_numBytes, &m_ptrPhysicalAddr, &m_mapHandle);
}
These are the functions:
int C1553::GetBaseMemAndPort()
{
m_baseCardAddress = 0xD0000; // Set card base port address
m_baseport = BASEPORT1553; // Point to start of I/O Register RAM
return(TRUE);
}
UINT C1553::ReadRam(USINT wordoffset)
{
UINT wordval;
char *ptrPhysMem = m_ptrPhysicalAddr;
ptrPhysMem += (wordoffset << 1);
wordval = ((UINT)*ptrPhysMem << 😎 | ((UINT)*(ptrPhysMem + 1));
return(wordval);
}
void C1553::WriteRam(USINT wordoffset, USINT wordval)
{
char byteval = (char)wordval;
char *ptrPhysicalMem = m_ptrPhysicalAddr;
ptrPhysicalMem += (wordoffset << 1);
*ptrPhysicalMem = byteval;
ptrPhysicalMem ++;
byteval = (char)(wordval >> 8);
*ptrPhysicalMem = byteval;
}
This is how I am using them.
void C1553::Reset()
{
UINT intLogEntry; // Interrupt Log Entry Address
outp(m_baseport, 0x03); // Enable board in 8 bit
data transfer mode
// 32K word memory size
// Check to see if master reset is set
if (ReadRam(HOST_CONTROL_REG) & 1)
{
sprintf(msg, "%s1553 Interface Card Not enabled. %s\n",
msg, "ASF Master Reset Signal is not active.");
MessageBox(NULL, msg, "Fatal Error!", MB_OK);
}
WriteRam(HOST_CONTROL_REG, 0); // Reset master reset
Delay(CARDRESETENDTIME); // Wait for card to come out of
reset mode
WriteRam(HOST_CONTROL_REG, 0x08); // Clear pending interrupts
WriteRam(HOST_CONTROL_REG, 0x040); // LED0 ON
WriteRam(HOST_CONTROL_REG, 0x080); // LED0 OFF AND LED1 ON
WriteRam(HOST_CONTROL_REG, 0); // LEDs OFF
WriteRam(VARIABLE_VOLT_REG, 0xF0); // Turn on max voltage
for (intLogEntry = INTLOGBASEADDRESS + 2; // Initialize each Interrupt
intLogEntry < INTLOGMAXADDRESS; intLogEntry += 3) // Log List
entry's
{
// tail pointer to
WriteRam(intLogEntry, intLogEntry + 1); // next cell address
WriteRam(intLogEntry - 2, 0); // Zero Interrupt Status Word
WriteRam(intLogEntry - 1, 0); // Zero Command Block Pointer
}
WriteRam(intLogEntry - 3, INTLOGBASEADDRESS); // Make circular list
WriteRam(INT_LOG_LIST_POINTER_REG, INTLOGBASEADDRESS); // Point to list
start
}
void C1553::LoadMessage(struct message1553 *message)
{
int datawordnum; // Data word number
int numofdatawords; // Data words in this message
UINT baseaddr = message->headpointer; // 1553 card address where
this message is to be placed
WriteRam(CONTROL_REG, m_controlreg); // Set card as Bus Controller
WriteRam(baseaddr, baseaddr); // Head Pointer
WriteRam(baseaddr + 1, message->controlword); // Control Word
WriteRam(baseaddr + 2, message->commandword[0]); // Comand word 1
WriteRam(baseaddr + 3, message->commandword[1]); // Comand word 2
WriteRam(baseaddr + 4, baseaddr + 8); // Data Pointer
WriteRam(baseaddr + 5, NOSTATUSWORD); // Status word 1
WriteRam(baseaddr + 6, NOSTATUSWORD); // Status word 2
WriteRam(baseaddr + 7, message->tailpointer); // Tail Pointer
if (!(message->commandword[0] & 0x0400)) // If this is a receive command
{ // load proper # of data
words
baseaddr = message->headpointer + 8; // Point to datawords
numofdatawords = message->commandword[0] & 0x1F;
if (numofdatawords == 0)
numofdatawords = 32;
for (datawordnum = 0; datawordnum < numofdatawords; datawordnum++)
WriteRam(baseaddr + datawordnum, message->dataword[datawordnum]);
}
}
int C1553::SendMessage(struct message1553 *message, char *msg)
{
CTimeCounter sendmsgtc; // Send message time counter
int datawordnum; // Data word number
int numofdatawords; // # of data words in message
UINT baseaddr = message->headpointer; // 1553 card addr where
msg at
unsigned long sendtime = 0; // Time since msg being
sent
// If Hardware failure or MRST is set
if ((ReadRam(HOST_STATUS_REG) & 1) || ((ReadRam(HOST_STATUS_REG) >> 1)
& 1))
{
sprintf(msg, "%s1553 Transmission ERROR. Hardware failure or %s\n",
msg, "ASF Master Reset Signal active.");
return(FALSE); // Indicate message error
}
WriteRam(CURRENT_COMMAND_REG, message->headpointer);
WriteRam(POLLING_COMPARE_REG, 0); // Disable polling
WriteRam(HIGH_PRIORITY_EN_REG, 0); // Disable priority interrupts
WriteRam(CONTROL_REG, m_controlreg | 1); // Start Enable Ready
WriteRam(CONTROL_REG, m_controlreg | 1); // Start Enable Run
sendmsgtc.Reset(); // Reset elapsed time counter
while (sendtime <= MAXSINGLEMESSAGESENDTIME)
{ // While not reached max time
sendtime = sendmsgtc.MsecsElapsed(); // Time since send began
if (ReadRam(STATUS_REG) & 1) // If Command not complete,
continue; // wait for command to
complete.
if ((ReadRam(message->headpointer + 1) & 0x8000) || // If message
error
(ReadRam(message->headpointer + 5) == NOSTATUSWORD))
{
if (ReadRam(message->headpointer + 5) == NOSTATUSWORD)
{ // If no status word received
sprintf(msg, "%s1553 Transmission ERROR. No RT status word
%s\n",
msg, "received.");
}
else // If status word received
{
sprintf(msg, "%s1553 Transmission ERROR. RT status %s %04X.\n",
msg, "word was", ReadRam(message->headpointer + 5));
}
return(FALSE); // Indicate message error
}
if (message->commandword[0] & 0x0400) // If this is a transmit
command
{ // read proper # of data
words
baseaddr = message->headpointer + 8; // Point to datawords
numofdatawords = message->commandword[0] & 0x1F;
if (numofdatawords == 0)
numofdatawords = 32;
for (datawordnum = 0; datawordnum < numofdatawords; datawordnum++)
message->dataword[datawordnum] = ReadRam(baseaddr + datawordnum);
}
return(TRUE); // Successful
}
sprintf(msg, "%s1553 Timeout ERROR. Status register indicates command
%s",
msg, "did not complete execution.\n");
return(FALSE); // Timed out before successful
}
The following calls are made in the C1553 destructor:
outp(m_baseport, 0x00); // Disable the 1553 card
UnMapPhysicalMemory (m_mapHandle);
This all works fine and I get no errors during execution of these commands.
However, when I use these commands to verify that the UUT is in transfer
mode by reading the dataword array of the 1553message structure, I find that
dataword[0] (the so-called headerword) is correctly returned and dataword[1]
has 0x8000 in it, but dataword [2] (which has the transfer mode bit) has
no data in it at all. In fact, the other data words returned in the array
are all zeros. I have tried various alignments using #pragma pack(0-8) statements
around the 1553message structure definition, but to no avail. Since the
variables in the structure are UINT's, does this really matter? What could
be causing this problem?
Thanks for your help,
Jeff Green
Raytheon Missile Systems Company
Bldg. M20, M/S P17
PO Box 11337
Tucson, AZ 85734-1337
520-663-7540
FAX 520-663-6847