↑ Writing ↑

GEONius.com
17-Aug-2024
 E-mail 

MILSTAR Universal Firmware User's Manual

1985

(Also see MILSTAR Universal Firmware Design)

 

1 Introduction

This document is intended as a user's manual for the MILSTAR Universal Firmware. The first half of the user's manual looks at the hardware and software configuration of the firmware. The second half of the user's manual provides the user with a detailed functional description of the universal firmware.

1.1 Overview

Automatic test equipment is being used to test various digital system components (RIU, IOC, CTC, and MMU) that will be placed on the MILSTAR satellites. An additional test set (panel STE) exercises a fully populated spacecraft panel. The automatic test equipment is composed of a remote processing unit (RPU) and a test interface rack (TIR) that controls and monitors the unit under test (UUT). The RPU for the panel STE test set is a Digital Equipment Corporation VAX-11/780 computer; it simulates the Ground Station Computer (GSC) and is connected to the TIR via an RS-232C serial link. The RPU for the other test sets is a Hewlett-Packard HP-1000 minicomputer that is connected to the TIR via an IEEE-488 bus. The RIU test set requires an additional test rack that is connected to the main rack via an RS-232C serial link. The RPU passes test commands and parameters to the TIR. After exercising the UUT as necessary, the TIR returns test results and status to the RPU.

The software that resides in the TIR consists of universal firmware and applications firmware. The applications firmware is test set-specific. Its functions include receiving test commands and parameters from the RPU, configuration of the TIR hardware per the test parameters, initiating the test, monitoring the test as it executes and collecting test data, and returning the test results and status to the RPU. The universal firmware is test set-independent. It provides the task communication, TIR-RPU interface, and rack A-rack B interface utilities needed by the applications firmware. It is also responsible for initializing the TIR computers and downloading and running the applications firmware.

1.2 Applicable Documents

The following documents were used in the design of the universal firmware:

  1. Am96/0000L Series RAM Boards, User's Manual
  2. Guide to Using the iSBC 286/10 Single Board Computer
  3. Intel Microsystems Components Handbook, Volumes I & II
  4. iRMX Installation and Configuration Guide for Release 6
  5. iRMX Programmer's Reference Manual for Release 6, Parts 1-2
  6. iSBX 488 General Purpose Interface Bus (GPIB) Multimodule Board Hardware Reference Manual
  7. iSDM 286 System Debug Monitor Reference Manual

1.3 Definitions

BIOS		Basic Input/Output System
CPU		Central Processing Unit
CTC		Comsec-Transec Controller
DAU		Data Acquisition Unit
DCL		Device Clear (IEEE-488 function)
EOI		End of Input (IEEE-488 bus signal)
EPROM		Erasable Programmable Read-Only Memory
GPIB		General Purpose Interface Bus (IEEE-488 bus, Intel nomenclature)
GSC		Ground Station Computer (panel STE test set)
HPIB		Hewlett-Packard Interface Bus (IEEE-488 bus, HP nomenclature)
I/F		Interface
IH		Interrupt Handler
I/O		Input/Output
IOC		Input/Output Controller
IOCT		I/O Completion Task
IST		Interrupt Service Task
LBX		Local Bus Extension
MILSTAR		Military Strategic and Tactical Relay Satellite System
MMU		Mass Memory Unit
MPSC		Multi-Protocol Serial Controller (Intel 8274)
NDAC		Not Data Accepted (IEEE-488 bus signal)
PIC		Priority Interrupt Controller (Intel 8259A)
PIT		Programmable Interval Timer (Intel 8254)
PPI		Programmable Peripheral Interface (Intel 8255A)
PROM		Programmable Read-Only Memory
RAM		Random Access Memory
RIU		Remote Interface Unit
RMX		Real-time Multi-tasking Executive
RPU		Remote Processing Unit
RSV		Request for Service (IEEE-488 SRQ bit)
SBC		Single Board Computer
SBX		SBC I/O Bus Expansion
SDM		System Debug Monitor
SRQ		Service Request (IEEE-488 bus signal)
STE		Panel Special Test Equipment
TBD		To Be Determined
TIR		Test Interface Rack
UUT		Unit Under Test
 

2 Universal Firmware Configuration

This section of the user's manual describes the hardware environment of the universal firmware and how the firmware is compiled, linked, and burned into programmable read-only memory (PROM) chips.

2.1 Hardware Configuration

The universal firmware runs on an Intel iSBC 286/10 single board computer. The SBC's CPU, its memory configuration, and its external interfaces had a large effect on the design, coding, and testing of the universal firmware.

2.1.1 80286 CPU

The SBC's 80286 CPU runs in real address (8086 compatibility) mode. There is a bug in the version of the 80286 CPU that we have. We spent a lot of time diagnosing the problem. How come hardware never works as well as the software that runs on it? The POPF (pop flags) instruction will sometimes temporarily enable interrupts, even if interrupts are disabled prior to executing the instruction and the flags being popped have interrupts disabled. Intel's workaround for this problem is to emulate the POPF by adding a return address to the flags on the stack and performing an IRET (interrupt return). POPF's are not used in the iRMX 286R operating system and are not generated by the PL/M-86 compiler. Only the assembly language power-up and low-level console I/O firmware were affected by this bug.

2.1.2 Memory Configuration

The standard memory configuration in the test racks is as follows:

               00000H - 07FFFH		On-Board Dual Port RAM (32K)
               30000H - AFFFFH		Off-Board LBX RAM (512K)
               C0000H - C3FFFH		On-Board Local RAM (16K)
               F0000H - FFFFFH		On-Board PROM (64K)

The IOC test rack is configured differently than the other test racks. An extra 32K of dual port RAM is added on-board, providing 64K of program RAM. A second 512K LBX RAM board is added to the test rack. Since the Multibus has 24 address lines and the real address mode 80286 only sources 20 address lines, spare address bit 23 is used to select which board responds to references in the 30000H-AFFFFH address space. The "ping" memory board starts at Multibus address 030000H; the "pong" memory board starts at Multibus address 830000H. Address bit 23 is driven by the IOC clock board and can be controlled manually or set up to "ping/pong" automatically every DBC cycle. The IOC test rack's memory configuration is as follows:

               00000H - 0FFFFH	On-Board Dual Port RAM (64K)
              030000H - AFFFFH	Off-Board LBX RAM (512K)
              830000H - AFFFFH	Off-Board LBX RAM (512K)
               C0000H - C3FFFH	On-Board Local RAM (16K)
               F0000H - FFFFFH	On-Board PROM (64K)

