Intel RMX/80 Executive Application Note
PDF
Dokument
Annonce
Annonce
intel APPLICATION AP-33
NOTE
October 1977
© Intel Corporation, 1977, 1978, 1979 9800577A
2-3
RMX/80 Real-Time
Multitasking Executive
2-4
Contents
INTRODUCTION .........eceocorecroccooo. 2-5
OVERVIEW. ........o.oooococcorccccocooo 2-5
Basic Concepts ............eereeorccocacoo 2-5
General Characteristics ...........ooe_resvoo 2-5
Nucleus Operations ..........ñeoeeeecereooo 2-7
ЕХТЕМЫЮМ®5........................... 2-10
Free Урасе Мапарег ...................... 2-10
Terminal Handler ........................ 2-11
Disk File System...........eoeeoccorecaroo 2-11
Debugger..........._eceeorcccocrooecoco. 2-11
USING THE RMX/80™ SOFTWARE ...... 2-11
Task and Exchange Definition .............. 2-12
Priority Assignment. ..................... 2-13
Static Descriptions...........oocooreacsveoo 2-13
Compilation/Assembly.................... 2-13
Linking ........coc_eorecxovccorersocococrren. 2-14
Locating .…...000000000 0000 sa aa ea ana e 2-14
Debugging...........e.oereoreocecocaroo .2-14
APPLICATIONS ........................ 2-14
Minimal Terminal Handler................. 2-14
Closed-Loop Analog Control............... 2-18
APPENDIX A .....e.oooreconcsccrocoocceco 2-21
APPENDIXB .........ñoeeceorcccsocccooeoo 2-25
APPENDIXC........eoceocecooccoocooacoo 2-27
INTRODUCTION
A large number of microcomputer applications
require the ability to respond to events in real time.
RMX/80 provides the system software around
which you can build a real-time multitasking appli-
cation on Intel SBC 80 Single Board Computers.
In addition, RMX/80 increases the utilization of
a Single Board Computer by allowing its resources
to be shared among several tasks executing concur-
rently. Synchronization of these multiple real-time
tasks is handled by RMX/80, freeing you to con-
centrate your major programming efforts on your
application.
This application note begins with an overview of
RMX/80. Readers who are familiar with the mate-
rial presented in the RMX/80 User’s Guide may
choose to skip to the next section, a description of
how to use RMX/80 and the steps involved in
using it by describing two applications.
e An interrupt driven minimal terminal handler
for a CRT or Teletypewriter.
® A closed-loop analog control subsystem utiliz-
ing the Intel SBC 711 analog-to-digital board.
Each example has diagrams illustrating the rela-
tionships between its tasks and exchanges. These
are useful tools in conceptualizing the activities
taking place in real time. Program listings of the
applications are interspersed with text describing
the application.
OVERVIEW
Real-time systems provide the ability to control
and respond to events occurring asynchronously
in the physical world. Later in this application
note, a process control application is described
that monitors and controls the temperature within
several chambers. The system controls the process
by simply turning on and off a heat source. The
system could also display the temperature on an
operator’s console and permit entry of new set-
point temperatures and error ranges.
A single large program could have been used to
perform the functions in a sequential manner.
However, this approach may not permit an opera-
tor to enter control variables at the same time the
process is being monitored and controlled. In
contrast, real-time systems do not operate sequen-
tially. A number of events may all be happening
at the same time. This concurrence of events is a
distinguishing characteristic of real-time systems.
2-5
BASIC CONCEPTS
There are basically three concepts that the user
‘must master to effectively use RMX/80. The first
is the task, an independent program which com-
petes for resources within the system. The second
concept is the message. Messages convey data and
synchronization information between tasks. The
third concept is the exchange. An exchange enables
one task to send a message to another. As we will
see later, the interaction between tasks and ex-
changes enables the user to implement mutual
exclusion, communication, and synchronization.
Mutual exclusion is a technique that controls
access to a shared resource such as an I/O device
or a data structure.
Task
Under RMX/80, the user codes a separate program,
known as a task, for each event. An arbitrary num-
ber of these tasks execute concurrently and are
subject to synchronization as required by their
functions. Tasks share resources such as data struc-
tures and can communicate between themselves.
Message
A message is a unit of communication between
tasks. Together with the exchange mechanism, it
conveys information between tasks and can syn-
chronize their operations.
Exchange
RMX/80 uses message exchanges for task-to-task
communication. An exchange is a pair of queues
represented by a data structure at which messages
are left by one task to be picked up by another.
Tasks may send messages to an exchange, and may
wait for messages at an exchange. A task which
waits for a message may perform a timed or an
untimed wait. A timed wait will terminate upon
the receipt of a message or at the end of the speci-
fied period of time, even if it has not received a
message. When a task does an untimed wait for a
message it is guaranteed that the task will not exe-
cute again until a message is available for it. A
‘representation of the exchange data structure is
shown in Figure 1.
GENERAL CHARACTERISTICS
In addition to the basic concepts of tasks and ex-
changes, several other general characteristics of
RMX/80 are relevant in this overview.
LINK
TASK A LINK
TASK B
Figure 1. Exchange Data Structure
System Time Unit
RMX/80 uses a system time unit that is the period
of time between “ticks” of the system clock. The
standard RMX/80 system time unit is 50 milli-
seconds, The system time unit provides timing and
user task scheduling. A task may wait at an ex-
change for a specified number of system time
units and then continue execution. A task could
be written to generate messages at specific time
intervals. Tasks waiting for the messages would
then be scheduled according to those time intervals.
Message Producing/Consuming Tasks
In general, tasks can be classified as message pro-
ducing or message consuming tasks. The processing
flow of these types of tasks are usually cyclic in
nature and can be shown as follows.
TASK ENTRY POINT TASK ENTRY POINT -
INITIALIZE TASK INITIALIZE TASK
—»1 WAIT FOR REQUEST >| PERFORM FUNCTION
INITIALIZE OPERATION
PERFORM FUNCTION (SEND MESSAGE)
SEND RESPONSE
WAIT FOR RESPONSE
CONSUMER PRODUCER
Figure 2. Message Producing/Consuming Tasks
A consumer task waits for a message to be posted
at a particular exchange and takes control of the
processor only when it has received a message and
no other tasks of higher priority are ready to exe-
cute. The consumer task performs some action
based upon the message and then simply resumes
waiting until the next message is received. Usually,
the consumer task acknowledges completion of
its function by sending a response message to some
other exchange associated with a task.
2-6
A producer task initiates its function by sending
a message to another exchange and then surrenders
control of the processor. The task continues to
wait until it receives a response to its message.
Notice that the distinction between these types
of tasks is relative since most tasks both produce
and consume messages. However, the producer/
consumer concept helps clarify the general struc-
ture of tasks—tasks are typically programmed
loops. A producer task performs a function, sends
a message, waits for a response, then loops back to
begin again. A consumer task waits for a message,
performs a function, sends a response, then loops
back to wait again.
Interrupts
Hardware interrupts are treated as messages from
peripheral devices for which a task can wait, as if
the interrupt were a message from some other task.
These messages arrive at particular exchanges,
called interrupt exchanges, but are otherwise treated
as described above. The system provides the abil-
ity to mask particular interrupts so that no mes-
sages ever arrive at a particular interrupt exchange
associated with the masked interrupt. In the event
that the overhead associated with turning an inter-
rupt into a message is too high, the interrupt can
be treated by the user directly via a user supplied
interrupt service routine.
Task States
Tasks may exist in a number of states. A task is
running if it actually has the processor executing
instructions on its behalf. A ready task is one that
could be running (any wait for a message or time
period has been satisfied), but a higher priority
task is currently running. A task is waiting if it
cannot be ready or running because it is waiting
at an exchange for a message. A suspended task is
one that is not permitted to run or compete for
system resources until it is resumed. The rela-
tionships between the task states are illustrated in
Figure 3. | |
Priority |
Each task has associated with it a priority that in-
dicates its importance relative to other tasks in
the system and relative to the interrupts of peri-
pheral devices. RMX/80 schedules a task for exe-
cution based on the task’s priority. Whenever a
decision must be made on which task should be
run, the highest priority ready task is chosen. Each
of the eight hardware interrupt levels has a set of
priorities, one of which must be assigned to the
task that services the interrupt. When an interrupt
occurs that task is executed if it is the highest
priority ready task. At the time a higher priority
task preempts a lower priority task, RMX/80
saves all the relevant information about the pre-
empted task so it can eventually resume execution
as though it were never interrupted. This process
is known as a context save.
|
RUNNING
— == =
A | : Y
SUSPENDED
WAITING
|
Figure 3. Task States
NUCLEUS OPERATIONS
The RMX/80 nucleus provides several operations
that you can access with programmed calls. Two
basic operations are covered in this section (addi-
tional operations are described in the RMX/80
User’s Guide):
e ROSEND, send a message to an exchange
eo RQWAIT, wait for a message or time interval
These two operations provide the capability to
pass messages between tasks in a system running
under RMX/80.
Message Format
The messages used by the send and wait operations
to convey information between tasks are variable
in length and contain the information shown in
Figure 4.
2-7
LINK (BASE)
LENGTH
TYPE
HOME EXCHANGE
RESPONSE EXCHANGE
REMAINDER
© NO ю ©
+Indicates optional
Figure 4. Message Format
Fields
|. LINK — a 2-byte field used to enter the mes-
sage on a linked list at an exchange.
2. LENGTH — a 2-byte field containing the total
length of the message in bytes. The minimum
message length is 5 bytes (LINK, LENGTH,
and TYPE).
3. TYPE — a 1-byte field indicating the type of
message.
4, HOME EXCHANGE — an optional 2-byte
field containing the address of an exchange to
which this message should be sent when it has
no further use. This field is very useful in im-
plementing and managing a pool of messages.
5. RESPONSE EXCHANGE — an optional
2-byte field containing the address of an ex-
change to which a logical response to this
message should be sent. This field is intended
to specify the exchange at which a sending
task is waiting for an acknowledgement
message if one is needed.
6. REMAINDER — an optional field of arbi-
trary length that may contain any data por-
tion of the message.
Sending a Message to an Exchange
The RQSEND operation enables a task to post a
message at an exchange. When you send a message
to an exchange, RMX/80 actually posts only the
address of the message at the exchange, not the
body of the message. RMX/80 avoids the overhead
required to move an entire message to an ex-
change. Thus it is possible to queue a number of
messages at the same exchange with little overhead
in either execution time or memory requirements.
When a task sends a message to an exchange, sev-
eral functions are performed.
e The message is placed on the specified ex-
change.
e If there are one or more tasks waiting at the
exchange, the first task is given the message
and is made ready.
e If a higher priority task is thereby made
ready, the sending task loses control until
it once again becomes the highest priority
ready task.
After a message is sent to an exchange, it must not
be modified by the sending task. A task which then
receives the message by waiting at the exchange
where the message has been posted is free to modi-
fy the message. The format of the RQSEND opera-
tion is as follows.
ROSEND(exchange-address,message-address)
Message exchanges are defined by the user, and are
normally addressed symbolically. For example,
the exchange used to pass readings from an analog-
to-digital (A/D) task might be named ATODEX.
The reading itself could be contained in a message
with the name RDNG. Thus, a typical call for a
send in a PL/M program might be as follows:
CALL RQSEND (:ATODEX,.RDNG) ;
The call procedure in assembly language is as
follows.
LXI B,ATODEX
LXI D,RDNG
CALL RQSEND
The assembly language rules for passing parameters
to RMX/80 are the same as for passing parameters
to a PL/M procedure called from an assembly lan-
guage module. For 2-byte parameters, the first
parameter is passed in the B and C registers; the
second parameter is passed in the D and E registers.
Waiting for a Message or Time Interval
The RQWAIT operation causes a task to wait for
a message to arrive at an exchange. It is also pos-
sible to delay execution of a task when no message
is anticipated for the task. The task simply waits
for the desired time period at a message exchange
where no message is ever sent. When a task waits
for a message at an exchange several operations
are performed.
2-8
e The task is made to wait until a message is
sent to the specified exchange, or until the
time limit has expired.
e When a message is available, its address is
returned to the task.
® Jf the time limit expires before a message
becomes available, a system TIMESOUT mes-
sage is returned to the task.
The format of the RQWAIT operation is as follows.
RQWAIT(exchange-address,time-limit)
The time limit is entered as some number of sys-
tem time units (50 milliseconds); a 1-second wait
is equal to 20 time units. If zero is specified the
wait is not timed, producing an indefinite wait
until a message is actually sent to the exchange.
Note that a specified wait of five time units may
sometimes only produce an actual wait of four
time units. This can occur if you enter a wait
immediately before the clock “ticks.” In this
case the count would be decremented immediately
after entering the wait. Only four full time unit
periods would lapse before completion of the
wait. Thus a user who wishes to ensure that at least
five time units are spent in an asynchronous wait
must specify six time units in the wait operation.
A task which waits synchronously to the system
clock, i.e., performs repetitive timed waits, does
not have this problem because a new wait is exe-
cuted following a tick that satisfied the previous
wait. The following are typical calls for the
ROWAIT operation.
PL/M
PTR = ROWAIT(.ATODEX,20) ;
The RQWAIT procedure returns an address value
which is the address of a message.
Assembly Language
LXI B,ATODEX
LX! D,20
CALL RQWAIT
The address of a message is returned in the HL
register pair.
Send — Wait Interaction
To a large extent, the power of RMX/80 as a pro-
gramming tool is derived from the interaction
between send and wait. The interaction includes
three multi-tasking operations.
e Communication
e Synchronization
e Mutual Exclusion
In describing these operations, a graphic notation
for diagramming tasks, exchanges, and their
interaction (send and wait operations) is useful.
The notation is described in the next section on
communication.
Communication. The most common interaction
between tasks is that of communication — the
transmission of data from one task to another
via an exchange (Figure 5).
TASK TASK
Figure 5. Communication
Rectangles designate tasks while circles represent
exchanges. Arrows that are directed from tasks to
exchanges indicate send operations. Wait opera-
tions are shown by arrows directed from exchanges
to tasks.
Figure 5 shows an example of communication
between task A and task B. Task A sends a message
to exchange X and task B waits for a message at
that exchange. Task A is the message producer
and task B the message consumer.
Synchronization. At times there is a requirement
to send a synchronizing signal from one task to
another. This signal can take the form of a message
that contains only header information, that is,
LINK, LENGTH, and TYPE.
Let us consider the implementation of a task
scheduler, used for the purposes of synchronizing
another task that performs a particular function
at periodic intervals. The relationship between the
tasks and exchanges is shown in Figure 6.
2-9
TASK TASK
B
Figure 6. Synchronization
Task A, the scheduler, performs a timed wait on
the X exchange. Note that the full wait period
will always occur because there is no task that
is sending messages to exchange X. In this manner,
a specific timed wait by task A precedes the pass-
ing of a synchronization message from task A to
task B via exchange Y, and then the return from
task B to task A via the Z exchange.
If task B waited on X directly, rather than using
task A for scheduling, it would be scheduled n sys-
tem time units from when it waits instead of n
units from the last time it was awakened. A com-
parison between the two methods is shown in
Figure 7.
TIME
B B B TIME
en tn rene armee” mate rer”
n B n B поп п
TASK B WAITING DIRECTLY ON X TASK A SCHEDULING TASK B
Figure 7. Scheduling Methods
Mutual Exclusion. In an environment with multi-
tasking, resources often must be shared. Examples
of shared resources include data structures and
peripherals such as the Intel SBC 310 Math Module.
Mutual exclusion can be used to ensure that only
one task has access to: a shared resource at a time.
Figure 8 shows how an exchange can be used to
limit access to a resource.
TASK
A
TASK EXCH
X
TASK
N
Figure 8. Mutual Exclusion
In this example, the X exchange is sent a single
message at system initialization. Then, as tasks re-
quire the resource, they wait for a message from
the X exchange. When the message is received,
the task knows it has sole access to the resource
because there is only one message associated
with the exchange. After the task finishes with
the resource it sends the message back to the X
exchange. The next task waiting for the resource
continues, knowing it has exclusive access to the
resource. | |
EXTENSIONS
RMX/80 has several extensions which provide
operations commonly used in real-time applica-
tions. The nucleus of RMX/80 requires less than
two thousand bytes of memory and includes all
of the basic operations. The extensions include a
Free Space Manager, Terminal Handler, Disk File
System, and a Debugger.
FREE SPACE MANAGER
The Free Space Manager maintains a pool of free
RAM and allocates memory from that pool upon
request from a task. The Free Space Manager also
reclaims memory and returns it to the pool when
it is no longer needed.
The Free Space Manager is especially useful in two
applications. The first application arises from the
need for variable length messages. If you have a
task that produces messages of variable length,
such as a task sending text for display on a CRT,
the Free Space Manager can be used to provide
a message to meet your exact size requirements.
2-10
An alternate solution is to maintain a pool
of large fixed length messages. The pool can be
maintained without the Free Space Manager;
however, memory is wasted because of the unused
space remaining in the fixed length messages.
The second application of the Free Space Manager
relates specifically to effective use of memory.
In a typical application, the total RAM require-
ment is computed by adding up the maximum
RAM requirements for each task in a system as
shown in Figure 9.
TASK C
TASK À
ROM
RAM
MAXA
TASK B
) MAXS
RAM
MAXC
RAMTOTAL = MAXA + MAXB + MAXC
Figure 9. RAM Requirements
The efficiency of memory utilization is a function
of the total RAM memory needed during typical
system operation. Reducing the total amount of
RAM by sharing it among the tasks often has
little impact on total performance. However, signi-
ficant cost advantages may be gained by reducing
the total amount of memory. The memory require-
ments can be calculated as the minimum RAM for
each task plus the pool (shared memory), as shown
in Figure 10.
TASK B POOL
ROM .
- TASKC
RAM
. MINB
RAM
MINA MINC
RAMTOTAL = MINA + MINg + MINg + POOL
Figure 10. RAM Requirements Using a Pool
TERMINAL HANDLER
The Terminal Handler provides real-time asyn-
chronous I/O between an operator terminal and
tasks running under the RMX/80 executive. The
Terminal Handler provides a line-edit capability
similar to that of ISIS-II and an additional type-
ahead feature. (ISIS-II is the diskette supervisor
system used on the Intellec Microcomputer Devel-
opment System.) Access to the Terminal Handler
is provided by two exchanges where messages are
sent to initiate read and write requests.
Several features of the Terminal Handler have
been incorporated specifically to facilitate interac-
tion with the debugger. Because of this interaction,
the Terminal Handler is required for operation of
the debugger. |
DISK FILE SYSTEM
The Disk File System (DFS) provides users of
RMX/80 with disk file management capabilities.
This system allows user tasks to create, access, and
maintain disk files in a real-time environment. This
means that many I/O requests can be processed
concurrently, rather than one at a time.
In addition to the file handling services, DFS pro-
vides a program loading facility that allows you to
load program segments into memory from disk.
The DFS can be configured to include only those
functions which you require. For example, if
your disk accesses are sequential rather than
random, you omit the SEEK function. This philo-
sophy of minimizing memory requirements by
including only the functions your application re-
quires is found in virtually all aspects of RMX/80.
DEBUGGER
An environment that is continually changing in
response to asynchronous physical events can pre-
sent a serious debugging challenge. The Debugger
aids you in debugging tasks running under the
RMX/80 executive. The Debugger provides a
command language that can be used to passively
display information about the system, or actively
modify and interact with the system.
Passive Functions
Because RMX/80 manages a fairly complex set of
data structures, the Debugger has the capability
of displaying them in an intelligible format. The
Debugger can be used in this manner to view
tasks, exchanges, messages, and other data struc-
2-11
tures maintained within the RMX/80 environment.
The contents of all RAM and ROM memory loca-
tions may also be displayed by the Debugger.
Active Functions
The active Debugger functions include those of
modifying memory, setting breakpoints, and moni-
toring stack overflow. The memory modification
commands enable you to update the contents of
memory and to move a series of bytes from any
location to any other location.
Breakpoints can be set, allowing you to gain con-
trol when encountered by a task. Two kinds of
breakpoints are supported: execution breakpoints
and exchange breakpoints. An execution break-
point can be placed at any instruction within read/
write (RAM) memory. When the breakpoint is
reached, the task encountering the breakpoint is
stopped from further execution. The task registers
may then be examined and modified before resum-
ing execution.
Exchange breakpoints can be used to detect
RQSEND and/or RQWAIT operations performed
on specified exchanges. The exchange breakpoint
can thus enable you to monitor the activity of any
of the exchanges in your system. The task execut-
ing the appropriate RQSEND or RQWAIT to an
exchange which has a breakpoint is stopped, allow-
ing you to examine the task. This enables you to
breakpoint a ROM resident task. The breakpointed
task and the message involved in the operation
with the exchange may then be displayed and
modified before resuming execution.
The debugger can also be used to monitor stack
overflow. This function is provided by the De-
bugger SCAN command which examines the stacks
of all tasks in the system at a specified periodic
interval. The fact that each task’s stack is initialized
with a unique value allows stack overflow to be
detected. When a task stack overflows, it is re-
moved from the system and a message is displayed.
USING RMX/80
This section of the application note describes the
steps involved in using RMX/80. The process
begins with the definition of the individual tasks
and exchanges in your application. It continues
with a discussion of the data structures that you
must prepare. The task coding, compilation or
assembly, linking, and locating is also described.
Finally, some comments are directed towards de-
bugging tasks within the RMX/80 envirnment.
Before the details of using RMX/80 are discussed,
some general observations are necessary to deter-
mine the suitability of RMX/80 for your applica-
tion. To effectively utilize RMX/80, your applica-
tion must either use interrupts or require device
polling. Thus, the key element is the need to
respond to external events. If your application
satisfies this criteria, it is a likely candidate. How-
ever, you must then determine if RMX/80 is capa-
ble of supporting your application. This can be
done by examining your interrupt response time
and frequency requirements. The time required to
transform an interrupt into a message that is sent
to an interrupt exchange is approximately 800
microseconds for an SBC 80/20. This is the
RMX/80 interrupt latency. It can be reduced to
60 microseconds by handling the interrupt directly,
using the RQSETV operation to bypass the
RMX/80 interrupt exchange mechanism. In this
latter mode, an interrupt-driven asynchronous
block transfer rate of about 10 kHz can be achieved.
TASK AND EXCHANGE DEFINITION
The initial design step for an application that runs
under the RMX/80 Executive is to define your
tasks, exchanges, and the interaction between
them. This is perhaps best accomplished using the
graphic notation introduced earlier in the section
on Send — Wait Interaction. The graphic notation
provides a clear picture of the relationships be-
tween the tasks and exchanges in your system.
You can begin either in a top-down or bottom-up
fashion. That is, you can use a top-down approach
to define, at a gross level the operation of your
system and then gradually break it down to the
individual tasks. Or, you can start with the tasks
associated with the external events in your appli-
cation and then build the pieces to form the gross
structure of your system.
The bottom-up approach forces you to begin with
external events that drive your system. The num-
ber of these events, the amount of processing
required, and the relationships between them
define the tasks and exchanges in a system. For
example, consider a system that samples an analog
input with an A/D converter. Assume that the A/D
provides an interrupt at the completion of a con-
version. To use the data from the A/D converter it
may also be necessary to scale it and add an offset.
With this information the portion of the task and
exchange definition that relates to this function
can be constructed. |
Begin with the external event, the interrupt from
the A/D. An “interrupt priority level must be as-
signed to the A/D converter. This same level will
be used by the task which waits on the interrupt
exchange. |
The relationship between the interrupt exchange
and the A/D task is shown in Figure 11. If pro-
cessing must be performed on raw data from the
A/D, a second, lower priority, task could be used.
“Another task for this function will require a syn-
chronizing signal from the ADC task to indicate
that raw A/D data has been obtained and is ready
for processing.
| ADC
TASK
Figure 11. Interrupt Exchange and A/D Task
The interaction between the ADC task and the
CONV task that processes the raw A/D data is
shown in Figure 12. Two exchanges provide
synchronization. The ADC task uses the TRGR
exchange to signal that data is ready for process-
ing by the CONV task. The CONV task uses the
RTRGR exchange to signal the completion of its
processing and thus its readiness to accept more
raw data.
- ADC ae CONV
Figure 12. ADC and CONV Task Interaction
In this example two tasks and three exchanges
have been defined. To develop an entire system,
the tasks and exchanges associated with all of the
external events in the system can be defined in
the same manner. Then, proceeding bottom-up,
the next step is to define the tasks and exchanges
required to support the interaction between tasks
running at the level of the real-time events.
After defining the entire application, you can begin
actual coding of the tasks. You may choose to
code in either assembly language or the PL/M 80
high-level language. Where possible, it is desirable
to code in PL/M because PL/M lends itself to
structured programming. Assembly language often
encourages an ad hoc approach. Even if your appli-
cation ultimately requires assembly language coding
because of critical time and/or space parameters,
initial design work in PL/M followed by transla-
tion into assembly language is recommended.
A total of 15 operations are supported by the
RMX/80 nucleus. Only two of the operations,
RQSEND and ROWAIT, are described in any detail
in this application note. The remaining operations
are described in the RMX/80 User’s Guide. The
reason for presenting only the send and wait opera-
tions is because they are sufficient for the imple-
mentation of a large number of real-time applica-
tions. These two operations provide a great deal of
power and flexibility, yet their simplicity should
enable those who are new to real-time program-
ming to quickly develop applications.
PRIORITY ASSIGNMENT
The relative priority of tasks within a system run-
ning under RMX/80 determines which task is to
be executed. Therefore, the assignment of a pri-
ority to each task is extremely crucial. For exam-
ple, consider a compute bound task placed at a
higher priority than an interrupt-driven task
responsible for servicing an I/O device. This im-
proper assignment of priorities could result in
missed interrupts from the I/O device. Several
steps can be followed in the assignment of task
priorities.
1. Assign hardware interrupt priority levels
according to the requirements of your appli-
cation.
2. Specify priorities for the tasks which service
the interrupts. These tasks should generally
be short and serve only to perform the data
2-13
transfers. A second task with a priority lower
than those assigned to the hardware inter-
rupts should be used where further processing
of the data is required.
3. Priority assignment should be made for all
other tasks in the system based on the relative
importance and interaction among the tasks.
Unfortunately the last step in assigning task pri-
orities is largely intuitive. In fact, you may need
some empirical data from actually running your
application before you settle on your final task
priority assignment.
STATIC DESCRIPTORS
When a system running under RMX/80 begins
execution, several tables of data are used to ini-
tialize the system. These tables usually reside in
ROM. The first table is the create table (RQCRTB)
that specifies the number of tasks and exchanges
in the system, and the addresses of the initial
task table and the initial exchange table. The ini-
tial exchange table contains the addresses of all
the exchange descriptors. The initial task table
contains the static task descriptors for each task,
and contains the following task parameters.
1. Name
2. Initial PC — the location at which’ to start
task execution
3. Initial SP — the location at which to start
the task stack
4. Stack length
5. Priority
6. Initial Exchange (described in the RMX/80
User’s Guide)
7. TD Address — the RAM address of the task
descriptor
You must prepare all three of these tables to pro-
duce a configuration module for RMX/80. The
release diskette for RMX/80 includes a set of files
which contain assembly language macros that sim-
plify the preparation of your configuration module.
The relationship between these tables is shown in
Figure 13.
COMPILATION/ASSEMBLY
Preparing program segments for compilation and
assembly can be simplified by use of files provided
on the RMX/80 diskette. As described in the last
section, a set of macros is included to assist you in
preparing your configuration module. Other files
are provided that are useful when coding calls to
RMX/80 and preparing data structures in PL/M.
RQCTAB ITT Co IET
ITT POINTER
EXCHANGE-ADDRESS-1
EXCHANGE-ADDRESS-2
IET POINTER
[ EXCHANGE
COUNT
sw N o
EXCHANGE-ADDRESS-n
Figure 13. ROM Based Tables
By coding in a modular fashion you can separately
compile and maintain tasks. This is advisable since
a single large module containing all your tasks
would require a lengthy recompilation to change
any one of the tasks. Following the compilation
and assembly of your source code modules, a
library containing the object modules can be
created.
LINKING
The process of linking prepares a single object mo-
dule from libraries containing the RMX/80 object
modules and your own application libraries or se-
parate object modules. The order in which you
specify the files to be linked is crucial to successful
linking. In general, your libraries or separate object
modules should be specified before the RMX/80
libraries. The link command should conclude with
the unresolved library (UNRSLV.LIB) that con-
tains miscellaneous modules for resolving PUBLICs
not used in the application code. PUBLICs extend
the scope of variables to allow linkage between
separate program modules. Figure 14 illustrates
how an application program is linked from RMX/80
and user tasks. |
LOCATING
It is appropriate in this section to give some guide-
lines regarding the assignment of RAM and ROM
address space for your Single Board Computer
environment. The SBC 80 Single Board Computers
have ROM based at location O. Since the LOCATE
program places all code in a contiguous block, the
code must begin at location 0. Likewise, the read/
write (RAM) data is also placed in a contiguous
block. The base address of data should be placed
at your RAM base address. Depending on the
2-14
amount of code space required by your applica-
tion it may be necessary to move the RAM mem-
ory base address on your SBC to a higher location.
A STACKSIZE of zero should be specified because
you allocate stack for each RMX/80 task in the
static task descriptors.
DEBUGGING
As mentioned in the overview of the RMX/80 De-
bugger, the real-time environment is a complex
one in which to debug your programs. Intel pro-
vides two tools that you can use for debugging.
The RMX/80 Debugger and the Intel In-Circuit
Emulator (ICE). It is desirable to have both of
these debugging tools at your disposal.
<Q Terminal
“Ru, Driver
Analog 1/0 Ry, <” High Speed
Drivers / RMX/80 Y Math Driver
№ Executive y
À, Free Space > of
HA, Manager TR
Debugger 3
>”
File
System
Figure 14. RMX/80 Linking
ICE enables you to use Intel Microcomputer Devel-
opment System memory in place of SBC 80 mem-
ory. This allows RAM residency during your debug-
ging as opposed to programming PROMs for each
iteration. Your system may initially fail before the
RMX/80 Debugger can begin operation. In this
situation ICE can be used to debug your program.
APPLICATIONS
RMX/80 is suitable for a wide variety of applica-
tions. Two specific examples are presented in this
application note. Each example illustrates the
steps involved in using RMX/80 and provides a
detailed description of the coding itself.
MINIMAL TERMINAL HANDLER
The basic functions required for a terminal handler
are well defined. The handler must respond to
operator input, transmit output characters, and
echo characters as they are entered. This applica-
tion note describes one implementation of a mini-
mal terminal handler.
The terminal handler presented here is not the
RMX/80 Terminal Handler. It does provide some
common functions and uses the same exchanges
and message formats. However, many features
of the RMX/80 Terminal Handler have been left
out. Omitted features include special hooks to run
with the Debugger, an alarm exchange, control S,
Q, and O operations.
As described in the chapter on using RMX/80, the
process of developing an RMX/80 application be-
gins with the definition of the tasks and exchanges.
The graphic notation is used to prepare a diagram
(Figure 15) showing the tasks, exchanges, and their
interaction.
— TASKS
— EXCHANGES — TASKS
— EXCHANGES
USER
USER
RDMIN
TASK
WRMIN
RECEIVER
READY
| ‚ УЗАВТ TRANSMITTER
READY
Figure 15. Minimal Terminal Handler
As shown in Figure 15, the RDMIN task waits
on the RQINPX exchange for input requests. The
RDMIN task also successively waits on the RQL6EX
and RQL7EX exchanges. It uses the RQL6EX
exchange to determine when a character has been
received by the USART. The RQL7EX exchange
is used to indicate when the transmitter is ready
to accept another character. RDMIN uses RQL7EX
for echoing input characters.
The WRMIN task waits on the RQOUTX exchange
for output requests. When it receives a request, it
2-15
waits on the RQL7EX to determine when charac-
ters can be sent to the USART.
The following listing* shows the RDMIN and
WRMIN tasks. These tasks provide a minimal ter-
minal handler. The program is written in PL/M.
The WRMIN task is also presented in assembly
language in Appendix B. The program listing is
interspersed with explanatory text. The program
begins with the program segment label “MINI-
MALSTERMINALSHANDLER:” and a DO state-
ment.
1 MINIMALSTERMINALSHANDLER:
LU;
Several macros are declared using the reserved
word LITERALLY. These macros are expanded
at compile time by textual substitution.
1 DECLARE TRUE LITERALLY 'OFFH
DECLARE FOREVER LITERALLY VWHILE TRUE"
/* SPECIAL ASCII CHARACTERS */
DECLARE
BELL LITERALLY 'O7H*,
LF LITERALLY 'BAH',
LITERALLY '2DH',
LITERALLY '12H',
LITERALLY '18H',
LITERALLY '1BH',
LITERALLY '7FH';
CONTROLSR
CONTKOLSX
ESC
RUBOUT
Some macros are used to simplify the declaration
of RMX/80 data structures. The structures de-
clared here are for the exchange descriptor, inter-
rupt exchange descriptor, and the messages used
by the minimal terminal handler.
DECLARE EXCHANGESDESCRIPTOR LITERALLY "STRUCTURE (
MESSAGESHEAD ADDRESS,
MESSAGESTAIL ADDRESS,
TASKSHEAD ADDFESS,
TASKSTAIL ADDRESS,
EXCHANGESLINK ADDRESS) *
DECLARE TD NSE aDESCRIPIOR LITERALLY ‘STRUCTURE (
MESSAGESHEAD ADER
MESSAGESTAIL ADDRESS,
TASKSHEAD ADDRESS,
TASKSTAIL ADDRESS,
EXCHANGESLINK ADDKESS,
LINK ADDRESS,
LENGTH TENES.
TYPE BYTE) '
DECLARE THSMSG LITERALLY 'STRUCTURE (
LINK ADDKES
LENGTH ADDRESS,
TYPE BYTE,
HOMESEXCHANGE ALLRESS,
RLS PONSESEXCHANGE ALLRLESS,
STATUS ADDRESS,
BUFFLRSALDKLSS ALLRLSS,
COUNT ADDRESS,
ACTUAL ADDRESS)" ;
The following macros are specifically for the SBC
80/20. The macros require changes to run the
minimal terminal handler on a different Single
Board Computer. Intel 8253 timer/counter and
8251 USART chips are used.
*Full size listings in Appendixes A and C.
7*
8253 PORT ADDRESSES.
*/
6 1 LECLARE A8253$MODE LITERALLY °'@DFH';
9 1 DECLARE A62535CTK2 LITERALLY 'ODEh';
*
8253 COMMANDS.
. */
10 1 DECLARE SELECT$2 LITERALLY '10000000B';
11 1 DECLARE KL$BOTH LITERALLY '00110000B°';
12 1 DECLARE MODE$3 LITERALLY '@0080110B';
13 1 DECLARE B246@ LITERALLY '0@1CH';
*
8251 PORT ADDRESSES.
*
14 1 DECLARE USARTSIN LITERALLY °@ECH',
USAKTSOUT LITERALLY 'BGECh',
USARTSCONTROL LITERALLY 'BEDh';
/*
8251 MODES.
*
15 1 DECLARE STOPS1 LITERALLY 010000008"
16 1 DECLARE CL8 LITERALLY '0000118
17 1 DECLARE RATES16X LITEKALLY 000000108" ;
/*
8251 COMMANDS.
*
18 1 DECLARE USARTSRESET LITERALLY 'G1000U88B',
LITERALLY ¡00100000B",
ERRORSRESET LITERALLY 'OQU18008B',
RXE LITERALLY '00000100B°',
DTR LITERALLY 1900009108",
TXEN LITERALLY ‘'00000601B°;
RDMIN and WRMIN call three RMX/80 opera-
tions. They are RQSEND, RQWAIT, and RQELVL.
RQSEND and RQWAIT allow tasks to send and
receive messages from exchanges. RQELVL enables
a specific interrupt level.
19 1 RUSEND:
PKOCEDUKE (EXCHANGESPOINTER,MESSAGESPOINTER) EXTERNAL;
24 2 DECLARE (EXCHANGESPOINTER, MESSAGES POINTER) ADDRESS;
21 2 END RUSEND;
22 1 RUWAIT:
PROCEDURE (EXCHANGESPOINTER, DELAY) ADDRESS EXTERNAL;
23 2 DECLARE (EXCHANGESPOINTER, DELAY) ACDRESS
24 2 END KUWAIT;
25 1 KQELVL:
. PROCEDURE (LEVEL) EXTERNAL;
26 2 CECLARE LEVEL BYTE;
27 2 END RuELVL;
The exchange descriptors and interrupt exchange
descriptors must be PUBLIC because they are
referenced by the configuration module.
28 1 DECLARE RQINPX EXCHANGESDESCRIPTOR PUBLIC;
29 1 DECLARE RYOUTX EXCHANGESDESCRIPTOR PUBLIC;
30 1 DECLARE RUL6EX INTSEXCHANGESDESCRIPTOR PUBLIC;
31 1 DECLARE RUL7EX INTSEXCHANGESDESCRIPTOR PUBLIC;
The following procedure initializes the 8253 and
8251 (USART). The 8253 generates the baud rate
clock (2400 baud in this example). The program
sends four nulls to the USART control port to
ensure that the USART is ready for a command,
no matter what state it was previously in. The pro-
gram then sends a reset command to the USART,
followed by the mode and another command.
32 1 INITIALIZATION:
PRUCEDURE;
33 2 OUTPUT (AB253$MODE) = SELECT$2 OR RLSBOTH OR MODES3;
34 2 OUTPUT (AB253$CTR2) = LOW(B2480);
35 2 OUTPUT (AB253SCTR2) = HIGH(B2400) ;
36 2 OUTPUT (USAKTSCONTROL) ,
OUTPUT (USARTSCONTROL) ,
OUTPUT (USARTSCONTROL) ,
OUTPUT (USARTSCONTKOL) = @;
37 2 OUTPUT (USAKTSCONTROL) = USARTSRESET;
38 2 OUTEUT (USARTSCONTKUL] = STOPS1 OR CLS OR RATESIÓN;
392 OUTPUT (USARTSCONTROL) = RTS OR EKRORSRESET О
RXE OR DTR OR TXEN;
av 2 END INITIALIZATION;
2-16
Tasks coded in PL/M take the form of parameter-
less PUBLIC procedures. The procedure declara-
tion is followed by the variables used in RDMIN.
MSGPTR receives the address of an input request
message. The based-variable MSG accesses the
data in the input request message. INTMSG is a
dummy variable which simply receives the address
of the interrupt message. BUFSADDRESS points
to the buffer where the input characters are to be
placed. The BUF array is based at the buffer
pointed to by BUFSADDRESS. о
RDSMIN:
1
PROCEDURE PUBLIC;
42 2. DECLARE (MSGPTR, INTMSG,BUFSADDRESS) ADDRESS;
43 2 DECLARE (CHAR,PTK,I) BYTE;
44 2 DECLARE MSG BASED MSGPTR THSMSG
45 2 DECLARE (BUF BASED BUFSADDRESS) (1) BYTE;
The RDMIN task echoes characters after they are
read in. The ECHOSCHAR procedure performs this
function. It waits for a level 7 interrupt, indicating
that the transmitter is ready for another character.
ECHOSCHAR then transmits the character.
46 2 ECHOSCHAR:
‚| PROCEDURE (CHAR);
47 3 DECLARE CHAR BYTE;
48 3 INTMSG = RQWAIT(.ROL7EX,0);
49 3 OUTPUT (USARTSOUT) = CHAR;
508 3 END ECHOSCHAR;
Execution of the RDMIN task starts with the next
statement, a call to the initialization procedure.
This call is followed by two calls to the procedure
which will enable interrupt levels 6 and 7.
51 2 CALL INITIALIZATION;
5% 2 CALL KQELVL(6) ;
53 2 CALL KQELVL(7);
The basic structure of an RMX/80 task is that of
a program with an imbedded infinite loop. This
loop starts with the DO FOREVER statement.
In the continuous loop, the task waits for an input
request message. This wait is satisfied when some
other task in the system sends an input request
message to the RQINPX exchange. The based
variable used to point to BUF is assigned from a
field in the input request message, MSG.BUF-
FERSADDRESS. An index for the BUF array,
PTR, and the variable CHAR are initialized.
54 2 DO FOREVER;
55 3 MSGPTR = RQWAIT(.RQINPX,0};
56 3 BUFSADDRLSS = MSG.BUFFERSADDRESS - 1;
57 3 PIR = 0:
56 3 CHAK = NOT Ck;
Task execution continues inside the next loop
until a carriage return (CR) is input. An escape
character (ESC) within the loop simulates a CR
which enables an exit from the loop. The task
simply waits on the RQL6EX exchange for a mes-
sage. This amounts to an interrupt service routine.
When the wait is satisfied, the USART has received
a character.
‘ DO WHILE CHAR <> CR;
INTMSG = KQWAIT(.RQL6EX, 8) ;
59 3
60 4
The next statement performs a whole series of
operations. The character input from the USART
is logically ANDed with 7FH to mask off the parity
bit, assigned to the variable CHAR, and tested to
determine if it is a RUBOUT character. If a RUB-
OUT is found, either a BELL is echoed to the ter-
minal if there are not characters to delete in the
buffer (PTR = 0), or the last character in the
buffer is echoed and the pointer is decremented.
IF (CHAK := INPUT (USAKTSIN) AND 7FH) = RUBOUT THEN
DO;
IF PTR = 0 THEN
CALL ECHOSCHAR (BELL);
ELSE
DO;
CALL ECHOSCHAR (BUF (PTR));
PTR = PTR - 1;
END;
END;
o
wr
ил О со Ал nu aL
If CHAR is not a RUBOUT, it is tested for a
CONTROLS$X. The function of a CONTROL$X
is to delete the entire line by resetting PTR to
zero. After deleting the line, the system prompts
the operator with a “#” character and is ready to
accept a new line.
ELSE
DO;
IF CHAR = CONTROLSX THEN
DO;
‘
CALL ECHOSCHAR('4');
CALL ECHOSCHAR(CR);
CALL ECHOSCHAR (LF);
PTR = 0;
END;
-~1
a
ANTAL SS
The next test determines if CHAR is a CON-
TROLSR. CONTROLSR echoes the entire line
that has been entered. This function is useful for
displaying a line containing a number of RUBOUTs.
Such lines can be difficult to interpret because
RUBOUT echoes deleted characters. Because
CONTROLS$R echoes only the remaining data
in the buffer, it eliminates “garbage” from the
display.
ELSE
DO;
IF CnAk = CUNTROLSk THEN
DO;
CALL ECHOSCHAR(Ck);
CALL ECHOSCHAR(LF);
DO I = 1 TO PTh;
CALL ECHUSCHAK(BUF(I1));
END;
со
N
“4 60 66 =) Un
END;
2-17
The character is then placed in the buffer unless
the end of the buffer has been reached. If the
buffer is full, a BELL is sent to the terminal.
ELSE
DO;
IE PTk < MSG.COLUNT ThktN
BUE(PTR := PIR+1) = CHAK;
ELSE
О;
IF CHAR <> Ck THEN
CHAR = BELL;
END;
o
=
®e«es ~~ oe
The last test is for an ESC character. It is echoed as
a “$” and is treated as if a CR were entered.
IF CHÂK = EsC THEN
Lo;
CALL ECHOSCHAR('S');
ChAk = Ch;
END;
CALL ECHUSCHAR(CHAn);
ND;
чо
<
Noh е) СО СО 60 е
The program places a line feed (LF) at the end of
the buffer when an exit is forced by a CR or an
ESC. The input request message actual character
count (MSG.ACTUAL) and the status (MSG.
STATUS) are set before sending the message to
its response exchange.
IF PTR < MSG.COUNT THEN
BUE (PTR:=PTR+1) = LF;
MSG. ACTUAL = PTR;
MSG.STATUS = 6;
CALL RUSEND (MSG.RESPONSESEXCnANGE ,MSGPTR) ;
CALL ECHUSCHAR(LF);
[=
=
œ
DO WwW ww Ww
END;
END kKESMIN;
The WRMIN task begins by enabling interrupt
level 7. Note that no other initialization is per-
formed before WRMIN waits for an output request
message to arrive at the RQOUTX exchange. Here
correct operation depends on the fact that RDMIN
has a higher priority than WRMIN. Were this not
the case, WRMIN could try to transmit a message
before the 8253 and 8251 have been set up.
WkKSMIN:
PROCEDURE PUBLIC;
DECLARE (MSGPTR,INTMSG,BUESADDRESS) ADDRESS;
DECLARE PTR BYTE; .
DECLARE MSG BASED MSGPTR THSMSG;
DECLARE (BUE BASED BUFSADDRESS) (1) BYTE;
CALL RUELVL(7);
DO FOREVER;
MSGPTR = RQWALIT(.RQOUTX,0);
BUFSADDRESS = MSG. BUFFERSADDRESS - |;
>
—
on
e La N DNNDN —
The next loop transmits all of the characters speci-
fied by the output request message. Once again,
the interrupt service routine is implemented by
simply waiting on the RQL7EX exchange for a
transmitter ready interrupt message. When this
message is received, the next character in the
buffer is transmitted.
DO PTR = 1 TO MSG.CCUNT;
INTMSG = KUWAIT (.RQUL7EX,0);
OUTPUT (USARTSOUT) = BUF (PTK);
ND;
-
N
ta
- du
The WRMIN task concludes by setting the actual
count and status, and then sends the output re-
quest message to its response exchange.
MSG.ACTUAL = MSG.COUNT;
MSG.STATUS = U;
CALL ROSEND (MSG. RESPONSESEXCHANGE, MSGPTK) ;
—
v
+
NN) ww ww
EN
END WRSMING
Using the macros provided on the RMX/80 dis-
kette, the following static task descriptors (STD)
should be placed in your configuration module.
STD
STD
RDMIN,64,112,0
WRMIN,64,128,0
The entries in the STD are interpreted as follows.
NAME,STKLEN,PRI,EXCH
STD
where:
NAME = the symbolic name assigned to the task asso-
ciated with the STD
STKLEN = the number of bytes allocated to the task
stack
PRI = the task priority level
EXCH = an optional field, usually 0
Priorities of 112 and 128 have been assigned to
RDMIN and WRMIN because they. correspond to
hardware interrupt levels 6 and 7.
The ‘ following exchange addresses should be
placed in your configuration module.
ROINPX
XCHADR
XCHADR RQOUTX
XCHADR RQLGEX
XCHADR RQL7EX
The XCHADR macro only requires the address of
the exchange descriptor.
Characters typed at the terminal are ignored unless
an input request message has been received. Thus,
type-ahead is not a built-in feature. However,
if type-ahead is desired, it is sufficient to ensure
that input requests are always queued for -the
RDMIN task and that the full input buffers are
sent to an exchange that queues full buffers.
2-18
This can easily be accomplished by sending several
input requests to the RQINPX. These input
requests have the address of a “full-buffer” ex-
change as the response exchange and the RQINPX
exchange as the home exchange. Then, tasks need-
ing terminal input wait on the “full-buffer” ex-
change and send the message to the home exchange
when finished.
CLOSED-LOOP ANALOG CONTROL
In the next example, a closed-loop analog control
subsystem using the Intel SBC 711 analog-to-
digital board illustrates task scheduling and syn-
chronization in a process control application. In
general, the subsystem samples an analog input at
specified intervals, converts the data to temperature
in degrees centigrade, and then — based upon pro-
grammed temperature limits — controls a heating
element. The algorithm used provides a 2-position
controller with neutral intermediate zone (or sim-
ply “bang-bang” control). The control algorithm
is shown in Figure 16. |
OUTPUT SWITCHING POINTS
A
POSITION 1
(ON)
POSITION 2 Na
(OFF) a
. SETPOINT
» TEMPERATURE
Figure 16. 2-Position Controller with Neutral Intermediate
Zone
The graphic notation in Figure 17 diagrams the
tasks, exchanges, and their interaction.
TSPARAMS
LOCK
EXCH
RETSPULSE
EXCH RETSTRIG
EXCH
CONTROL
TASK
TICKER
TASK
ADC
TASK
TRIGGER
EXCH
GOSPULSE
EXCH
Figure 17. Analog Subsystem
This application includes three tasks and six asso-
ciated exchanges. The TICKER task schedules
the ADC task. TICKER has a very high priority
because nothing else in the system should inter-
fere with its scheduling activities. It is also a very
short task since it repetitively executes a timed
wait and then handshakes a message.
TICKER schedules the ADC task. The ADC task
services the A/D converter. After obtaining data
from the A/D it handshakes with the CONTROL
task to signal that data is ready for processing.
The ADC task is assigned a priority equivalent
to the level of the hardware interrupt from the
A/D. Clearly, calculations should not be performed
at that priority.
Thus, CONTROL performs the processing function
at a lower priority. The CONTROL task used the
TSPARAMSLOCK exchange to govern access to
the control parameters. This avoids problems re-
sulting when some other task is updating the pa-
rameters at the same time the CONTROL task is
using them for testing.
As in the minimal terminal handler, the following
listing contains the complete analog subsystem
tasks and is interspersed with explanatory text.
The program begins with the program segment
label “ATOD:” and a DO statement.
1 ATOD:
DO;
The macros and externals used in this module
are brought in by means of INCLUDEs from the
RMX/80 diskette.
$SINCLUDE(:F1:COMMON.ELT)
DECLARE TRUE LITERALLY "ОВЕН";
DECLARE FALSE LITERALLY 'OCH';
DECLARE BOOLEAN LITERALLY 'BYTE';
DECLARE FOREVER LITERALLY ‘WHILE 1°;
ло о nv
- a
$INCLUDE( :F1:EXCH.ELT)
DECLARE EXCHANGE$DESCRIPTOR LITERALLY *STRUCTURE (
MESSAGESHEAD ADDRESS,
MESSAGE$TAIL ADDRESS,
TASK$HEAD ADDRESS,
TASK$TAIL ADDRESS
EXCHANGE$LINK ADDRESS);
“nu
$INCLUDE(:F1:IED.ELT)
DECLARE INT$EXCHANGE$DESCRIPTOR LITERALLY 'STRUCTURE (
MESSAGE$HEAD ADDRESS,
MESSAGE$TAIL ADDRESS,
TASK$HEAD ADDRESS,
TASK$TAIL ADDRESS,
EXCHANGE$LINK ADDRESS,
LINK ADDRESS,
LENGTH ADDRESS,
TYPE BYTE)';
uw."
$INCLUDE( :F1:MSG.ELT)
DECLARE MSG$HDR LITERALLY *
LINK ADDRESS,
LENGTH ADDRESS,
TYPE BYTE,
HOME$ EXCHANGE ADDRESS,
RESPONSE$EXCHANGE ADDRESS‘;
DECLARE MSG$DESCRIPTOR LITERALLY *STRUCTURE(
MSG$HDR
REMAINDER( 1) BYTE)
$ INCLUDE( :F1:INTRPT, EXT)
RQENDI:
PROCEDURE EXTERNAL;
AU 08 SE UNO ON OU AE EN MODA
2-19
11 2 = END RQENDI;
12 1 = RQELV
= PROCEDURE (LEVEL) EXTERNAL;
13 2 = DECLARE LEVEL BYTE;
=
14 2 = END RQELVL;
15 1 = RODLVL:
= PROCEDURE (LEVEL) EXTERNAL;
16 д = DECLARE LEVEL BYTE;
17 д =: END RODLVL;
18 1 = RQSETV:
= PROCEDURE (PROC,LEVEL)! EXTERNAL:
19 2 = DECLARE PROC ADDRESS
20 2 =: DECLARE LEVEL BYTE;
21 2 = END RQSETV;
$INCLUDE( :F1:SYNCH.EXT)
22 1 = ROSEND:
z PROCEDURE (EXCHANGE$POINTER,MESSAGE$POINTER) EXTERNAL;
23 2 = DECLARE (EXCHANGE$POINTER,MESSAGE$POINTER) ADDRESS;
24 д = END RQSEND;
25 tos RQWAIT:
= PROCEDURE ( EXCHANGES$POINTER,DELAY) ADDRESS EXTERNAL;
26 2 = DECLARE (EXCHANGESPOINTER, DELAY) ADDRESS;
27 2 = END RQWAIT;
28 1 = RQACPT:
= PROCEDURE (EXCHANGESPOINTER) ADDRESS EXTERNAL;
23 2 = DECLARE EXCHANGE$POINTER ADDRESS;
30 2 = END RQACPT;
31 1 = RQISND:
PROCEDURE (IED$PTR) EXTERNAL;
32 2 = DECLARE IED$PTR ADDRESS;
33 2 = END RQISND;
Additional macros are declared to aid in the use
of the SBC 711 analog-to-digital board.
7
SBC 711 ANALOG TO DIGITAL BOARD
*/
34 à DECLARE ADC$BASE ADDRESS AT (ОРТООН
35 1 DECLARE COMMAND$REGISTER BYTE AT (,ADC$BASE+0);
36 1 DECLARE STATUS$REGISTER BYTE AT (.ADC$BASE+0);
37 1 DECLARE FIRST$CHANNELSREGISTER BYTE AT (.ADCSBASE+1);
38 1 DECLARE LAST$CHANNELSREGISTER BYTE AT (.ADC$BASE+2);
39 1 DECLARE CLEAR$INTERRUPT$REQUEST BYTE AT (.ADC$BASE+3);
0 DECLARE - ADCSDATASREGISTER ADDRESS AT (.ADC$BASE+1);
4 1 DECLARE GO$BIT LITERALLY ‘1°
a2 1 DECLARE AUTOS INCREMENTSENABLE LITERALLY *2 ;
a3 1 DECLARE BUSY LITERALLY '8';
TE. DECLARE EOS$INTERRUPTS$ENABLE LITERALLY *10H';
451 DECLARE EOC$INTERRUPT$ENABLE LITERALLY * 20H‘;
461 DECLARE ENDSOF$SCAN LITERALLY ' ВОН’;
47 1 DECLARE END$OF$CONVERSION LITERALLY *80H';
The exchange descriptors and the interrupt ex-
change descriptors are declared.
48 1 DECLARE DUMMY EXCHANGE$DESCRIPTCR PUBLIC;
491 DECLARE RET$PULSE EXCHANGE$DESCRIPTOR PUBLIC;
50 1 DECLARE GO$PULSE EXCHANGE$DESCRIPTOR PUBLIC;
51 1 DECLARE TRIGGER EXCHANGE$DESCRIPTOR PUBLIC;
52 1 DECLARE RET$TRIG EXCHANGESDESCRIPTOR PUBLIC;
53 1 DECLARE RQL2EX INT$EXCHANGESDESCRIPTOR;
The CONTROL task uses an external data struc-
ture to obtain operating parameters. This data
structure (BOXSPARAMS) has an exchange asso-
ciated with it (TSPARAMSLOCK) that is used to
provide mutual exclusion, ensuring that only one
task accesses the data structure at a time.
54 1 DECLARE T$PARAM$LOCK EXCHANGE$DESCRIPTOR EXTERNAL;
55 1 DECLARE BoxsPARaHS (5) STRUCTURE(
CH EL
SETSPOINT ADDRESS,
ERROR ADDRESS,
OFFSET ADDRESS,
SAMPLES ADDRESS,
COUNT ADDRESS,
ACCUM ADDRESS,
READING ADDRESS ) EXTERNAL;
TICKER, the scheduler task, has an initialization
sequence in which it sets up two messages and
sends them to the RETSPULSE exchange. Then it
enters an infinite loop where it waits on the
DUMMY exchange for 250 milliseconds. After
the timed wait is complete, TICKER passes a mes-
sage from the RET$PULSE exchange to the GO$-
PULSE exchange. In effect this is a handshake,
checking to see that the ADC task has completed
its last operation and then signaling it to perform
another.
56 1 TICKERS TASK:
PROCEDURE PUBLIC;
57 2 DECLARE MSG ADDRESS
58 2 DECLARE PULSESMSG(2) STRUCTURE (
MSG$HDR
59 2 PULSE$MSG(O0).LENGT
PULSE$MSG(1). LENGTH = SIZE( PULSE$MSG(0));
60 2 PULSE$MSG(0).TYPE,
PULSE$MSG(1).TYPE = 65;
61 2 CALL RQSEND(.RET$PULSE,,PULSE$MSC(0));
62 2 CALL RQSEND(.RET$PULSE,.PULSESMSG(1));
63 2 DO FOREVER;
64 3 MSG = ROWAIT(.DUMMY,5);
65 3 MSG = RQWAIT(.RET$PULSE,0);
66 3 CALL RQSEND(.GO$PULSE,MSG);
67 3 ND;
68 2 END TICKER$TASK;
Scheduled by TICKER, the ADC task performs the
A/D sampling. It begins by setting up TRIGGER $-
MSG and enabling the level 2 interrupt from the
A/D. Inside the ADC task continuous loop, mes-
sages are passed from the GOSPULSE exchange to
the RETSPULSE exchange. Then it waits for ac-
cess to the BOXSPARAMS data structure. When
the ADC task has access, it loops through the A/D
channels, accumulating readings in BOX$PARAMS.
After all the A/D channels are sampled and the
BOXS$PARAMS readings updated, the LOCK$SMSG
is returned to the TSPARAM$LOCK exchange.
The ADC task concludes the continuous loop by
handshaking a message with the CONTROL task.
FIRST$ CHANNEL$ REGISTER = BOXS PARANS CD CHANNEL
+ ROL(GAIN,6);
69 1 ADC$TASK:
PROCEDURE PUBLIC;
70 2 DECLARE TRIGGER$MSG STRUCTURE (
MSG$HDR );
71 2 DECLARE (T$MSG,MSG,LOCK$MSG) ADDRESS;
72 2 DECLARE I EYTE;
73 2 DECLARE GAIN LITERALLY ‘00°;
74 2 DECLARE N$CHNLS LITERALLY '5';
75 2 TRIGGER$MSG.LENGTH = SIZE(TRIGGERSNSO) ;
76 2 TRIGGER$MSG.TYPE = 6
77. 2 — CALL RQSEND( . ¿RETOTRIO, + TRIGGER$MSG) ;
78 2 CALL RQELVL
79 2 DO FOREVER;
80 3 MSG = ROWAIT( .GO$PULSE, 0) ;
81 3 CALL RQSEND(.RET$PULSE, MSG);
82 3 LOCK$MSG = RQWAIT(.T$PARAM$LOCK,0);
83 3 DO I = 0 TO N$CHNLS-1;
84 4
4
COMMAND$REGISTER = GO$BIT
OR EOC$INTERRUPT$ENABLE;
86 4 MSG = RQWAIT(.RQL2EX,0);
87 4 COMMAND$REGISTER = 0;
88 1 BOX$PARAMS(I).ACCUM = BOX$PARAMS(I).ACCUM
+ ADC$DATA$REGISTER;
89 14 END;
90 3 CALL RQSEND(.T$PARAM$LOCK,LOCK$MSG);
91 3 T$MSG = RQWAIT(.RET$TRIG,0);
92 3 CALL RQSEND(.TRIGGER,T$MSG):
93 3 ND;
94 2 END ADC$TASK;
The CONTROL task waits for a message from the
ADC task signaling that A/D readings have been
taken and are ready for further processing. It com-
pletes the handshake by sending the message to
the RET$STRIG exchange. Then, as in the ADC
task, accesses the BOXSPARAMS data structure.
Inside the next loop, the readings are averaged,
scaled, offset, and tested. Appropriate action is
taken to turn the heating elements on or off. The
loop concludes by returning the message to the
TSPARAMSLOCK exchange.
95 1 CONTROL$TASK:
PROCEDURE PUBLIC;
96 2 DECLARE (LOCKSMSG, T, MSG) ADDRESS;
97 г DECLARE I BYTE;
98 2 DECLARE NCHNLS LITERALLY '5';
99 2 DECLARE TURN$LAMP$ON
LITERALLY 'OUTPUT(OETH)=SHL(I,1)';
100 2 DECLARE TURNS LAMPS OFF
LITERALLY ‘OUTPUT(OE7H) = SHLCT, 1) +1°
101 г . DECLARE SETUP$8255 LITERALLY ‘OUTPUT(OE7H) = 80H;
OUTPUT(OE6H) = OFFH'
102 2 SETUP$8255;
104 2 DO FOREVER;
105 3 MSG = ROWAIT(. TRIGGER, 0);
106 3 CALL RQSEND(.RET$TRIG,MSG);
107 3 LOCK$MSG= RQWAIT(. T$PARAM$LOCK, 0);
108 3 DO I = 0 TO NCHNLS-1;
109 4 BOX$PARAMS(I).COUNT = BOX$PARAMS(I).COUNT + 1;
4
IF BOX$PARAMS(I).COUNT
= BOX$PARAMS(I).SAMPLES THEN
112 5 T,
BOX$PARAMS(I),READING
= (BOX$PARAMS(I).ACCUM
/BOX$PARAMS(1I).SAMPLES) / 38
+ BOX$PARAMS(I).OFFSET;
113 5 IF T <= BOX$PARAMS(I).SET$POINT
- BOX$PARAMS(I).ERROR THEN
114 5 TURN$LAMP$ON;
ELSE
115 5 IF T >= BOX$PARAMS(I).SET$POINT
+ BOX$PARAMS(I).ERROR THEN
116 5 TURN$LAMPSOFF ;
BOX$PARAMS(I).ACCUM,
BOX$PARAMS(I).COUNT = 0;
118 5 ND;
119 4 END;
120 3 CALL RQSEND(.T$PARAM$LOCK,LOCK$MSG);
121 3 END;
122 2 END CONTROL$TASK;
123 1 END ATOD;
The purpose of this application note is to intro-
duce you to the Intel RMX/80, Real-Time Multi-
tasking Executive. The general framework of
RMX/80 was discussed, including the nucleus and
extensions.
This application note described the steps involved
in using RMX/80. Key emphasis has been placed
on the need to fully define the tasks and exchanges
in your application using graphic notation.
Applications have been presented to demonstrate
task communication, synchronization, and mutual
exclusion in a minimal terminal handler and an
analog subsystem. The tasks responded to real-
time asynchronous events such as USART and
A/D interrupts.
RMX/80 represents a significant step in the sophis-
tication of microcomputer software. Its ease of
use, flexibility, and power should enable you to
quickly implement real-time software for your
applications.
Ww N?
Oo on
APPENDIX A
MINITH PL/M LISTING
MINIMALSTERMINALSHANDLER:
DO,
DECLARE TRUE LITERALLY '@FFH';
DECLARE FOREVER LITERALLY ‘WHILE TRUE’;
/* SPECIAL ASCII CHARACTERS */
DECLARE
BELL LITERALLY 'Q07H',
LF LITERALLY '@QAR’',
CR LITERALLY 'GBDH',
CONTROLSR LITERALLY '128'’,
CONTROLSX LITERALLY '186',
ESC LITERALLY '1BH',
RUBOUT LITERALLY '7FH';
DECLARE EXCHANGESDESCKRIPTOR LITERALLY 'STKUCTURE (
MESSAGESHEAD ADDRESS,
MESSAGESTAIL ADDRESS,
TASKSAEAD ADDRESS,
TASKSTAIL ADDRESS,
EXCHANGESLINK ADDRESS) ';
DECLARE INTSEXCHANGESDESCRIPTOR LITERALLY "STRUCTURE
MESSAGESHEAD ADDRESS,
MESSAGESTAIL ADDRESS,
TASKSHEAD ADDRESS,
TASKSTAIL ADDRESS,
EXCHANGESLINK ADDRESS,
LINK ADDRESS,
LENGTH ADDRESS,
TYPE BYTE) ';
DECLARE ThSMSG LITERALLY 'STRUCTURE (
LINK ADDRESS,
LENGTH ADDRESS,
TYPE BYTE,
HOMESEXCHANGE ADDRESS,
RESPONSESEXCHANGE ADDRESS,
STATUS ADDRESS,
BUFFERSADDRESS ADDRESS,
COUNT ADDRESS,
ACTUAL ADDRESS) ';
/*
8253 PORT ADDRESSES.
*/
LECLARE A8253SMODE LITERALLY 'ODFH'
DECLARE A8253SCTKR2 LITERALLY "ODER!
(
2-21
14
15
17
18
19
20
21
HHHbH
HHH
HH NN NN
HH
N N
/*
8253 COMMANDS.
* / | a
DECLARE SELECTS2 LITERALLY '10000000B';
DECLARE RLS$BOTH LITERALLY 'GO0110000B';
DECLARE MODES3 LITERALLY '00000110B';
DECLARE B2400 LITERALLY 'QÓG1CH';
/*
8251 PORT ADDRESSES.
* /
DECLARE USARTSIN LITERALLY 'QECH',
USARTSOUT LITERALLY 'GECH',
USARTSCONTROL LITERALLY ‘GEDA’
“о
/*
8251 MODES.
* / ВО
DECLARE STOPS1 LITERALLY '01000000В';
DECLARE CL8 LITERALLY 'O0001100B';
DECLARE KATES16X LITERALLY 'B0V00010B':
/*
8251 COMMANDS.
*/
DECLARE USARTSRESET LITERALLY 'B1U00000B',
RTS LITERALLY 'G0100B00B',
ERRORSRESET LITERALLY 'O0U10000B',
RXE LITERALLY 'B00U00100B',
DTR LITERALLY '00000010B',
'TXEN LITERALLY '00060006@1B"';
RUSEND:
PROCEDURE (EXCHANGESPOINTER,MESSAGESPOINTER) EXTERNAL;
DECLARE (EXCHANGESPOINTER,MESSAGESPOINTER) ADDRESS;
END RUSEND; |
RQWAIT : | |
PROCEDURE (EXCHANGESPOINTER,DELAY) ADDRESS EXTERNAL;
DECLARE (EXCHANGESPOINTER, DELAY) ADDRESS;
END RUWAIT; |
ROELVL:
PROCEDURE (LEVEL) EXTERNAL;
CECLARE LEVEL BYTE;
END RUELVL;
DECLARE RQINPX EXCHANGESDESCRIPTOR PUBLIC;
DECLARE RyOUTX EXCHANGESDESCRIPTOR PUBLIC;
DECLARE RQL6EX INTSEXCHANGESDESCRIPTOR PUBLIC;
DECLARE REOL7EX INTSEXCHANGESDESCRIPTOR PUBLIC;
INITIALIZATION:
PROCELURE; -
OUTPUT (A8253$MODE)
OUTPUT (A8253SCTR2)
SELECTS2 OR KLSBOTH OR MODES3;
LOW(B2400) ;
2-22
35
36
37
35
40
41
42
44
45
46
47
48
49
50
O O Oy ay ÓN UIT >
N NN
N
N www N D N NN H-
N N
UN SS SS SW WWW N
ul a au
Un
OUTPUT (A8253SCTR2) = HIGH (B24v0) ;
OUTPUT (USARTSCONTROL) ,
OUTPUT (USARTSCONTROL) ,
CUTPUT (USARTSCONTROL) ,
OUTPUT (USARTSCONTROL)
OUTPUT (USARTSCONTROL)
OUTPUT (USARTSCONTROL)
OUTPUT (USARTSCONTROL)
0;
USARTSRESET;
STOPS1 OR CL8 OR RATESl6X;
RTS OR ERRORSRESET OR
RXE OR DTR OR TXEN;
END INITIALIZATION;
RDSMIN:
PROCEDURE PUBLIC;
DECLARE (MSGPTR,INTMSG,BUFSADDRESS) ADDRESS;
DECLARE (CHAR,PTR,I) BYTE;
DECLARE MSG BASED MSGPTR THSMSG;
DECLARE (BUE BASED BUFSADDRESS) (1) BYTE;
ECHOSCHAR:
PROCEDURE (CHAR) ;
DECLARE CHAR BYTE;
INTMSG = ROWAIT(.ROL7EX,0);
OUTPUT (USARTSOUT) = CHAR;
END ECHOSCHAR;
CALL INITIALIZATION;
CALL kuELVL (6) ;
CALL RUELVL (7);
DO FOREVEK;
MSGPTR = REWAIT(.ROINPX,();
BUFSADDRESS = MSG.BUFFERSADDRESS - 1;
PTR = 0;
CHAR = NOT CK;
DO WHILE CHAR <> CR;
INTMSG = RYWAIT(.RQL6EX, 0) ; |
IF (CHAR := INPUT (USARTSIN) AND 7FH) = RUBOUT THEN
DO;
IF PTR = 0 THEN
CALL ECHOSCHAR (BELL) ;
ELSE
DO;
CALL ECHOSCHAR (BUF (PTR) ) ;
PTR = PTR - 1;
END;
END;
- ELSE
DO;
IF CHAR = CONTROLSX THEN
DO; ;
CALL ECHOSCHAR('#');
CALL ECHOSCHAR (CR) ;
CALL ECHOSCHAR(LF) ;
PTR = 0;
END;
ELSE
DO;
2-23
113
114
115
116
127
130
J0OONUS SOC
N WWW WG WW SU =} =] СО ©0 ©0 —] =] ОО CO JO
VD N NN -
N
| НО О в В О О О
IF CHAR = CONTROLSK THEN
DO;
CALL ECHOSCHAR (CR);
CALL ECHOSCHAR (LF);
DO I = 1 TO PTK;
- CALL ECHOSCHAR(BUF(1));
END;
END;
ELSE
DO;
IF PTR < MSG.COUNT THEN
BUF (PTR := PTR+1) = CHAR;
ELSE
DO;
IF CHAR <> CK THEN
CHAR = BELL;
END;
IF CHAR = ESC THEN
DO;
CALL ECHOSCHAR('S") ;
CHAR = CR;
END;
CALL ECHOSCHAR (CHAK) ;
END;
END;
END;
END;
IF PTR < MSG.COUNT THEN
BOF (PTR:=PTR+1) = LF;
MSG.ACTUAL = PTR;
MSG.STATUS = 0;
CALL RUSEND (MSG. RESPONSESEXCHANGE, MSGPTR);
CALL ECHOSCHAR (LF);
END;
END RDSMIN;
WRSMIN:
PROCEDURE PUBLIC;
DECLARE (MSGPTR,INTMSG,BUFSADDRESS) ADDRESS;
CECLARE PTR BYTE;
DECLARE MSG BASED MSGPTR THSMSG;
DECLARE (BUF BASED BUFSADDRESS) (1) BYTE;
CALL RUELVL (7);
DO FOREVER; |
MSGPTR = RQOWAIT (.RQOUTX, 0) ;
BUFSADDRESS = MSG.BUFFERSADDRESS - 1;
DO PTR = 1 TO MSG.CCUNT; |
INTMSG = ROWAIT(.RQL7EX,0);
OUTPUT (USARTSOUT) = BUF (PTK) ;
END; | |
MSG. ACTUAL
MSG. STATUS
CALL KGSEND
END;
END WRSMIN;
END MINIMALSTERMINALSHANDLER;
'MSG.COUNT;
0; |
MSG. RESPONSESEXCHANGE , MSGPTR) ;
— HU
2-24
LOC
00EC
0000
0002
0005
0008
000B
000E
000F
0012
0013
0014
0015
0016
0017
0018
001A
001B
001D
001E
001F
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
002A
002B
002E
002F
0030
0033
0036
0039
003A
003B
003C
003D
003F
0040
OBJ
0 EO 7
CDO000
110000
010000
CD0O000
ES
110700
19
LE
23
4 6
23
C5
3600
23
3600
23
SE
23
56
23
LE
23
46
23
71
23
70
78
B1
CA4300
C5
D5
110000
010000
CDOOOO
D1
C1
1A
13
D3EC
0B
C32900
APPENDIX B
WRMIN ASSEMBLY LANGUAGE LISTING
SEQ
NN) ed ed 00 AP 25 A 28 AP AP A
O DONQU EN O DO NOU uN
№ о № п № № Ю о
DO СО Кл 4 60 ГО —
WW WW WWW О WW WW
O ON QU FU ND — ©
= EEE EE
II сли ло 4 6 Г) — ©
‘лол о +
-— OW o
52
DATOUT
WRMIN:
WRO:
WR1:
WR2:
NAME
EXTRN
PUBLIC
EQU
CSEG
MVI
CALL
LXI
LXI
CALL
PUSH
LXI
DAD
MOV
INX
MOV
INX
PUSH
MVI
INX
MVI
INX
MOV
INX
MOV
INX
MOV
INX
MOV
INX
MOV
INX
MOV
MOV
ORA
JZ
PUSH
PUSH
LXI
LXI
CALL
POP
POP
LDAX
INX
OUT
DCX
JMP
SOURCE STATEMENT
WRMIN
RQELVL,RQOUTX,RQWAIT,RQSEND
WRMIN,RQLTEX
OECH
C,
RQELVL
D,0
B,RQOUTX
RQWAIT
= 3
=
©
©
L LILZLUZÍZAQALIOIXZXEZAELEZEOLTLOÓLAZORZL
ue o a = = = =
=
Po
= U O
AIT
DOW Two w= =
Oo -
DATOUT
WR 1
QL7EX
’
.
,
,
.
y
o
?
USART OUTPUT PORT ADR
ENABLE INTERRUPT LVL 7
WAIT FOR OUTPUT RQST
PUSH MESSAGE ADDRESS
GET RESPONSE EXCHANGE
PUSH RESPONSE EXCHANGE
STATUS = O
GET BUFFER ADR/IN DE
GET COUNT IN BC
ACTUAL = COUNT
EXIT LOOP IF COUNT = 0
WAIT FOR TXRDY INTRPT
TRANSMIT NEXT CHAR
2-25
0043 C1 53 POP B ; BC RESPONSE EXCHANGE
0044 D1 54 POP D s DE = MSG ADDRESS
0045 CDOONOO E 55 CALL RQSEND ; SEND MSG TO RESP. EXCH
0048 C30500 C 56 JMP WRO
57 3
58 DSEG
59 RQLTEX:
000F 60 DS 15
61 5
62 END
2-26
Ul Zw ho
10
11
12
13
14
o — eed
APPENDIX C
ATOD PL/M LISTING
ATOD:
DO;
$INCLUDE( :F1:COMMON.ELT)
DECLARE TRUE LITERALLY 'OFFH';
DECLARE FALSE LITERALLY '00H':
DECLARE BOOLEAN LITERALLY 'ВУТЕ';
DECLARE FOREVER LITERALLY 'WHILE
$INCLUDE( :F1:EXCH.ELT)
DECLARE EXCHANGE$DESCRIPTOR LITERALLY *STRUCTURE (
MESSAGE$HEAD ADDRESS,
MESSAGE$ TAIL ADDRESS,
TASK$HEAD ADDRESS,
TASK$TAIL ADDRESS,
EXCHANGE$LINK ADDRESS)" ;
$INCLUDE( :F1:IED.ELT)
DECLARE INT$EXCHANGE$DESCRIPTOR LITERALLY ‘STRUCTURE (
MESSAGE$HEAD ADDRESS,
MESSAGE$TAIL ADDRESS,
TASK$HEAD ADDRESS,
TASK$TAIL ADDRESS,
EXCHANGE$LINK ADDRESS,
LINK ADDRESS,
LENGTH ADDRESS,
TYPE BYTE)';
$INCLUDE( :F1:MSG.ELT)
DECLARE MSG$HDR LITERALLY *
LINK ADDRESS,
LENGTH ADDRESS,
TYPE BYTE,
HOME$ EXCHANGE ADDRESS,
RESPONSE$EXCHANGE ADDRESS’;
DECLARE MSG$DESCRIPTOR LITERALLY
MSG$HDR,
REMAINDER(1) BYTE)';
$INCLUDE( :F1:INTRPT.EXT)
RQENDI:
PROCEDURE EXTERNAL;
END RQENDI;
RQELVL:
PROCEDURE (LEVEL)
EXTERNAL;
DECLARE LEVEL BYTE;
END RQELVL;
1";
' STRUCTURE(
2-27
15
16
17
18
19
20
21
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
45
46
o — — nd lA
ед = — o ==> o——
RQDLVL:
PROCEDURE
DECLARE
(LEVEL) EXTERNAL;
LEVEL BYTE;
END RQDLVL;
RQSETV:
PROCEDURE (PROC,LEVEL) EXTERNAL;
DECLARE PROC ADDRESS;
DECLARE LEVEL BYTE;
END RQSETV;
$INCLUDE( :F1:SYNCH.EXT)
— RQSEND:
PROCEDURE (EXCHANGE$POINTER,MESSAGE$POINTER) EXTERNAL;
DECLARE (EXCHANGE$POINTER,MESSAGE$POINTER) ADDRESS;
END RQSEND;
RQWAIT:
PROCEDURE ( EXCHANGE$POINTER,DELAY) ADDRESS EXTERNAL;
DECLARE ( EXCHANGE$POINTER,DELAY) ADDRESS;
END RQWAIT;
RQACPT:
PROCEDURE ( EXCHANGE$POINTER) ADDRESS EXTERNAL;
DECLARE EXCHANGE$POINTER ADDRESS;
END RQACPT;
RQISND:
PROCEDURE (IED$PTR) EXTERNAL;
DECLARE IED$PTR ADDRESS;
END RQISND;
/ *
SBC 711 ANALOG TO DIGITAL BOARD
* /
DECLARE ADC$BASE ADDRESS AT (OF700H);
DECLARE COMMAND$REGISTER BYTE AT (.ADC$BASE+0);
DECLARE STATUS$REGISTER BYTE AT (.ADC$BASE+0);
DECLARE FIRST$CHANNEL$REGISTER BYTE AT (.ADC$BASE+1);
DECLARE LAST$CHANNEL$SREGISTER BYTE AT (.ADC$BASE+2);
DECLARE CLEARSINTERRUPT$REQUEST BYTE AT (.ADC$BASE+3);
DECLARE ADC$DATA$SREGISTER ADDRESS AT (.ADC$BASE+!);
DECLARE GO$BIT LITERALLY '1';
DECLARE AUTO$INCREMENT$ENABLE LITERALLY '2';
DECLARE BUSY LITERALLY '8';
DECLARE EOS$INTERRUPT$ENABLE LITERALLY ‘ 10H* :;
DECLARE EOC$INTERRUPT$ENABLE LITERALLY '20H':
DECLARE *4OH';
END$OF$SCAN LITERALLY
2-28
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
N N
ГО ГО го MN Го no ww LWW N N
NN NN
DECLARE
DECLARE
DECLARE
DECLARE
DECLARE
DECLARE
DECLARE
DECLARE
DECLARE
END$OF$CONVERSION LITERALLY '80H';
DUMMY EXCHANGE$DESCRIPTOR PUBLIC;
RET$PULSE EXCHANGE$DESCRIPTOR PUBLIC;
GO$PULSE EXCHANGE$DESCRIPTOR PUBLIC;
TRIGGER EXCHANGE$DESCRIPTOR PUBLIC;
RET$TRIG EXCHANGE$DESCRIPTOR PUBLIC;
RQL2EX INT$EXCHANGE$DESCRIPTOR;
T$PARAM$LOCK EXCHANGE$DESCRIPTOR EXTERNAL;
BOX$PARAMS(5) STRUCTURE(
CHANNEL BYTE,
SET$POINT ADDRESS,
ERROR ADDRESS,
OFFSET ADDRESS,
SAMPLES ADDRESS,
COUNT ADDRESS,
ACCUM ADDRESS,
READING ADDRESS ) EXTERNAL;
TICKER$ TASK:
PROCEDURE PUBLIC;
DECLARE MSG ADDRESS;
DECLARE PULSE$MSG(2) STRUCTURE (
MSG$HDR )
PULSE$MSG(0).LENGTH,
PULSE$MSG(1).LENGTH = SIZE( PULSE$MSG(0));
PULSE$MSG(0).TYPE,
PULSE$SMSG(1).TYPE = 65;
CALL RQSEND( .RET$PULSE, .PULSE$MSG(0));
CALL RQSEND( .RET$PULSE, .PULSE$MSG( 1) ) ;
DO FOREVER;
MSG = RQWAIT(.DUMMY,5);
MSG = RQWAIT(.RET$PULSE, 0) ;
CALL RQSEND( .GO$PULSE,MSG);
END;
END TICKER$TASK;
ADC$ TASK:
PROCEDURE PUBLIC;
DECLARE TRIGGER$MSG STRUCTURE (
MSG$HDR );
DECLARE
DECLARE
DECLARE
DECLARE
(T$MSG,MSG,LOCK$MSG) ADDRESS;
I BYTE; |
GAIN LITERALLY '00';
N$ CHNLS LITERALLY '5°;
TRIGGER$MSG.LENGTH = SIZE(TRIGGER$MSG) ;
TRIGGER$MSG.TYPE = 65;
CALL RQSEND( .RET$TRIG, . TRIGGER$MSG) ;
CALL RQELVL(2);
2-29
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
9 4
95
96
97
98
99
100
101
102
104
105
106
107
108
109
110
111
112
113
114
115
+= 0 0 сю О ГО
nN NNN VD WwWWwWWwE EE
N
EE FU О WW N
=
DO FOREVER;
MSG = RQWAIT( .GO$PULSE,0);
CALL RQSEND( .RET$PULSE, MSG) ;
LOCK$MSG = RQWAIT(. T$PARAM$LOCK, 0);
DO I = 0 TO N$CHNLS-1; — |
PIRST$CHANNEL$REGISTER = BOX$PARAMS(I).CHANNEL
+ ROL(GAIN,6);
COMMAND$REGISTER = GO$BIT
OR EOC$INTERRUPT$ENABLE;
MSG = RQWAIT(.RQL2EX,0);
COMMAND$REGISTER = 0;
BOX$PARAMS(I).ACCUM = BOX$PARAMS(I).ACCUM
+ ADC$DATA$REGISTER;
END:
CALL RQSEND(. T$PARAM$LOCK, LOCK$MSG);
T$MSG = RQWAIT( .RET$TRIG,0);
CALL RQSEND( . TRIGGER, T$MSG) ;
END;
END ADC$TASK;
CONTROL$TASK:
PROCEDURE PUBLIC;
DECLARE (LOCK$MSG, T, MSG) ADDRESS;
DECLARE I BYTE; |
DECLARE NCHNLS LITERALLY "5;
DECLARE TURN$LAMP$ON
LITERALLY 'OUTPUT(OE7H)=SHL(I,1)" ;
DECLARE TURN$LAMP$OFE
LITERALLY 'QUTPUT(OE7H)= -SHL(I, 1) +1';
DECLARE SETUP$8255 LITERALLY 'OUTPUT(OE7H)=80H:
| | ООТРОТ( ОЕбН) = ОРЕН' ;
SETUP$8255 ;
DO FOREVER;
MSG = RQWAIT(.TRIGGER,O0);
CALL RQSEND( .RET$TRIG,MSG) ;
LOCK$MSG= RQWAIT( .T$PARAM$LOCK, O0) :
DO I = 0 TO NCHNLS-1;
BOX$PARAMS(I).COUNT = BOX$PARAMS(I).COUNT + 1:
IF BOX$PARAMS(I).COUNT
= BOX$PARAMS(I).SAMPLES THEN
DO; |
T, №
BOX$PARAMS(I) .READING
= (BOX$PARAMS(I).ACCUM
/BOX$PARAMS(I).SAMPLES) / 38
+ BOX$PARAMS(I).OFFSET;
IF T <= BOX$PARAMS(I).SET$POINT
- BOX$PARAMS(I).ERROR THEN
TURN$LAMP$ON;
ELSE Ш
IF T >= BOX$PARAMS(I).SET$POINT
+ BOX$PARAMS(I).ERROR THEN
2-30
116 5 TURN$ LAMP $OFF ;
BOX$PARAMS(I) .ACCUM,
BOX$PARAMS(I).COUNT = O;
118 5 END;
119 4 END;
120 3 CALL RQSEND( .T$PARAM$LOCK,LOCK$MSG);
121 3 END; |
122 2 END CONTROL$TASK;
123 1 END ATOD;
2-31
">
/
Download
Bare en venlig påmindelse. Du kan se dokumentet lige her. Men vigtigst af alt har vores AI allerede læst det. Den kan forklare komplekse ting i enkle vendinger, besvare dine spørgsmål på ethvert sprog og hjælpe dig med hurtigt at navigere selv de længste eller mest komplicerede dokumenter.
Annonce