The 512K RAM boards should have parity detect enabled and their parity error interrupts tied to Multibus interrupt level 0. A normal LBX board (including IOC's "ping" board) should have its parity error register located at I/O address 0000H; the IOC "pong" board should have its parity error register located at I/O address 0008H. The on-board PROM consists of two 27256 32K PROM's. One PROM contains all the even-addressed bytes; the other PROM contains the odd-addressed bytes.

The universal firmware tests all RAM memory on power-up (the presence of the IOC clock board determines whether the "pong" memory is tested). However, the universal firmware only uses a small portion of the available RAM:

                 00000H - 003FFH		Interrupt Vector Table
                 00400H - 005FFH		MTEX-86 Monitor Data
                 00600H - 00FFFH		Universal Firmware Data
                 C0000H - C3FFFH		iRMX 286R System Memory

NOTE that the iRMX 286R system memory is located in the local RAM. The universal firmware does NOT run correctly out of dual port RAM. There is a problem with dual port bus arbitration if an interrupt occurs while the CPU is halted (iRMX idle state); the flags the CPU then tries to push onto the stack in dual port RAM do not always reach the RAM! When the flags are later popped by returning from the interrupt, strange things sometimes happen. The MTEX-86 monitor does have its stack stored in dual port RAM, but, since interrupts are disabled in the monitor, there is no problem (I hope!).

2.1.3 RS-232C Interface

There are two RS-232C channels on the iSBC 286/10 board; both channels are configured as Data Communications Equipment (DCE) devices. A single 8274 Multi-Protocol Serial Controller (MPSC) on the iSBC 286/10 board handles both channels. Channel A of the MPSC connects rack A and rack B of the RIU test set and provides the link between the test rack and the RPU in the panel test set. Channel B of the MPSC is dedicated to the console interface. Both channels are configured as follows:

NOTE that although the channels are configured to receive 8-bit characters, the 8274 interrupt handler masks the parity bit (most significant bit) of input characters.

2.1.4 IEEE-488 Interface

An iSBX 488 General Purpose Interface Bus (GPIB) Multimodule Board provides the IEEE-488 interface functions required by the universal firmware. The iSBX 488 board is attached to connector J5 (SBX2) of the SBC. The 8291A GPIB talker/listener chip is located in the 00AxH I/O address space; the 8292 GPIB controller chip is located in the 00BxH I/O address space. The iSBX 488 board has the following changes made to its factory-installed jumper configuration:

	  Pins		 Jumper
	--------	---------

	E1 - E9		installed	IEEE-488 device address = 10H.
	E2 - E10	installed		"
	E3 - E11	installed		"
	E4 - E12	installed		"
	E5 - E13	removed			"
	E6 - E14	installed	Enable talk address.
	E7 - E15	installed	Enable listen address.

	E8 - E16	installed	SBC is talker/listener; RPU is the GPIB
					controller (all test sets except panel
					test set).
	E8 - E16	removed		SBC is GPIB controller (panel test set
					only).

	E18 - E19	removed		Disconnect EOI signal from the 8292
					chip's COUNT input.
	E17 - E18	installed	Connect NDAC signal to the 8292 chip's
					COUNT input.

NOTE that jumper E8-E16 should be removed for the panel STE test set, where the SBC controls the IEEE-488 bus; the jumper should be installed for all the other test sets, where the RPU (i.e., the HP computer) controls the bus. NOTE also that factory-installed jumper E18-E19 (wire-wrapped) should be removed and jumper E17-E18 installed. When the SBC is the GPIB controller, it detects that a device addressed to talk is not present by timing-out on the 8292's COUNT input. Therefore, the most meaningful COUNT input is the IEEE-488 Not Data Accepted (NDAC) signal, and not the End of Input (EOI) signal. A final NOTE: if the IEEE-488 is not working at all, check and make sure that the ribbon cable is attached to the iSBX 488 board and not the SBC!

2.1.5 Interrupt Structure

The iSBC 286/10 computer has two 8259A Priority Interrupt Controllers (PIC) on board, one master PIC and one slave PIC. The PIC's are initialized by the power-up firmware (see MSUSBC.A86) and then re-initialized by the iRMX 286R operating system when it boots itself. Once iRMX 286R is up and running, the PIC's are handled by the operating system; user firmware should NOT fool around with them. The SBC has the following interrupt structure:

	80286 CPU:
		NMI - grounded
		INTR - connected to the master PIC

	Master 8259A PIC:
		Level	Vector	Connection
		-----	------	----------
		  0	  56	8254 PIT counter 0 (iRMX 286R interval timer)
		  1	  57	Multibus INT1
		  2	  58	Multibus INT2
		  3	  59	Multibus INT3
		  4	  60	Multibus INT4
		  5	  61	Multibus INT5
		  6	  62	8274 MPSC interrupt
		  7	  63	Slave PIC interrupt

	Slave 8259A PIC:
		Level	Vector	Connection
		-----	------	----------
		  0	 120	Multibus INT6
		  1	 121	Multibus INT7
		  2	 122	Multibus INT0 (LBX RAM parity error interrupt)
		  3	 123	SBX1/J6 MINTR0
		  4	 124	SBX1/J6 MINTR0
		  5	 125	SBX2/J5 MINTR0 (iSBX 488 8291A interrupt)
		  6	 126	SBX2/J5 MINTR0 (iSBX 488 8292 interrupt)
		  7	 127	Line printer interrupt

NOTE that Multibus interrupt level 0 has been disconnected from the CPU's non-maskable interrupt (NMI) and connected to slave PIC interrupt level 2; the NMI has been grounded. The interrupt vectors are assigned by RMX.

2.1.6 SBC Function Control

An 8255A Programmable Peripheral Interface (PPI) is used as a line printer interface (PPI ports A and B) and to control various functions on the SBC (PPI port C). PPI port C is initialized on power-up so as to release the Multibus interface, to enable NMI, and to place RS-232C channel A on-line. During normal program execution, PPI port C is also used to clear and re-enable timeout interrupts (the yellow LED) and to turn the two red LED's on and off. LED DS1 is turned on whenever the 8274 MPSC interrupt handler is invoked; the LED is turned off when the handler is exited. LED DS2 is turned on whenever the 8291A talker/listener interrupt handler is invoked; the LED is turned off when the handler is exited. The LED's are arranged on the SBC as follows:

                             .---.---.---.---.
                             | G | Y | R | R |
                             |___|___|___|___|
                              DS4 DS3 DS2 DS1

    G (green)  -  ON = SBC running, OFF = SBC halted (iRMX 286R idle state)
    Y (yellow) -  ON = Memory or I/O reference timeout
    R (red)    -  ON = IEEE-488 bus activity
    R (red)    -  ON = RS-232C or console serial link activity

A peculiarity in the iRMX 286R operating system sometimes causes red LED DS2 to stay on for an extended length of time. What happens is that the 8291A interrupt handler is invoked and turns the LED on. The handler then signals the operating system (RQ$SIGNAL$INTERRUPT). The operating system schedules other tasks for execution, without yet returning control to the interrupt handler. Thus, the LED stays on while other tasks execute. It appears that control is not returned to the interrupt handler until the system goes idle again. The interrupt handler then turns the LED off and exits. (This situation probably happens with red LED DS1, too, but the console/RS-232C activity has not been such that the problem is apparent.)

2.1.7 Timers

An 8254 Programmable Interval Timer (PIT) with a 1.23 MHz clock input supplies various timing signals to the iSBC 286/10 computer. Counter 0 of the 8254 PIT is used as an interval timer; it is configured by iRMX 286R to generate a timer interrupt every 10 msecs. Counters 1 and 2 act as 16X baud rate generators for the two 9600 baud RS-232C channels.

2.2 Software Configuration

Configuration of the universal firmware is more difficult than configuration of the hardware on which it runs, if only because the hardware personnel handled most of the modifications to the boards. The following sections describe how to build the universal firmware.

2.2.1 Configuring the iRMX 286R Operating System

Before the iRMX 286R operating system is used, it must be configured for the hardware and software environment it operates in. RMX is configured using the Intel-supplied Interactive Configuration Utility (ICU). A default configuration file (RMX286.DEF) for the iSBC 286/10 computer comes with the operating system package; the ICU generates a new configuration file when it is run. The ICU is used as follows:

    "RUN :F1:ICU86.86  :F4:RMX286.DEF TO :F4:NEWRMX.CFG"
    ... Sign-on Messages ...
    ... Command Menu ...
    "C"
    ... Sequence through the different screens and change those items that
    ... need to be changed.
    "S"
    ... Save the changes in the new configuration file.
    "L :F4:NEWRMX.DOC"
    ... Create a listing file to document how you configured RMX.
    "G"
    ... Generates a command file to build RMX according to your specifications.
    "E"
    ... Exits the ICU.

See the iRMX INSTALLATION AND CONFIGURATION GUIDE FOR RELEASE 6 for more information on using the ICU.

The configuration of iRMX 286R for the MILSTAR universal firmware is described in the following paragraphs. See the programmer's reference manuals and the configuration guides for more information about how to configure RMX. Asterisks have been placed beside those configuration options that are most likely to be changed.

2.2.1.1 Hardware

The RMX hardware environment is specified on the following ICU screen:

    Hardware
    (CPU) Processor used in the system              80286
    (OSP) 80130 Operating System Extension [Yes/No] No
    (TP)  8253/8254 Timer Port [0-0FFFFH]           00D0H
    (CIL) Clock Interrupt Level [0-7]               0000H
    (CN)  Timer Counter Number [0,1,2]              0000H
    (CI)  Clock Interval [0-0FFFFH msec]            000AH
    (CF)  Clock Frequency [0-0FFFFH khz]            04CDH
    (TPS) Timer Port Separation [0-0FFH]            0002H
    (NPX) Numeric Processor Extension [Yes/No]      No
    (IF)  Initialize iSBC 286/10 Functions [Yes/No] Yes

Most of the hardware parameters (including the interrupt structure below) were pre-defined in the default iSBC 286/10 configuration file.

2.2.1.2 Interrupts

The SBC interrupt structure is defined on the following screen:

    Interrupts
    (MP)  8259A Master Port [0-0FFFFH]              00C0H
    (MPS) Master PIC Port Separation [0-0FFH]       0002H
    (SIL) Slave Interrupt Levels [0-7/None]         7
          Slaves       0      1      2      3      4      5      6      7
          Ports      0000H  0000H  0000H  0000H  0000H  0000H  0000H  00C4H
          Separation 0000H  0000H  0000H  0000H  0000H  0000H  0000H  0002H
    (LSS) Level Sensitive Slaves [0-7/None]         None

2.2.1.3 Memory

Addresses F9B0:0 through FFFE:0 are available in ROM for the RMX code. Addresses C000:0 through C3FF:F are available in RAM (Local) for management by RMX. These areas of memory are specified on this screen:

    Memory
    Type : RAM = low, high
    Type : ROM = low, high
  * Type : RAM = C000H, C3FFH
  * Type : ROM = F9B0H, FFFEH

2.2.1.4 Sub-systems

None of the RMX sub-systems are used in the universal firmware:

    Sub-systems
    (UDI) Universal Development Interface [Yes/No]   No
    (HI)  Human Interface [Yes/No]                   No
    (AL)  Application Loader [Yes/No]                No
    (EIO) Extended I/O System [Yes/No]               No
    (BIO) Basic I/O System [Yes/No]                  No
    (SDB) System Debugger [Yes/No]                   No
    (DDB) Dynamic Debugger [Yes/No]                  No
    (TH)  Terminal Handler [Yes/No]                  No
    (CA)  Crash Analyzer [Yes/No]                    No

2.2.1.5 Nucleus

The RMX nucleus and the RMX root job are configured in the following screen:

    Nucleus
    (ASC) All Sys Calls [Yes/No]                     Yes
  * (PV)  Parameter Validation [Yes/No]              Yes
  * (ROD) Root Object Directory Size [0 - 0FF0h]     0000H
  * (MTS) Minimum Transfer Size [0-0FFFFH]           0080H
    (DEH) Default Exception Handler [Yes/No/Deb/Use] Yes
    (NEH) Name of Ex Handler Object Module [1-32chs]
    (EM)  Exception Mode [Never/Program/Environ/All] Never
  * (SRR) Start Root job from Reset [Yes/No]         No

All parameters passed to nucleus system calls are validated for correctness. The root job's object directory size is set to zero, since the MILSTAR firmware won't store any RMX objects in this directory. The minimum size for transfers of dynamically-allocated memory between jobs is set at 2048 bytes. Originally, the minimum transfer size was 1024 bytes, but memory fragmentation limited the number of tasks that could be created by the applications firmware (each task requires a stack allocated from the RMX-managed memory). The MILSTAR power-up initialization firmware is executed first after a reset; RMX is booted up later.

2.2.1.6 User Jobs

Parameters for the first level user job are defined here:

    User Jobs
    (NAM) Job Name [0-14 characters]                 user_job
  * (ODS) Object Directory Size [0-0FF0H]            0002H
  * (PMI) Pool Minimum [20H - 0FFFFH]                0080H
    (PMA) Pool Maximum [20H - 0FFFFH]                FFFFH
    (MOB) Maximum Objects [1 - 0FFFFH]               FFFFH
    (MTK) Maximum Tasks [1 - 0FFFFH]                 FFFFH
  * (MPR) Maximum Priority [0 - 0FFH]                0000H
    (AEH) Address of Exception Handler [CS:IP]       0000H:0000H
    (EM)  Exception Mode [Never/Prog/Environ/All]    Never
  * (PV)  Parameter Validation [Yes/No]              Yes
    (TP)  Task Priority [0-0FFH]                     009BH
  * (TSA) Task Start Address [CS:IP]                 F03CH:0021H
  * (DSB) Data Segment Base [0-0FFFFH]               0000H
  * (SSA) Stack Segment Address [SS:SP]              0000H:0000H
  * (SS)  Stack Size [0-0FFFFH]                      0180H
    (NPX) Numeric Processor Extension Used [Yes/No]  No

Two entries are reserved in the user job's object directory; only one is currently used (the RESET semaphore). Other object names used by the universal and applications firmware are stored in the test rack job's (created by the user job) object directory. Object directory sizes should be kept as small as possible because RMX actually reserves memory for the specified number of object names when creating a job. The pool minimum is based on the nucleus' minimum transfer size.

The maximum priority of tasks created by the job is the highest possible, 0. Note that interrupt service tasks have their priorities boosted by RMX after declaring an interrupt handler; if the new priority is greater than the job's maximum priority, an error will occur.

All parameters to RMX nucleus calls are validated. The user job's initial task's start address is a fixed location in the universal firmware's jump table; changes to the firmware do not require RMX to be re-configured. The initial task assigns its own data segment; RMX allocates a 432-byte stack for it. Guidelines for determining a task's minimum stack size can be found in the iRMX PROGRAMMER'S REFERENCE MANUAL FOR RELEASE 6, PART 2.

2.2.1.7 User Modules

No user modules are specified. This screen is only used for RAM-based systems:

    User Modules
    Module : 1-55 characters

2.2.1.8 ROM Code

The RMX nucleus and the root job are both placed in ROM:

    ROM code
    (NIR) Nucleus in ROM [Yes/No]                    Yes
    (RIR) Root Job in ROM [Yes/No]                   Yes

2.2.1.9 Includes and Libraries

The next screen tells the ICU where to find the compilers and libraries it needs to build the operating system:

    Includes and Libraries
    Path Name [1-45 Characters]
    (UDF) UDI Includes and Libs
                                /rmx86/udi/
    (HIF) Human Interface Includes and Libs
                                /rmx86/hi/
    (EIF) Extended I/O System Includes and Libs
                                /rmx86/eios/
    (ALF) Application Loader Includes and Libs
                                /rmx86/loader/
    (BIF) Basic I/O System Includes and Libs
                                /rmx86/bios/
    (SDF) System Debugger Includes and Libs
                                /rmx86/sdb/
    (THF) Terminal Handler and Dynamic Debugger Includes and Libs
                                /rmx86/th/
    (NUF) Nucleus and Root Job Includes and Libs
                                :f1:
    (ILF) Interface Libraries
                                :f1:
    (CAF) Crash Analyzer Includes and Libs
                                /rmx86/crash/
    (DTF) Development Tools Path Names
                                :f0:

2.2.1.10 Generate File Names

The absolute files (NUCLUS and ROOT) created by building RMX are stored on disk ":F4:"; the RAM code file name is specified for documentation purposes only:

    Generate File Names
    File Name [1-55 Characters]
    (ROP) ROM Code Prefix
                                :F4:
    (RAF) RAM Code File Name
                                :F1:NEWRMX.LIB

2.2.1.11 Building iRMX 286R

The "G" command of the ICU generates a number of assembly language programs and a command file used to build a version of RMX configured as you specified. For the example above, a file, NEWRMX.CSD, is created. To build RMX, submit the file for processing:

    - SUBMIT :F4:NEWRMX.CSD

Several assembly language routines are assembled and the nucleus and root job are linked and located. In general, the error messages generated by this process can be ignored (the configuration guide explains these errors, if you are interested). The root job file "ROOT" should be copied onto the monitor disk.

2.2.2 Building the Utility Routines

The MILSTAR utility firmware is a group of general purpose routines that are useful both to the universal firmware and to the applications firmware. The low-level console I/O and memory test routines were written in assembly language and are considered part of the MTEX-86 monitor and power-up firmware. The remaining utility routines were written in PL/M-86.

The procedure name of each utility routine in its source code is prefixed with the letters "MSU". The jump table has an entry for the prefix-less name that jumps to the prefixed name. For example, the jump table has an entry called "CREATE_SEMAPHORE" that contains a jump to routine "MSU$CREATE_SEMAPHORE". User-written firmware can then call "CREATE_SEMAPHORE"; the jump table directs control to the actual program code.

Building the utility routines consists of compiling the routines and collecting the object modules in a library file:

    RUN PLM86 :f4:addbin.plm OPTIMIZE(3)
    RUN PLM86 :f4:addout.plm OPTIMIZE(3)
    RUN PLM86 :f4:addq.plm   OPTIMIZE(3)
    RUN PLM86 :f4:arghex.plm OPTIMIZE(3)
    RUN PLM86 :f4:bindec.plm OPTIMIZE(3)
    RUN PLM86 :f4:binhex.plm OPTIMIZE(3)
    RUN PLM86 :f4:bldmsg.plm OPTIMIZE(3)
    RUN PLM86 :f4:checkb.plm OPTIMIZE(3)
    RUN PLM86 :f4:checkr.plm OPTIMIZE(3)
    RUN PLM86 :f4:chksum.plm OPTIMIZE(3)
    RUN PLM86 :f4:conin.plm  OPTIMIZE(3)
    RUN PLM86 :f4:conout.plm OPTIMIZE(3)
    RUN PLM86 :f4:crtask.plm OPTIMIZE(3)
    RUN PLM86 :f4:crtmbx.plm OPTIMIZE(3)
    RUN PLM86 :f4:crtseg.plm OPTIMIZE(3)
    RUN PLM86 :f4:crtsem.plm OPTIMIZE(3)
    RUN PLM86 :f4:decout.plm OPTIMIZE(3)
    RUN PLM86 :f4:delmsg.plm OPTIMIZE(3)
    RUN PLM86 :f4:delq.plm   OPTIMIZE(3)
    RUN PLM86 :f4:dubdec.plm OPTIMIZE(3)
    RUN PLM86 :f4:examq.plm  OPTIMIZE(3)
    RUN PLM86 :f4:getarg.plm OPTIMIZE(3)
    RUN PLM86 :f4:getstr.plm OPTIMIZE(3)
    RUN PLM86 :f4:hexbin.plm OPTIMIZE(3)
    RUN PLM86 :f4:hexout.plm OPTIMIZE(3)
    RUN PLM86 :f4:initq.plm  OPTIMIZE(3)
    RUN PLM86 :f4:lenq.plm   OPTIMIZE(3)
    RUN PLM86 :f4:lkpobj.plm OPTIMIZE(3)
    RUN PLM86 :f4:lkpsym.plm OPTIMIZE(3)
    RUN PLM86 :f4:nibbin.plm OPTIMIZE(3)
    RUN PLM86 :f4:printq.plm OPTIMIZE(3)
    RUN PLM86 :f4:prtmem.plm OPTIMIZE(3)
    RUN PLM86 :f4:prtmsg.plm OPTIMIZE(3)
    RUN PLM86 :f4:sndsig.plm OPTIMIZE(3)
    RUN PLM86 :f4:stsout.plm OPTIMIZE(3)
    RUN PLM86 :f4:watred.plm OPTIMIZE(3)
    RUN PLM86 :f4:wrdsel.plm OPTIMIZE(3)
    ;
    RUN LIB86
    CREATE :f4:msutil.lib
    ADD :f4:addbin.obj TO :f4:msutil.lib
    ADD :f4:addout.obj TO :f4:msutil.lib
    ADD :f4:addq.obj   TO :f4:msutil.lib
    ADD :f4:arghex.obj TO :f4:msutil.lib
    ADD :f4:bindec.obj TO :f4:msutil.lib
    ADD :f4:binhex.obj TO :f4:msutil.lib
    ADD :f4:bldmsg.obj TO :f4:msutil.lib
    ADD :f4:checkb.obj TO :f4:msutil.lib
    ADD :f4:checkr.obj TO :f4:msutil.lib
    ADD :f4:chksum.obj TO :f4:msutil.lib
    ADD :f4:conin.obj  TO :f4:msutil.lib
    ADD :f4:conout.obj TO :f4:msutil.lib
    ADD :f4:crtask.obj TO :f4:msutil.lib
    ADD :f4:crtmbx.obj TO :f4:msutil.lib
    ADD :f4:crtseg.obj TO :f4:msutil.lib
    ADD :f4:crtsem.obj TO :f4:msutil.lib
    ADD :f4:decout.obj TO :f4:msutil.lib
    ADD :f4:delmsg.obj TO :f4:msutil.lib
    ADD :f4:delq.obj   TO :f4:msutil.lib
    ADD :f4:dubdec.obj TO :f4:msutil.lib
    ADD :f4:examq.obj  TO :f4:msutil.lib
    ADD :f4:getarg.obj TO :f4:msutil.lib
    ADD :f4:getstr.obj TO :f4:msutil.lib
    ADD :f4:hexbin.obj TO :f4:msutil.lib
    ADD :f4:hexout.obj TO :f4:msutil.lib
    ADD :f4:initq.obj  TO :f4:msutil.lib
    ADD :f4:lenq.obj   TO :f4:msutil.lib
    ADD :f4:lkpobj.obj TO :f4:msutil.lib
    ADD :f4:lkpsym.obj TO :f4:msutil.lib
    ADD :f4:nibbin.obj TO :f4:msutil.lib
    ADD :f4:printq.obj TO :f4:msutil.lib
    ADD :f4:prtmem.obj TO :f4:msutil.lib
    ADD :f4:prtmsg.obj TO :f4:msutil.lib
    ADD :f4:sndsig.obj TO :f4:msutil.lib
    ADD :f4:stsout.obj TO :f4:msutil.lib
    ADD :f4:watred.obj TO :f4:msutil.lib
    ADD :f4:wrdsel.obj TO :f4:msutil.lib
    LIST :f4:msutil.lib
    EXIT

Rather than typing in each of those commands, you can just enter the following:

    "SUBMIT :F4:MSUTIL.BLD"

After it is created, the MSUTIL.LIB library file should be copied onto the MTEX-86 monitor disk.

2.2.3 Building the MTEX-86 Monitor and Power-up Initialization Firmware

The monitor and power-up initialization firmware includes the MTEX-86 monitor, some low-level console I/O routines, a memory test routine, and the power-up/reset initialization firmware. Building this firmware requires compiling and assembling the routines, linking to the utility routine library, and locating the code:

    RUN ASM86 :f4:memtst.a86
    RUN ASM86 :f4:msucio
    RUN ASM86 :f4:msujmp.a86
    RUN ASM86 :f4:msumon.a86
    RUN ASM86 :f4:msurst.a86
    RUN ASM86 :f4:msusbc.a86
    RUN PLM86 :f4:disasm.plm OPTIMIZE(3)
    ;
    RUN LINK86 &
    	:f1:rpifl.lib &
    		(VERSION6P0, RQLACN, RQLACP, RQLCCP, RQLCET, &
    		RQLCJB, RQLCMB, RQLCOB, RQLCRG, RQLCSG, RQLCSM, &
    		RQLCTK, RQLDCP,	RQLDDL, RQLDEX, RQLDJB, RQLDRG, &
    		RQLDSA, RQLDSG, RQLDTK, RQLEDL, RQLEIN, RQLENB, &
    		RQLFDL, RQLGEH, RQLGPA, RQLGPR, RQLGSZ, RQLGTP, &
    		RQLGTT, RQLICP, RQLLUO, RQLOFF, RQLRCL, RQLRIN, &
    		RQLRMS, RQLRTK, RQLRUN, RQLSCL, RQLSEH, RQLSIN, &
    		RQLSLP, RQLSMS, RQLSOE, RQLSPM, RQLSPR, RQLSTK, &
    		RQLSUN, RQLUCO, RQLEXI, RQLDMB, RQLDSM, RQLSIG, &
    		RQLWTI, RQLSEX, RQLGLV, RQLERR, RQLR04, RQLR06, &
    		RQLR08, RQLR10, RQLR12, RQLR14, RQLR20, RQLR40, &
    		INITTASKSIGNAL), &
    	:f4:msujmp.obj, &
    	:f4:msumon.obj, &
    	:f4:msurst.obj, &
    	:f4:msusbc.obj, &
    	:f4:disasm.obj, &
    	:f4:memtst.obj, &
    	:f4:msucio.obj, &
    	:f4:msutil.lib, &
    	PUBLICSONLY (:f4:root) &
    	TO :f4:msumru.lnk &
    	ASSIGN (UserJobStartAddress (0F3802H))
    ;
    RUN LOC86 &
    	:f4:msumru.lnk TO :f4:msumru &
    	ORDER (CLASSES (DATA (monitor_data), STACK, MEMORY, &
    			CODE (code, msujmp_code))) &
    	ADDRESSES (SEGMENTS (ffff0_code (0FFFF0H)), &
    		CLASSES (DATA (000400H), CODE (0F0000H))) &
    	SEGSIZE (STACK (0)) &
    	NOINITCODE &
    	OBJECTCONTROLS (PUBLICS, NOLINES, NOCOMMENTS, NOSYMBOLS)

Submit file "MSUMRU.BLD" contains these same commands. During the LOCATE process, ignore the warning about the lack of a start address.

All the modules in the RMX interface libary (RPIFL.LIB) are explicitly named in the LINK statement so as to include all of them in the link file. If these modules were not specified explicitly, only those modules referenced by the universal firmware would be included.

The "PUBLICSONLY (:f4:root)" statement extracts the start address of the root job, so that the power-up initialization firmware knows where to jump to to start up RMX. Label USERJOBSTARTADDRESS is the start of the universal firmware and is assigned an address explicitly (determined from a universal firmware map listing). You could do a "PUBLICSONLY" on the universal firmware absolute file, but since the universal firmware does a "PUBLICSONLY" on MSUMRU, you have the chicken-before/after-the-egg problem.

NOTE the ordering of the segments when locating the CODE class. The CODE segment is the name of the RMX interface library code segment; MSUJMP_CODE is the name of the jump table code segment; the remaining code is located after these segments (see the Memory Map section below). NOTE the "PUBLICS" clause in the LOCATE command. This makes the entry points of the RMX system calls and the universal utility routines available to other programs that are linked using a "PUBLICSONLY (msumru)" statement.

2.2.4 Building the Universal Firmware

The universal firmware consists of the first level user job created by RMX and the test rack job created by the user job. The test rack job includes the I/O interfacing tasks, etc. Building the universal firmware involves compiling the programs, linking to the utility routines and to RMX via the MSUMRU absolute file, and locating the firmware:

    RUN PLM86 :f4:devlst.plm OPTIMIZE(3)
    RUN PLM86 :f4:downfw.plm OPTIMIZE(3)
    RUN PLM86 :f4:drv232.plm OPTIMIZE(3)
    RUN PLM86 :f4:drv488.plm OPTIMIZE(3)
    RUN PLM86 :f4:drvcon.plm OPTIMIZE(3)
    RUN PLM86 :f4:ih232.plm  OPTIMIZE(3)
    RUN PLM86 :f4:ih8274.plm OPTIMIZE(3)
    RUN PLM86 :f4:ih8291.plm OPTIMIZE(3)
    RUN PLM86 :f4:ih8292.plm OPTIMIZE(3)
    RUN PLM86 :f4:ihcon.plm  OPTIMIZE(3)
    RUN PLM86 :f4:ihprty.plm OPTIMIZE(3)
    RUN PLM86 :f4:in488.plm  OPTIMIZE(3)
    RUN PLM86 :f4:in8274.plm OPTIMIZE(3)
    RUN PLM86 :f4:inptlk.plm OPTIMIZE(3)
    RUN PLM86 :f4:is8274.plm OPTIMIZE(3)
    RUN PLM86 :f4:ist232.plm OPTIMIZE(3)
    RUN PLM86 :f4:ist488.plm OPTIMIZE(3)
    RUN PLM86 :f4:istcon.plm OPTIMIZE(3)
    RUN PLM86 :f4:istsyc.plm OPTIMIZE(3)
    RUN PLM86 :f4:isttlc.plm OPTIMIZE(3)
    RUN PLM86 :f4:outlis.plm OPTIMIZE(3)
    RUN PLM86 :f4:rifcmd.plm OPTIMIZE(3)
    RUN PLM86 :f4:rpuift.plm OPTIMIZE(3)
    RUN PLM86 :f4:spcfnc.plm OPTIMIZE(3)
    RUN PLM86 :f4:spoll.plm OPTIMIZE(3)
    RUN PLM86 :f4:sycmd.plm OPTIMIZE(3)
    RUN PLM86 :f4:takctl.plm OPTIMIZE(3)
    RUN PLM86 :f4:tirjob.plm OPTIMIZE(3)
    RUN PLM86 :f4:uii.plm    OPTIMIZE(3)
    RUN PLM86 :f4:usrjob.plm OPTIMIZE(3)
    RUN PLM86 :f4:usrman.plm OPTIMIZE(3)
    RUN PLM86 :f4:wt8292.plm OPTIMIZE(3)
    RUN PLM86 :f4:xfrdev.plm OPTIMIZE(3)
    ;
    RUN LINK86 &
    	:f4:usrjob.obj, &
    	:f4:devlst.obj, &
    	:f4:downfw.obj, &
    	:f4:drv232.obj, &
    	:f4:drv488.obj, &
    	:f4:drvcon.obj, &
    	:f4:ih232.obj,  &
    	:f4:ih8274.obj, &
    	:f4:ih8291.obj, &
    	:f4:ih8292.obj, &
    	:f4:ihcon.obj,  &
    	:f4:ihprty.obj, &
    	:f4:in488.obj,  &
    	:f4:in8274.obj, &
    	:f4:inptlk.obj, &
    	:f4:is8274.obj, &
    	:f4:ist232.obj, &
    	:f4:ist488.obj, &
    	:f4:istcon.obj, &
    	:f4:istsyc.obj, &
    	:f4:isttlc.obj, &
    	:f4:outlis.obj, &
    	:f4:rifcmd.obj, &
    	:f4:rpuift.obj, &
    	:f4:spcfnc.obj, &
    	:f4:spoll.obj, &
    	:f4:sycmd.obj, &
    	:f4:takctl.obj, &
    	:f4:tirjob.obj, &
    	:f4:uii.obj,    &
    	:f4:usrman.obj, &
    	:f4:wt8292.obj, &
    	:f4:xfrdev.obj, &
    	PUBLICSONLY (:f1:msumru) &
    	TO :f4:msuniv.lnk
    ;
    RUN LOC86 &
    	:f4:msuniv.lnk TO :f4:msuniv &
    	ORDER (CLASSES (DATA, STACK, MEMORY, CODE)) &
    	ADDRESSES (CLASSES (DATA (000600H), CODE (0F3800H))) &
    	SEGSIZE (STACK (0)) &
    	NOINITCODE &
    	OBJECTCONTROLS (NOLINES,NOCOMMENTS,NOPUBLICS,NOSYMBOLS)

Submitting file "MSUNIV.BLD" is easier than typing in these commands by hand. There is one problem, though. An 8" floppy disk can hold the source code, the object code, and the link, locate, and map files. The list files, however, take up too much room; delete them before you link and locate (maybe before, if necessary). The size of the STACK segment is reduced to zero because RMX allocates the stacks for the universal firmware tasks; for the same reason, "NOINITCODE" is used. During the LOCATE process, ignore the warning messages about the stack size and the lack of a start address.

2.2.5 Burning the Firmware into Read-Only Memory

To burn the firmware into PROM's, you must first erase two 27256 32K PROM's. To do this, place the PROM's in the ultraviolet eraser for about 25 minutes. While the PROM's are erasing, convert the LOCATE'd firmware files into Intel ASCII hex files:

    RUN OH86 :f4:msumru TO :f4:msumru.hex
    RUN OH86 :f4:msuniv TO :f4:msuniv.hex
    RUN OH86 :f4:nuclus TO :f4:nuclus.hex
    RUN OH86 :f4:root   TO :f4:root.hex

Now, insert the PROM programmer module into the DATA I/O 29B programmer. Using an RS-232C cable, connect the DATA I/O port to serial port 1 on the Intel SERIES II computer. Turn the DATA I/O on, and wait for it to complete its self-test. The next step is to download the hex code into the DATA I/O. Run TERM6 on the SERIES II (channel 1, 9600 baud). On both machines, enter the following commands:

    DATA I/O:
	"SELECT, B3, 88, START, START"	(Selects Intel hex file format)
	"SELECT, A2, FF, START"		(Fill DATA I/O RAM with all FF's)
					(Copy data from port to RAM.)
	"COPY, PORT, F0000, START, 0, START, RAM, 0, START"

    SERIES II:
	TERM6> O			(Output the hex file to the serial port)
	Output File Name? MSUMRU.HEX

    DATA I/O:
	(Watch the clock go around and around until the download is complete!)
					(Copy data from port to RAM.)
	"COPY, PORT, F0000, START, 0, START, RAM, 0, START"

    SERIES II:
	TERM6> O			(Output the hex file to the serial port)
	Output File Name? MSUNIV.HEX

    DATA I/O:
	(Watch the clock go around and around until the download is complete!)
					(Copy data from port to RAM.)
	"COPY, PORT, F0000, START, 0, START, RAM, 0, START"

    SERIES II:
	TERM6> O			(Output the hex file to the serial port)
	Output File Name? NUCLUS.HEX

    DATA I/O:
	(Watch the clock go around and around until the download is complete!)
					(Copy data from port to RAM.)
	"COPY, PORT, F0000, START, 0, START, RAM, 0, START"

    SERIES II:
	TERM6> O			(Output the hex file to the serial port)
	Output File Name? ROOT.HEX

    DATA I/O:
	(Watch the clock go around and around until the download is complete!)
	"SELECT, A5, START"		(Split the contents in RAM, placing all
					 the even-addressed bytes in the lower
					 32K of RAM and all the odd-addressed
					 bytes in the upper 32K of RAM.)

Remove the PROM's from the eraser and label one of them EVEN and the other ODD. Now, program the PROM's:


    DATA I/O:
					(Copy even-address bytes from RAM to
					 the EVEN PROM.)
	"COPY, RAM, 0, START, 8000, START, DEVICE, 0, START, C132"
	(Place the EVEN PROM in the socket whose LED is lit.)
	"START"
	(The PROM will be tested, programmed, and verified.  When done, note
	 down the 4-digit hex number displayed; this is the checksum for the
	 EVEN PROM.)
					(Copy odd-address bytes from RAM to
					 the ODD PROM.)
	"COPY, RAM, 8000, START, 8000, START, DEVICE, 0, START, C132"
	(Place the ODD PROM in the socket whose LED is lit.)
	"START"
	(The PROM will be tested, programmed, and verified.  When done, note
	 down the 4-digit hex number displayed; this is the checksum for the
	 ODD PROM.)

	"SELECT, B1, START"		(Displays the checksum for the two
					 PROM's combined.)

You're done! Insert the PROM's into their sockets on the SBC and power-up!

2.2.6 Memory Map

The distribution of code and data in the SBC's memory is as follows:

   RAM	00000H - 003FFH		Interrupt Vector Table - Initialized by the
				power-up firmware and modified by RMX.
	00400H - 0054BH		Monitor Data
	0054CH - 0054DH		Utility Routines Data
	00600H - 00D42H		Universal Firmware Data
	C0000H - C0001H		RMX Nucleus Data
	C0020H - C015DH		RMX Root Job Data and Stack
	C????H - C3FFFH		RMX-managed RAM

  PROM	F0000H - F03C6H		RMX Interface Code
	F03C8H - F04ADH		Jump Table
	F04AEH - F04DAH		Initial Task Signal Code - RMX call used only
				by the universal firmware.
	F04DCH - F1A8AH		Monitor and Power-Up Firmware Code
	F1A8CH - F37B1H		Utility Routines Code
	F3800H - F9ACBH		Universal Firmware Code
	F9B00H - FFAB5H		RMX Nucleus Code
	FFAE0H - FFE50H		RMX Root Job
	FFFF0H - FFFF4H		Hardware Reset Code

The RMX interface code and the initial task signal code are from the Intel-supplied RMX interface library, RPIFL.LIB. Locating the RMX interface code below the jump table means that new subroutines can be added to the end of the jump table without affecting the locations of the RMX interface entry points or of the old entries in the jump table. In other words, applications firmware linked to a particular version of the universal PROM's remains compatible with new versions of the PROM's. Locating the RMX initial task signal code after the jump table was an oversight, but this call should only be used by the first-level, universal user job, which is in PROM.

You might notice the gap between the RMX root job and the hardware reset code. Using a base address greater than F9B00H caused the RMX ICU to locate the nucleus in PROM and the root job down in RAM! The ICU probably estimates the size of the RMX modules.

There are some other unused areas of memory in the PROM's. If you make changes to the PROM'ed firmware and find yourself running out of space, there are some sections of the code that you could cut out. The IEEE-488 transfer between devices routine (XFRDEV.PLM) will probably not be used (although it works!). The monitor disassembler is a nice feature, but not necessary. The help commands could be deleted from the monitor and the universal firmware, or the amount of help text could be reduced. The debug output in the universal firmware (primarily in the IEEE-488 code) could be deleted.

 

3 Universal Firmware Design

In order to take full advantage of the capabilities of the universal firmware, it helps to have a general understanding of the design of the firmware. The following sections look at the high-level structure of the firmware, with some low-level details given as necessary.

3.1 Power-up and Initialization

When electricity first surges through the veins of the SBC, the 80286 CPU is reset and the first instruction executed is at address FFFF0H. This instruction is simply a jump to the start of the power-up and initialization firmware. The CPU's registers are set up and then the SBC's hardware functions are initialized. These hardware functions include the RS-232C interfaces, the timers, and the interrupt controllers.

Following the board initialization, the expected areas of RAM are tested and the test statuses are saved in the monitor data area (where the universal firmware can access them when returning that information to the RPU). Testing memory zeroes out the tested memory. The following memory test statuses are collected (the upper 32K of dual port RAM and the "pong" LBX RAM are only present in the IOC test set):

              Addresses        Status          Description
          ----------------    ---------    ----------------------
           00000H - 07FFFH    Pass/Fail    Dual Port RAM (32K)
           08000H - 0FFFFH    Pass/Fail    Dual Port RAM (32K)
           C0000H - C3FFFH    Pass/Fail    Local RAM (16K)
          030000H - AFFFFH    Pass/Fail    LBX RAM, "ping" (512K)
          830000H - AFFFFH    Pass/Fail    LBX RAM, "pong" (512K)

Upon completion of the memory testing, a flag is set in memory to inhibit testing memory again after a hardware reset. The flag is assigned a value of 55AAH, a value unlikely to occur on power-up. The memory test routine is available as a utility routine for use by the applications firmware.

Next, the monitor data structures are reset to their initial state. The interrupt vector table is then initialized so that all vectors point into the monitor. Finally, the power-up and initialization firmware exits by jumping to the start of the RMX root job, which will bring up RMX.

3.2 iRMX 286R Operating System

The capabilities and limitations of the iRMX 286R operating system had a large impact on the design of the universal firmware. RMX is intended for real-time, multi-tasking applications, but the limitations of the operating system made implementation awkward in some places. The following paragraphs discuss some of the basics concepts of RMX and their utilization in the universal firmware.

3.2.1 iRMX Objects

The foundation of RMX is the object. An RMX object is identified by a 16-bit word called a "token". Typical RMX objects include jobs, tasks, memory segments, semaphores, and mailboxes. Routines in the Nucleus allow you to associate names with tokens (RQ$CATALOG$OBJECT) and tokens with names (RQ$LOOKUP$OBJECT). The name-token relationships are stored in a job's object directory and are thus available to all the tasks in the job. This capability allows multiple tasks to access the same semaphore or mailbox using an agreed-upon name.

3.2.2 iRMX Jobs

RMX jobs are used to logically group tasks and resources. An RMX job consists of an initialization task that is activated when the job is created, subtasks that must be created by the initialization task or its children, and the resources associated with the job. Resources (i.e., memory segments, semaphores, and mailboxes) utilized by a task are taken from and returned to the resources of the job.

Jobs are hierarchically structured. At the top of the hierarchy is the "root" job; at the next level down are the "first level" jobs. The Intel-supplied root job is automatically created when RMX starts up and is responsible for initializing the Nucleus and creating the first level jobs (RQ$CREATE$JOB). The first level jobs include a Basic Input/Output System initialization job, a System Debugger initialization job, and one or more user jobs (the jobs to be created by the root job are specified when the operating system is configured).

The TIR firmware requires only a single first-level job, consisting solely of an initialization and reboot task. Called the user job, this job will in turn create a child job, the test rack job, consisting of an initialization and download task, the interface tasks, and the application tasks. The purpose of this two level user job hierarchy is to provide a simple means of deleting tasks and deallocating resources when performing a "soft" reset (deleting the child job automatically deletes all resources allocated to that job).

3.2.3 iRMX Tasks

RMX tasks are stand-alone programs that perform various functions. The distribution of functions among tasks and the functional scope of a particular task are determined by the nature of the functions to be performed. For example, in the universal firmware, I/O functions for different devices are allocated to separate tasks; in the applications firmware, time-critical board interface functions are allocated to separate tasks.

Associated with an RMX task are its state, its priority, its stack, and its allocated resources. A task may be executing, ready for execution, or suspended while waiting on mailboxes, semaphores, timers, and interrupts. Task priorities can be manipulated (RQ$SET$PRIORITY) to give critical processing priority over less-critical processing. Because RMX is event-driven, a high-priority ready task cannot pre-empt a low-priority executing task until an event (i.e., an interrupt) occurs. Each task has a stack that can be statically allocated when the task is linked and located, or (preferably) dynamically allocated from the job's memory pool when the task is created. A task's resources include its stack and any memory segments, semaphores, or mailboxes it has created.

Task synchronization and inter-task communication are accomplished using common memory, semaphores, and mailboxes. The PL/M-86 language includes a function (LOCKSET) that provides an indivisible read-and-set access to common memory. RMX handles memory segments, semaphores, and mailboxes. An RMX task has the capability to create other tasks (RQ$CREATE$TASK).

3.2.4 iRMX Segments

RMX provides programs with the ability to dynamically allocate and deallocate segments of memory. The sections of RAM to be managed by RMX are specified when RMX is configured. A segment is known by its token, or "selector", which determines its base address in memory; segments must be a minimum of 16 and a maximum of 65,536 (64K) bytes long. Utilization of the memory management capabilities of RMX in the MILSTAR firmware include implicit allocation/deallocation of a stack segment when a task is created/deleted and explicit allocation/deallocation of a memory segment when a mailbox message is sent/received.

3.2.5 iRMX Semaphores

Semaphores are counters of abstract units. They may be used to ensure mutually exclusive access to resources and to synchronize concurrent tasks. RMX allows you to create and delete semaphores, catalog them by name in the job's object directory, lookup a semaphore in the job's object directory, wait on the semaphore for a particular number of units to be available, and return a particular number of units to the semaphore. Semaphores are used in the MILSTAR firmware for signalling and mutual exclusion.

3.2.6 iRMX Mailboxes

Mailboxes are a means of passing information and/or control between tasks. RMX allows you to create and delete mailboxes, catalog them by name in the job's object directory, lookup a mailbox in the job's object directory, wait on a mailbox for a message to be received, and send a message to a mailbox. The "message" that is passed via an RMX mailbox is actually a token; the token can be the identifier for any RMX object.

3.2.7 iRMX Timers

There are two methods of accessing timers in RMX. The first is to specify a time-out period when waiting on a semaphore or a mailbox. The second is to put yourself to sleep for a specified period of time using the RQ$SLEEP nucleus call. The length of the clock "ticks" used to specify time periods is 10 milliseconds.

3.2.8 iRMX Interrupt Handling

RMX allows a program to declare an interrupt handling routine that is to be invoked when an interrupt at a certain level occurs, and, optionally, an interrupt task that is to be associated with the interrupt handler.

An interrupt handler is declared and assigned to an interrupt level by the RQ$SET$INTERRUPT nucleus call; the handler can be deassigned using the RQ$RESET$INTERRUPT call. When the interrupt handler is invoked following an interrupt, it can only make a very restricted set of nucleus calls. RQ$ENTER$INTERRUPT allows the interrupt handler to obtain access to a data segment specified when the handler was declared; this protects the current data segment of the interrupted task. RQ$EXIT$INTERRUPT sends an end-of-interrupt signal to the hardware prior to returning from the interrupt handler (at which point interrupts are re-enabled). These are the only two nucleus calls that an interrupt handler is allowed to make.

Because an interrupt handler is restricted in its use of the RMX nucleus, applications requiring other nucleus calls in response to interrupts can associate an interrupt task with the interrupt handler. The interrupt task is the task that declares the interrupt handler; whether or not the task is considered an interrupt task is governed by a flag passed to the RQ$SET$INTERRUPT routine. An interrupt task is put to sleep by calling the RQ$WAIT$INTERRUPT routine. The associated interrupt handler, when invoked, can call either RQ$EXIT$INTERRUPT or RQ$SIGNAL$INTERRUPT. RQ$EXIT$INTERRUPT exits the interrupt normally. RQ$SIGNAL$INTERRUPT wakes up the interrupt task, allowing it to do any interrupt processing that requires access to the complete nucleus. In the MILSTAR universal firmware, for example, the I/O interrupt handlers call RQ$EXIT$INTERRUPT when simply inputting or outputting a data byte; the interrupt task remains asleep. When the end of the input data record is detected or the output buffer is exhausted, the interrupt handler signals the interrupt task using RQ$SIGNAL$INTERRUPT. The interrupt task can then process the input data or initiate more data output.

3.2.9 Waiting on Multiple Events

Real-time, multi-tasking systems like the MILSTAR test rack firmware require the ability to respond to multiple, asynchronous events. RMX has many capabilities, but waiting on multiple events is not one of them. A task can wait on a semaphore, a mailbox, a timer, or an interrupt, but not on more than one at a time. Some programming contortions are needed in order to get around this limitation of RMX. One possible method of accomplishing this depends on the type of events to be fielded.

A "pollable" RMX event is an event for which a time-out period of zero can be specified when requesting a wait on the event. Waiting on semaphores and mailboxes are pollable events. If the semaphore units are not immediately available or no mailbox message is ready, then no wait occurs and an error status is returned to the calling task. Polling allows you to sequentially check if any of several events has occurred.

A "non-pollable" RMX event is an event for which no time-out is possible while waiting on the event. Timers and interrupts are examples of non-pollable events. If you're sleeping on a timer, you can't wake up until the alarm goes off. Once you wait on an interrupt, you're suspended until the interrupt occurs (if it ever does). You can't directly check to see if any of several non-pollable events has occurred.

To simulate a task waiting on multiple events, you must do the following:

  1. Create a special semaphore for the task that indicates an event has occurred
  2. Keep all the pollable events in the task
  3. Create a separate subtask and a separate semaphore or mailbox for each non-pollable event

The special semaphore is used to indicate that some event has occurred that the task is interested in. Any external task that initiates one of these events (i.e., sending a mailbox message or signalling another semaphore) must signal this special semaphore. The subtasks for the non-pollable events (i.e., timers and interrupts) must also signal the special semaphore when their event has occurred. (Since an interrupt handler can't signal a semaphore, an interrupt task is required.)

The above techniques are used extensively in the MILSTAR universal firmware. For example, the I/O driver tasks must be prepared for two types of events to occur. I/O requests may be received from the RPU interface task and I/O completions may be received from the driver's interrupt service task. A special semaphore, XXX_EXCHANGE, is used to solve this problem. For each I/O request, the RPU interface task mails the request to the driver task and signals the exchange semaphore. For each I/O completion, the interrupt service task adds the operation to the completion queue and signals the exchange semaphore. The driver task waits on the exchange semaphore. Each time the semaphore is signalled, the driver task polls its request mailbox and its completion queue to see what needs to be processed.

3.3 Utility Routines

The MILSTAR universal firmware includes a set of utility routines that are proven beneficial to the programs that use them. These utilities reduce the size of programs because the utilities are general purpose, they generate their own error messages, and they reside in PROM. The RMX-related utilities provide a simpler, less error-prone interface to the iRMX 286R operating system. The console I/O utilities give the user formatted I/O capabilities. The queue utilities separate the calling program from the implementation details of queues.

3.4 Universal Firmware

3.5 MTEX-86 Monitor

 

4 iRMX 286R Functions

 

5 Utility Routines

The universal firmware utility routines are described in the following paragraphs. For more detailed information about them, the reader should examine their source code.

In order to reference any of the utility routines, the applications firmware should include the following statement in its modules:

                    /* External procedures. */
    $   INCLUDE (:F1:MSUPRC.EXT)

NOTE that all the utility routines are reentrant and their local variables are temporarily stored on the stack. There is only one global variable, CREATE_SEGMENT's MEMORY$WAIT, which holds the RMX token for the memory allocation scheduling semaphore.

NOTE that the binary-hex/hex-binary conversion routines are recursive; i.e., converting a double word is the same as converting two words, and converting a word is the same as converting two bytes. Watch your stack!

Most of the utility routines follow the RMX conventions when returning statuses; i.e., E$OK (zero) means no error, anything else indicates an error. Routines that return tokens return a null token (zero) if an error occurs.

5.1 Console I/O and Formatted Output Utilities

ADDRESS_OUT converts an address to ASCII hexadecimal format ("XXXX:YYYY") and outputs it to the console.

    CALL address_out (addr) ;

CI waits for a character to be entered at the console and inputs it. The parity bit is NOT masked.

    input_char = ci ;

CO outputs a character to the console. CO also inputs any character entered at the keyboard while CO is waiting to output the character. A control-C puts you in the monitor. Control-S and control-Q suspend and resume output, respectively. Other characters are ignored.

    CALL co (output_char) ;

CONSOLE_IN inputs a buffer of characters from the console keyboard using utility routine CI. The calling routine can specify a prompt to be displayed on the screen. Characters are input and echoed until a carriage return is entered; limited line editing is possible.

    CALL console_in (@prompt, @input_buffer, size, @length) ;

CONSOLE_OUT outputs a string of characters to the console screen using utility routine CO.

    CALL console_out (@string, length) ;

COO outputs a character to the console. COO does NOT check the keyboard for data input. COO should be used when the calling program wishes to handle the control characters.

    CALL coo (output_char) ;

CSTS checks if a character has been entered at the keyboard and is waiting to be read; CSTS returns immediately.

    is_available = csts ;

DEC_OUT converts a binary byte or word into its ASCII decimal representation and outputs it to the console. The binary number can be interpreted as signed or unsigned. The field width can be specified; if necessary, leading zeroes are inserted.

    CALL dec_out (@item, data_type, field_width) ;

HEX_OUT converts a binary byte, word, or double word into its ASCII hexadecimal representation and outputs it to the console. The output ASCII number is ordered from the most significant byte to the least significant byte (i.e., the same way you would specify it in a PL/M-86 program).

    CALL hex_out (@item, data_type) ;

STATUS_OUT outputs a status message to the terminal with the status word converted to ASCII hexadecimal format; the status message is followed by a carriage return and line feed.

    CALL status_out (@status) ;

5.2 Conversion Utilities

ADDRESS_TO_BINARY converts a free-format ASCII address string to its binary pointer value.

    CALL address_to_binary (@string, length, @addr, @status) ;

BINARY_TO_DECIMAL converts a binary byte or word into its ASCII decimal representation. The binary number can be interpreted as signed or unsigned. The field width can be specified; if necessary, leading zeroes are inserted.

    CALL binary_to_decimal (@binary_value, data_type,
                            @ASCII_buffer, field_width) ;

BINARY_TO_HEX converts a buffer of binary bytes, words, or double words into their ASCII hexadecimal representation. The ASCII representation of each value is ordered from the most significant byte to the least significant byte (i.e., the same way you would specify it in a PL/M-86 program).

    CALL binary_to_hex (data_type, num_items, @binary_buffer, @ASCII_buffer) ;

GET_ARG is an applications firmware utility routine that finds the requested argument in an applications firmware command message and converts it from ASCII decimal to binary.

    value = get_arg (argument_number, @command_text, command_length) ;

GET_ARG_H is an applications firmware utility routine that finds the requested argument in an applications firmware command message and converts it from ASCII hexadecimal to binary. The requested argument can actually be a whole set of ASCII hexadecimal numbers.

    CALL get_arg_h (argument_number, @command_text, command_length, @table) ;

HEX_TO_BINARY translates a buffer of ASCII hexadecimal numbers into their binary byte, word, or double word representation. The ASCII representation of each value is ordered from the most significant byte to the least significant byte (i.e., the same way you would specify it in a PL/M-86 program).

    CALL hex_to_binary (data_type, num_items, @ASCII_buffer, @binary_buffer) ;

NIBBLE_TO_BINARY converts an ASCII hexadecimal character ('0'-'9', 'A'-'F') to its binary representation (4 bits).

    value = nibble_to_binary (char) ;

WORD_TO_SELECTOR is passed an argument of type WORD and returns that same argument with type SELECTOR. It is useful when you need to perform calculations on a segment value (which requires the WORD type) and must then construct a POINTER using the segment value (which requires the SELECTOR type). An example of this is converting an input ASCII hexadecimal number to a binary POINTER value.

    selector_value = word_to_selector (word_value) ;

5.3 iRMX 286R-Related Utilities

CREATE_MAILBOX creates an RMX mailbox using fixed parameters and catalogs it under the user-specified name. CREATE_MAILBOX replaces two RMX routines, RQ$CREATE$MAILBOX and RQ$CATALOG$OBJECT, and uses a less error-prone mailbox name representation. CREATE_MAILBOX prints its own error status messages.

    mailbox_token = create_mailbox (@name) ;

CREATE_SEGMENT allocates an RMX memory segment of a specified size. Round-robin scheduling of tasks that are (unsuccessfully) attempting to allocate memory segments is implemented using the MEMORY$WAIT semaphore (which is created by a user job call to CREATE_SEGMENT). The scheduling is simple enough that it should work; I've seen no evidence, however, that it does or doesn't work!

    segment_token = create_segment (segment_size) ;

CREATE_SEMAPHORE creates an RMX binary semaphore using fixed parameters and catalogs it under the user-specified name. CREATE_SEMAPHORE replaces two RMX routines, RQ$CREATE$SEMAPHORE and RQ$CATALOG$OBJECT, and uses a less error-prone semaphore name representation. CREATE_SEMAPHORE prints its own error status messages.

    semaphore_token = create_semaphore (@name, initial_value) ;

CREATE_TASK creates an RMX task with fixed parameters. CREATE_TASK prints its own error status message.

    task_token = create_task (@main_routine, stack_size) ;

LOOKUP_OBJECT looks up an RMX object in the specified job's object directory. This is essentially the same function that RMX routine RQ$LOOKUP$OBJECT performs, but LOOKUP_OBJECT utilizes a less error-prone object name representation.

    object_token = lookup_object (@name, job) ;

PRINT_MEMORY_STATISTICS displays the RMX memory statistics (obtained by a call to RMX routine RQ$GET$POOL$ATTRIB) for the calling task's job on the console. How useful these statistics are is not clear.

    CALL print_memory_statistics (@header) ;

SEND_AND_SIGNAL sends a message packet to the specified mailbox and signals the specified semaphore. SEND_AND_SIGNAL combines calls to RQ$SEND$MESSAGE and RQ$SEND$UNITS; it outputs its own error status messages.

    CALL send_and_signal (mailbox, packet, semaphore, @status) ;

WAIT_AND_READ waits on the specified semaphore and reads a message packet from the specified mailbox. WAIT_AND_READ combines calls to RQ$RECEIVE$UNITS and RQ$RECEIVE$MESSAGE; timeouts, such as no wait or wait forever, can be specified for both operations. WAIT_AND_READ outputs its own error status messages.

    CALL wait_and_read (semaphore, sem_timeout, mailbox, mbx_timeout, @packet, @status) ;

5.4 Queue Utilities

ADD_QUEUE adds a data item to the rear of a queue. The queue is specified by a queue descriptor, which defines the state of the queue. An error message is displayed on the console if the queue overflows.

    CALL add_queue (@queue, @item, @status) ;

DELETE_QUEUE deletes and returns the data item at the front of a queue. The queue is specified by a queue descriptor, which defines the state of the queue and the data type of items in the queue.

    CALL delete_queue (@queue, @item, @status) ;

EXAMINE_QUEUE returns the data tiem at the front, rear, or inside of a queue. The queue is specified by a queue descriptor, which defines the state of the queue and the data type of items in the queue.

    CALL examine_queue (@queue, position, index, @item, @status) ;

INITIALIZE_QUEUE creates a queue by initializing the fields in a queue descriptor. The caller specifies the data type of the elements in the queue and the size and location of the queue.

    CALL initialize_queue (@queue, type, @buffer, size) ;

LENGTH_IN_QUEUE determines the distance between two indices in a circular queue. The queue is specified by a queue descriptor, which defines the state of the queue.

    len = length_in_queue (@queue, first, last) ;

PRINT_QUEUE displays a caller-specified queue name and the fields of a queue descriptor on the console screen.

    CALL print_queue (@queue_name, @queue) ;

5.5 Miscellaneous Utilities

BUILD_MESSAGE allocates a mailbox message packet and fills in the fields of the packet with the specified parameters. Always be sure to specify the function modifier (FMOD) correctly: N$DELETE if the message text is in an RMX-allocated memory segment that should be deleted after use, or N$NONE if the message text is a constant or a user-owned buffer.

    packet_token = build_message (source, destination, func, fmod,
                                  text_length, text_location) ;

CHECK_BOREDS is an applications firmware utility routine that goes out on the I/O bus and checks the board number of each board specified in the input table.

    CALL check_boards (@board_table, @status) ;

CHECK_REGS is an applications firmware utility routine that goes out on the I/O bus and verifies that the 8-, 13-, or 16-bit registers specified in the input table are all working.

    CALL check_regs (@registers_table, register_width, @status) ;

CHECKSUM_OF computes a checksum for a buffer of data. The data in the buffer are treated as bytes; the checksum is the 16-bit sum of all the bytes (roll-over is ignored).

    value = checksum_of (@buffer, length) ;

DELETE_MESSAGE deletes a mailbox message packet segment and, if specified in the packet, the message text segment. Errors deleting either of the segments are ignored.

    CALL delete_message (packet_token) ;

GET_STRING gets the next "word" from a string of text. A "word" is a string of characters delimited on each side by a control character, space, or one user-specified character, or the beginning or end of the string.

    CALL get_string (@string, string_length, start, delimiter,
                     @first, @last, @length) ;

LOOKUP_SYMBOL looks up a target string in a symbol table. Partial matches are allowed (i.e., 'DEB' matches 'DEBUG'). The first match found for ambiguous abbreviations is the match returned.

    index = lookup_symbol (@target, target_length,
                           @symbol_table, symbol_table_size) ;

MEMORY_TEST tests a specified region of memory. This routine uses the stack, which should not be in the area of memory being tested.

    status = memory_test (start_address, stop_address,
                          @bad_address, @expected_value) ;

PRINT_MESSAGE displays the fields of a message packet and the message text on the console screen. A useful feature of this routine is that non-printing ASCII characters in the message text are converted to their ASCII hexadecimal representation, thus allowing binary data (i.e., checksums, etc.) to be verified.

    CALL print_message (@header, packet_token, text_switch) ;
 

6 Universal Firmware Functions

Since this document was never finished, the remainder of the document was extracted from various program prologs. Topics discussed include pre-applications processing (i.e., before the applications firmware is started), RPU interface functions (I/O configuration, etc.), IEEE-488 I/O functions, RS-232C I/O functions, console I/O functions, and debug monitor functions.

6.1 Pre-Applications Processing

As mentioned earlier, the universal firmware has a two level job hierarchy. The first-level user job is created by iRMX when it boots up. The user job, in turn, creates a child job called the test rack job. These two jobs are described in the following paragraphs.

6.1.1 User Job

The user job initialization and restart task is the only task activated when the user job is created by the RMX root job upon a "hard" system reset. The task then continually loops, waiting for a "soft" reset to be signalled. Upon receipt of such a signal, the test rack job is deleted (thereby deallocating all its resources) and recreated.

One semaphore is created by this job. The RESET semaphore is used by the test rack job to signal the user job that a "soft" reset is to be performed. The application start address variable is allocated and initialized by the user job, but from then on it is the responsibility of the test rack job. By being the property of the parent user job, the application start address is, in a sense, "global" to consecutive instantiations of the test rack job.

An interrupt handler is set up to field parity error interrupts from the iLBX 512K RAM boards. This interrupt handler is NOT associated with an interrupt service task and can be superseded by a user-written handler by RESET$INTERRUPT'ing it and SET$INTERRUPT'ing the new handler. A hard or soft RESET, however, restores the universal firmware interrupt handler.

6.1.2 Test Rack Job

The test rack job is created by the first-level user job. This two-job structure simplifies restarting the firmware; the user job needs only to delete the test rack job in order to deallocate all the test rack job's resources (semaphores, mailboxes, memory segments, etc.).

The test rack job initialization and download task is the first task executed when the test rack job is created. This task is responsible for creating some semaphores and mailboxes, starting up the interface tasks, and, if requested, downloading the applications firmware. The main applications task is then created and control is passed to it. During the download, the initialization and download task appears to the interface tasks as a pseudo-main applications task (thus using the same semaphores and mailboxes as the real main applications task).

The download task recognizes the following commands from the RPU:

"UP"
If the universal firmware is up and running, then send the version number of the firmware back to the RPU.

"DL"
Begin applications firmware download.

"GO"
Start the applications firmware running.

Usually, the following communications will take place between the RPU and the SBC:

  1. The RPU repeatedly sends "UP" to the SBC until it receives a response from the SBC.

  2. After booting up, the SBC waits for an "UP" message from the RPU. Upon receiving the "UP" message, the SBC returns a status and version number message to the RPU.

  3. The RPU then sends a "DL" message to inform the SBC to set up for applications firmware download.

  4. Upon receiving the "DL" command, the SBC resets its download parameters. NOTE: Sending a new "DL" command aborts the download currently in progress and begins a new download.

  5. The RPU sends each record of the INTEL hexadecimal object file to the SBC. These INTEL-generated records all have a colon (":") at the beginning of the record.

  6. The SBC processes each download record.

  7. After download is complete, the RPU sends a "GO" command to the SBC.

  8. Upon receiving a "GO" command from the RPU, the SBC starts up the applications firmware at the address specified in the download.

The "UP" command should always be sent to the SBC because it sets up the source and destination mapping for the RPU (i.e., who is the RPU). The version message returned to the RPU includes the statuses of the memory tests performed upon power-up of the test rack. These are stored in a variable, MEMORY$TEST$STATUS, which is declared in the MILSTAR power-up firmware (see MSURST.A86). If a memory test passed, then a "P" is inserted in the version message; if the test failed, an "F" is inserted, instead.

6.2 RPU Interface Commands

6.3 IEEE-488 Interface

This paragraph describes the IEEE-488 functions that the universal firmware provides the user. Devices on the IEEE-488 bus are connected in a master/slave relationship. One device acts as the system controller (master); the remaining devices are simple talkers or listeners (slaves) under the direction of the system controller. In the panel STE test set, where the RPU/GSC is the VAX computer, the SBC functions as the system controller. In the other test sets, where the RPU is the HP computer, the HP functions as the system controller and the SBC is just a talker/listener. Since the SBC's IEEE-488 interface must be configured differently depending on its functional identity, the SBC as the system controller and the SBC as a talker/listener are discussed separately below.

6.3.1 SBC as System Controller

Only in the panel STE test set does the SBC control the devices on the IEEE-488 bus. The SBC knows that it is the system controller by the configuration of the jumpers on the iSBX 488 interface card (see paragraph 2.1.4 of this document) - jumpers E8-E16, E18-E19, and E17-E18 must be set up correctly. The functioning of the SBC when it is the IEEE-488 system controller involves the universal firmware's response to interface signals, the output and control capabilities the universal firmware provides the applications firmware, and the asynchronous inputs fielded by the universal firmware. These are discussed below, followed by some example interface dialogs.

6.3.1.1 Interface Signal Responses

A multitude of events can occur on the IEEE-488 interface - the universal firmware restricts them to the manageable few it can handle:

6.3.1.2 Output/Control Functions

The IEEE-488 driver task controls output to the IEEE-488 bus. Output mailbox messages received by the IEEE-488 driver task specify data or commands that are to be output on the IEEE-488 bus. Although these functions are described from the point of view of the applications firmware sending to and receiving messages from the universal firmware, it is possible to access these same functions from the console (see the Console Interface section of this document).

The following conventions apply to the descriptions of the functions below. The function names (READ$488, SPC$488, etc.) are for descriptive purposes only; they are not parameterized anywhere and are not used in the firmware. The message functions (INPUT, OUTPUT, and SPECIAL) are parameterized in the MSUNIV.EXT include file as N$INPUT, N$OUTPUT, and N$SPECIAL. The function modifiers (none or /DELETE) are parameterized in the MSUNIV.EXT include file as N$NONE and N$DELETE. Mailbox messages passed to and from the IEEE-488 driver task must have the message source, destination, function, and function modifier specified. Utility routines BUILD_MESSAGE and SEND_AND_SIGNAL make it easy to send commands to the IEEE-488 interface (see the examples later).

A device list is a string of ASCII hexadecimal device addresses. For example, a list of device addresses { 4, 19, 21, 23 } is represented as "04131517". A device/status list (returned by a serial poll) is a string of device addresses and device statuses; i.e., "04xx13yy15zz17ss".

Requests sent to the IEEE-488 driver task are queued to the IEEE-488 interrupt service task for processing when the interface is idle. The following functions can be requested when the test rack computer acts as the IEEE-488 bus controller:

    WRITE$488 - Write data from an output buffer to the IEEE-488 bus.

		Message function:  OUTPUT { /DELETE }
		Message text    :  output data

    TALK$488 - Configure the device at the specified IEEE-488 address as a
               talker and input data from that device.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "TLK device"

    LISTEN$488 - Configure the devices at the specified IEEE-488 addresses as
                 listeners; the next output buffer is output to these listeners.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "LIS deviceList"

    TRANSFER$488 - Set up a data transfer between the specified talker and the
                   specified listeners.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "XFR talker listeners"

    ASCII$TEXT - Output an ASCII string to the current listeners.  If there
                 is no string specified, a carriage return and line feed are
                 output.  This function is useful when entering commands
                 interactively via the console interface.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "ASC asciiText"

    BINARY$DATA - Output binary data to the current listeners.  Each byte
                  is specified in ASCII hexadecimal form.  This function is
                  useful when entering commands interactively via the console
                  interface.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "BIN hexData"

    DEFAULT$SPOLL - Specify a new list of default devices for unsolicited
                    serial polls.  If no devices are specified, then the
                    default list defaults to the original list of devices.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "DSP deviceList"

    DEVICE$CLEAR - Send a Selected Device Clear (SDC) command to the specified
                   devices; if no devices are specified, a Device Clear (DCL)
                   command is sent to all devices.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "DCL deviceList"

    GROUP$EXECUTE$TRIGGER - Send a Group Execute Trigger (GET) command to the
                            specified devices; if no devices are specified, the
                            GET command is sent to the current listeners.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "GET deviceList"

    GO$TO$LOCAL - Send a Go To Local (GTL) command to the specified devices; if
                  no devices are specified, the GTL command is sent to the
                  current listeners.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "GTL deviceList"

    INTERFACE$CLEAR - Assert an Interface Clear (IFC) signal on the IEEE-488 bus.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "IFC"

    LOCAL$MODE - Deassert the Remote Enable (REN) signal on the IEEE-488 bus.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "LCL"

    LOCAL$LOCKOUT - Send a universal Local Lockout (LLO) command to all devices.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "LLO"

    REMOTE$ENABLE - Assert the Remote Enable (REN) signal on the IEEE-488 bus.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "RMT"

    SERIAL$POLL - Conduct a serial poll of the specified devices on the
                  IEEE-488 bus.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "SPL deviceList"

6.3.1.3 Asynchronous Input

The IEEE-488 driver task is the asynchronous source of the following types of messages:

    READ$488 - Data was input from the IEEE-488 interface into a buffer until
        EOI was received.  The transmitting device must be addressed as a
        talker before the transmission begins.

		Message function:  INPUT/DELETE
		Message text    :  input data

    SPC$488 - A solicited/unsolicited serial poll was conducted.  The
              device/status list contains the address and status of each
              device polled; if the most significant bit of a device address
              is set, then the device did not respond.  The device status list
              for an unsolicited serial poll only contains statuses for devices
              actually requesting service.

		Message function:  SPECIAL/DELETE
		Message text    :  "SPC deviceList/statusList"

Input from the IEEE-488 bus is buffered; when a complete record has been assembled, the data is transferred to a dynamically allocated memory segment and an input mailbox message is sent to the RPU interface task. The physical source for input mailbox messages is the driver task itself (488); the logical destination is found in the global input destination table. The RPU interface task determines the logical source (i.e., when the IEEE-488 bus is the source of RPU messages) and physical destination for the messages.

6.3.1.4 Examples

6.3.2 SBC as a Talker/Listener

In all but the panel STE test set, the remote processing unit (HP computer) controls the IEEE-488 interface; the SBC acts as a simple talker/listener. The SBC knows that it is not the system controller by the configuration of the jumpers on the iSBX 488 interface card (see paragraph 2.1.4 of this document) - jumper E8-E16 and the device address jumpers must be set up correctly. The functioning of the SBC when it is a talker/listener involves the universal firmware's response to interface signals, the output and control capabilities the universal firmware provides the applications firmware, and the asynchronous inputs fielded by the universal firmware. These are discussed below, followed by some example interface dialogs.

6.3.2.1 Interface Signal Responses

The following events are handled by the universal firmware when the SBC is a talker/listener on the IEEE-488 bus:

6.3.2.2 Output/Control Functions

The IEEE-488 driver task controls output to the IEEE-488 bus. Output mailbox messages received by the IEEE-488 driver task specify data or commands that are to be output on the IEEE-488 bus. Although these functions are described from the point of view of the applications firmware sending to and receiving messages from the universal firmware, it is possible to access these same functions from the console (see the Console Interface section of this document).

The following conventions apply to the descriptions of the functions below. The function names (READ$488, WRITE$488, etc.) are for descriptive purposes only; they are not parameterized anywhere and are not used in the firmware. The message functions (INPUT, OUTPUT, and SPECIAL) are parameterized in the MSUNIV.EXT include file as N$INPUT, N$OUTPUT, and N$SPECIAL. The function modifiers (none or /DELETE) are parameterized in the MSUNIV.EXT include file as N$NONE and N$DELETE. Mailbox messages passed to and from the IEEE-488 driver task must have the message source, destination, function, and function modifier specified. Utility routines BUILD_MESSAGE and SEND_AND_SIGNAL make it easy to send commands to the IEEE-488 interface (see the examples later). When the test rack computer acts as an IEEE-488 talker/listener (the HP computer is the system controller), the available functions are as follows:

    WRITE$488 - Write data from an output buffer to the IEEE-488 bus.

		Message function:  OUTPUT { /DELETE }
		Message text    :  output data

    ASSERT$SRQ - Assert a Service Request (SRQ) signal on the IEEE-488 bus and
        output request byte YY when serially polled.

		Message function:  SPECIAL { /DELETE }
		Message text    :  "SRQ YY"

6.3.2.3 Asynchronous Input

The IEEE-488 driver task is the asynchronous source of the following types of messages:

    READ$488 - Data was input from the IEEE-488 interface into a buffer until
        EOI was received.

		Message function:  INPUT/DELETE
		Message text    :  input data

Input from the IEEE-488 bus is buffered; when a complete record has been assembled, the data is transferred to a dynamically allocated memory segment and an input mailbox message is sent to the RPU interface task. The physical source for input mailbox messages is the driver task itself (488); the logical destination is found in the global input destination table. The RPU interface task determines the logical source (i.e., when the IEEE-488 bus is the source of RPU messages) and physical destination for the messages.

6.3.2.4 Examples

6.4 RS-232C Interface

This paragraph describes the RS-232C (Channel A) functions that the universal firmware provides the user. Although these functions are described from the point of view of the applications firmware sending to and receiving messages from the universal firmware, it is possible to access these same functions from the console (see the Console Interface section of this document).

The RS-232C driver task controls input from and output to the RS-232C serial link. Output mailbox messages received by the RS-232C driver task specify data that is to be output over the RS-232C serial link. Input from the RS-232C interface is buffered; when a complete record has been assembled, the data is transferred to a dynamically allocated memory segment and an input mailbox message is sent to the RPU interface task. The physical source for input mailbox messages is the driver task itself (232); the logical destination is found in the global input destination table. The RPU interface task determines the logical source (i.e., when the RS-232C serial link is the source of RPU messages) and physical destination for the messages.

As with the IEEE-488 functions, the READ$232 and WRITE$232 labels are for desciptive purposes only and are not used in the firmware.

The RS-232C driver task is the asynchronous source of the following message type:

    READ$232 - Data was input from the RS-232C interface into a buffer until a
        carriage return was received.  XON/XOFF is handled and line feeds are
        ignored.  The 8-bit input characters are masked to produce 7-bit ASCII
        characters.

		Message function:  INPUT/DELETE
		Message text    :  input data

Requests sent to the RS-232C driver task are queued to the RS-232C interrupt service task for processing when the interface is idle. The following function is available:

    WRITE$232 - Write data from an output buffer to the RS-232C serial link.
        A carriage return and line feed are automatically appended to the
        output text.

		Message function:  OUTPUT { /DELETE }
		Message text    :  output data

6.5 Console Interface

 

7 MTEX-86 Monitor Functions


Alex Measday  /  E-mail