|
|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 29952 (0x7500)
Types: TextFile
Names: »micmaninp«
└─⟦00964e8f7⟧ Bits:30007478 RC8000 Dump tape fra HCØ.
└─⟦b2ec5d50f⟧
└─⟦fd91a6c89⟧ »tm68net«
└─⟦this⟧
;ali time 4 0
(mode list.yes
micman=set 80
permanent micman.17
micman=typeset
mode list.no)
*pl 297,18,250,4,3**pn 0,0*
*lw 170**ps 0**sj*
H. C. Ørsted Institute
Computer Department
Universitetsparken 5
DK-2100 K benhavn Ø
*nl4*
*ct*
NETMON
USER's MANUAL
"micmaninp"
*nl8*
Ejvind Sørensen
*sj* *nl19**lm 120*
78.11 *lm120**nl*
Novenber 1978
*nl*
*rj**pn 5,0**ps 18*
*lm0*
*rj*
*nl6*
*ld24*
\f
*ns 1,2,0 Introduction*
--------------*nl**np*
The following is a short description of the process monitor for the
Motorola 6800 which is used for datacollection and control of experiments
for simple peripherals.
Mon4 consist of what maybe called 'internal' and 'external' processes.
The processes are syncronized by means of a centrallogic which contains
the subroutines necessasary to run the processes in a quasi_parrallel
way. Further it contain routines which make communication between processes
possible in an easy way.
*ns 1,2,1 How processes communicate*
-----------------------------*nl**np*
When two processes wants to exchange information this is done by
sending messages to each other. See example below
*sj*
PROC_1 PROC_2
wait_message(PROC_2) send_message(PROC_1)
! !
perform task wait_answer
! !
send_answer perform task
goto PROC_1 goto PROC_2
*rj*
*nl 2*
For simplicity we can assume that PROC_1 calculates the product
of two numbers given in the message sent by PROC_2. PROC_1 will be
waiting until a message arrives and it can multiply the two numbers
Let us now assume that PROC_2 has prepared
a message to PROC_1 and executed the two commands: send_message(proc_1),
wait_answer. The following happens:
*sj*
1: PROC_1 gets the message
2: PROC_1 performs the multiplication and sends an answer to PROC_2
containing the result of the multiplication.
3: PROC_2 waits for the answer from PROC_1
4: PROC_2 gets the answer from PROC_1 and continues.
5: PROC_1 waits for a new message.
*rj**nl2*
Before continuing we will have to discuss the format for a message,
an answer and which of the processes a 'user_process' can/may commu-
nicate with.\f
*ns 1,2,1.1 Format of a message*
-----------------------*nl**np*
Each message consists of 14 bytes with the following format:
*sj*
byte
+0...3 <receiver> ; 4 bytes containing the name of the receiver
+4...7 <sender > ; 4 bytes containing the name of the sender
+8 <opcode > ; operation: input/output/dummy
+9..13 <operands> ; 5 bytes containing operands
*rj*
Below is shown an example how to make a message. It has the form
which is accepted by the general assempler GENASS.
*sj*
mess: <:term:> ; receiver:='term'
<:user:> ; sender:='user'
3<4 ; op:='input'
frst>8,frst ; first address dataarea
noda>8,noda ; no_of_bytes
0 ; spare byte
*rj*
*ns 1,2,1.2 Format of an answer*
-----------------------*nl**np*
When the user_program has sent a message it may wait for an answer.
An answer consist of 14 bytes i.e. it has the same size as an mes-
sage. When received the answer contains a result of the exchange of
information. An answer looks like
*sj*
byte
+0...3 <receiver> ; the receiver of the message_sent
+4 <result > ; a result indicating success or failure:
+5 <status > ; 1: normal answer_check status
; bit0: time_out
; bit1: transmission
; 2: dummy answer __ an answer sent by the
; monitor.
; 5: receiver does not exist __ check the
; spelling of the name of the receiver
+6...8 <dummy > ; irrellevant
+9..12 <operands> ; the state of the operands after the
; message has been sent.
Below is shown how to make an answerarea. It also has the form
accepted by GENASS.
answ: 0,r.14 ; allocate 14 bytes initially filled with 0's
; e.g. write 14 zeros from the address given by
; the symbolic name 'answ' and forth
*rj**nl 2*
How to send a message and receive an answer-- will
be shown in the next section.
*ns 1,2,1.3 Queues*
----------*nl**np*
The monitor makes use of three queues. A processqueue, which is
scheduled due to monitor calls or time out. A event
queue belonging to each process and at last a queue of free buffers called
the common pool-.When a message or an answer is sent to a process
it is linked into the event queue and the receiving process is activated-
e.g. it is made ready to examine the eventqueue.
*ns 1,2,1.4 Process-states*
------------------ *nl**np*
In each process_description a byte is reserved for status.
The bits have the following meaning:
*sj*
bit0 : the process is pasive
bit1 : -------------- active
bit2 : --running
bit3 : waiting for message
bit4 : waiting for answer
bit5 : waiting for event
bit6 : busy(external processes only)
bit7 : stopped(user process only)
*rj*
Bit 7 is the most significant bit, and the status_byte
is found at process_description address+5.
*ns 1,2,1.5 Illegal instructions and reserved names*
-------------------------------------------*nl**np*
For a proper execution you must avoid to use the WAI-instruction
and all stack-oprations. During a reset_sequense the monitor initiates
the stack and expects it to be in the bottom of the user_ram.
*ns 1,2,1.5.1 Reserved names:*
----------------------*nl**np*
The following names must be avoided as they are used by the monitor:
COMM,RCRQ,INPR,RCRD,DATA and DUMM.
\f
*ns 1,2,2.0 Call of monitor procedures*
------------------------------*nl**np*
The monitor is called by a special opration: trap <no> where
no is an integer 0...19. Each <no> has a monitorprocedure connected to it.
In the following theese procedures will be explained in detail.*nl2*
When the monitor is called the userprogram-your program-is stopped
at the point of the call and a jump to the specified monitorprocedure
is done. The monitor executes the code belonging to the procedure and a
return to the userprogram is performed.
*ns 1,2,2.0.1 List of monitorprocedures*
-------------------------------*nl**np*
Below is shown a list of all the monitorprocedures,which can be
called from a user_program:*nl*
*sj*
trap 0 : send_message
trap 1 : wait_message
trap 2 : send_answer
trap 3 : wait_answer
trap 4 : wait_event
trap 5 : get_event
trap 6 : create_external_process
trap 7 : passivate
trap 8 : release
trap 9 : get_process_description
trap 10 : add_a_to_x
trap 11 : copy
trap 12 : compute_bytes
trap 13 : put_buf
trap 14 : clear_time_out
trap 15 : get_clock
trap 16 : wait_for_start
trap 17 : regret_message
trap 18 : set timer
trap 19 : post mortem dump
trap 20 : xchange X and AconB
trap 21 : set 'timer' interrupt vector
trap 22 : set 'device' interrupt vector
trap 23 : read 'timer' vector
trap 24 : read 'device' vector
*rj*
*ns 1,2,2.1 Description of the monitorprocedures*
----------------------------------------*nl**np*
TRAP 0 *nl*
*ns 1,2,Send_message(time_out,message,address_buf*
*sj*
-----------*nl**rj**np*
Sends a message to a receiver defined in the messagearea.
see section 1.1.
The message is sent using a messagebuffer fetched from the common pool. As seen
in the parameterlist the calling process is informed of the
address of this messagebuffer-the underlined parameter- . This feature
is used when the calling process wants to wait for an answer delivered
in the same buffer.*nl2*
The M6800 has two accumulators A,B and an indexregister X. These
are used to hold the parameters when a monitorprocedure is called.
*sj*
ex.
call return
A timeout.hi A destroyed
B timeout.low B destroyed
X address message area X address messagebuffer
zero if no buffer
*rj*
NOTE*nl*
Timeout is measured in units of 50ms and is used when you want to
be sure to receive an answer. The time out value be changed may using
the monitorprocedure settimer, see later.
If the answer is delivered by timeout, a result returned in the answer will
be normal-see later. If timeout is zero you never get a timeout answer
and will have to wait for a normal answer with status=0.
*sj*
ex.
How to send a message
ldai 1 ;
ldbi 20 ; timeout:=50times(256+20)ms
ldxi mess ; X:=address message area
trap 0 ; send_message
stx savx ; save address messagebuffer
.
.
mess: <:term:> ; receiver:='term'
; e.g a process called term is receiver
<:user:> ; sender:='user'
5<4 ; operation:=output
frst>8,frst ; first byte to get data
no>8,no ; no of bytes to output
0 ; spare
savx: 0,0 ; room for saving messagebufferaddress
*rj**nl2*
In the example above the user has assumed that the output can be
performed in less than 50 times 276 ms. If it is not the case the monitor
delivers a dummy answer when the specified time has gone. If you do not
want to use the timeout write clra,clrb instead of ldai 1,ldbi 20
Note that the process 'term' is a user defined process which has to be
created by a special monitorprocedure-see create external process-.
The function of the example is to output a number of bytes (no) to an external
device starting at the address frst.*nl*
Note: In order to speed up the send message you can insert the address
of the receiver by putting zeros in the two first bytes
of the message and the address in the following two bytes.
When the operation is finished an answer is sent to the sender.*nl2*
TRAP 1*nl*
*ns 1,2,Wait_message(messagearea,bufferaddress)*
*sj*
-------------*nl**rj**np*
The calling process waits for a message. When a message arrives in
the eventqueue the contents of the message is copied into an area addres-
sed by messagearea specified in the call. At return register X
points at the
messagebuffer in which the message was delivered.
Further the messagebuffer is linked out of the eventqueue and is made
ready to deliver an answer.
*sj*
call return
A none A destroyed
B none B destroyed
X messagearea X bufferaddress
ex.
ldxi msar ;
trap 1 ; wait message
stx savx ; save bufferaddress
.
.
msar: 0,r.14 ; message area
savx: 0,0 ; save X
*rj*
TRAP 2 *nl*
Send_answer(answeraddress,addressmessbuf,result)*nl*
*sj*
------*nl2*
*rj*
This procedure copies an answer
into the messagebuffer, which has been received by a wait
message call. The messagebuffer is then sent back to the original sender.
Is the sender waiting for this answer, it is activated e.g. the passive bit
in the process statusword is cleared. Otherwise it stays in the passive
state and the answer is linked into the eventqueue. The return parameter
result indicates whether the answer sent was a normal or a dummy answer.
*sj*
call return
A answerarea.hi A result. 1 normal 5 dummy
B answerarea.lo B destroyed
X address_mess_buf X destroyed
ex. Add two 16 bit integers received in a message and return
the answer
ldxi msar ;
trap 1 ; wait_message
stx savx ; save address messagebuf
ldxi msar ; examine message:
ldax 8 ; get operation
cpai 43 ; if op='+' then
bne l1 ;
ldax 12 ;
adax 10 ; get op no 4
bcc l2 ; add op 2 and 4
incx 9 ; if carry then
l2: stax 10 ; op1:=op1+1
ldax 11 ; add op1 and op3
adax 9 ;
stax 9 ;
ldx savx ; insert parameters
ldai msar>8 ;
ldbi msar<8>8 ;
trap 2 ; send_answer
l1: ... ; if op <>'+' then
msar: 0,r.14 ; message area
savx: 0,0 ; save X
*rj*
TRAP 3 *nl*
*ns 1,2,Wait_answer(answeraddress,messagebuf,messagebuf,result)*
*sj*
_________________*nl**rj**np*
The calling process waits for an answer specified by messagebuf.
When the answer arrives in the event_queue, the content of the answer
is copied into the area defined by answerarea. At return the 4_byte
field used to hold sender is replaced with a result and a status fol-
lowed by two zeroes
*sj*
The result has the following meaning:
1: normal answer..check status
2: dummy answer
5: dummy answer, receiver does not exist
If the answer comes from a external process used to transmit a block o
of data you get useful information about the transfer.
Let us look on a dummy answer
BEFORE AFTER
mess: <:term:> answ: <:term:> ; receiver
<:user:> 2,0,0,0 ; result of operation
; and status
5<4 x ; last byte sent
frst>8,frst y>8,y ; location next byte
no>8,no z>8,z ; remaining bytes
; to send
0 0 ; spare
From the example above you can see:
1: who was the receiver
2: result of the operation
3: the last byte sent/received
4: address of the next byte to send
5: how many bytes are remaining
If the dummy answer is generated by time_out you may have to
increase the time_out values. Is it an answer due to transmission-
errors it is probably a due to the matrial_error.
call return
A answerarea.hi A destroyed.
B answerarea.lo B destroyed.
X messageaddress X messageaddress
ex1.
ldx savx ; get message address
ldai answ>8 ;
ldbi answ<8>8 ; get answer_area
trap 3 ; wait_answer
ex2.
The order of wait_answer calls is unimportant
clra,clrb ; time_out:=0,0
ldxi mes1 ;
trap 0 ; send_message(mes1)
stx svx1 ; save x
clra,clrb ; time_out:=0,0
ldxi mes2 ;
trap 0 ; send_message(mes2)
stx svx2 ; save X
ldx svx1 ;
ldai answ>8 ;
ldbi answ<8>8 ; wait_answer(mes1)
trap 3 ;
clra,clrb ; time_out:=0,0
ldxi mes3 ;
trap 0 ; send_messge(mes3)
ldai answ>8 ;
ldbi answ<8>8 ;
trap 3 ; wait_answer(mes3)
ldx svx2 ;
ldai answ>8 ;
ldbi answ<8>8 ;
trap 3 ; wait_answer(mes2)
.
.
mes1: ....
mes2: ....
mes3: ....
answ: 0,r.14
svx1: 0,0
svx2: 0,0
svx3: 0,0
*rj**nl2*
TRAP 4*nl*
*ns 1,2,Wait_event(last_buf_addr,result,next_buf_addr)*
*sj*
____________________ *nl**rj**np*
Examines the eventqueue of the calling process. The process
is delayed until a message or an answer arrives in the queue after
the buffer given by last buffer_address. At return the process is supplied
with the address of the next buffer and a result indicating whether it
is a message or an answer. The buffer is not removed from the queue.
If buffer_address=0 then the queue is examinaed from the start.
Suppose you have an experiment where two different parameters are measured
and you do not know the sequense in advance, then it is very usefull
to use wait_event.
*sj*
call return
A none A result 0 mess/1 answer
B none B destroyed
X last_buf_addr/0 X next_buf_addr
ex.
clra,clrb ;
ldxi mes1 ;
trap 0 ;
stx svx1 ; send_message(mes1)
clra,clrb ;
ldxi mes2 ;
trap 0 ; send_message(mes2)
stx svx2 ; save X
l3: ldxi 0 ; X:=0
trap 4 ; wait_event (examine from start)
tsta ;
beq exms ; ANSWER(A<>0)
cpx svx1 ; if event=answ(mes1) then
beq l1 ; .....
cpx svx2 ; if event=answer(mes2) then
beq l2 ; ....
trap 5 ; else get_event (see later)
bra l3 ; examine next event
l1: ldai answ>8 ;
ldbi answ<8>8 ;
trap 3 ; wait_answer
l2: ...
*ps*
\f
Below the idea of wait event is shown schematically
!------------------>wait_event<--------------------!
! = !
! = = !
! = = !
! !--------------! !-----------------! !
! ! message ! ! answer ! !
! !--------------! !-----------------! !
! ! ! !
! ! ! !
! perform task "find sender" !
! ! ! !
! ! ! !
! !--------------! !-----------------! !
! ! send answer ! ! get answer ! !
! !--------------! !-----------------! !
! ! ! !
! ! ! !
!-----------! !------------!
*rj**nl2*
TRAP 5*nl*
*ns 1,2,Get_event(buf_address,buf_address)*
___________*nl**np*
Removes a given buffer from the event_queue. Is the event an answer
the buffer is returned to the common pool. Is it a message the buffer-
address is returned to the calling process and made ready to transmit an
answer.
*sj*
call retrun
A none A destroyed
B none B unchanged
X buf_address X buf_address/0 if answer
ex.
l2: ldxi 0 ;
trap 4 ; wait_event
tsta ;
beq l1 ; if answer then
trap 5 ; get_event eg. return to pool
bra l2 ; examine next
l1: ... ; prepare answer
ldai answ>8 ;
ldbi answ<8>8 ;
trap 2 ; send_answer
*rj**nl2*
TRAP 6*nl*
Create_external_process(description)*nl2*
This procedure connects peripherals to the program in the micro
By means of a description vector the procedure
creates a processdescription which has the
following format:
*sj*
BYTE
+0 <kind>
+1 <name>
+5 <state>
+6 <link next>
+8 <link last>
+10<interrupt vector>
+12<address port>
+14<address code>
+16<mask>
*rj**nl2*
The user can choose between the kinds: 2,3 or 4.*nl*
Kind 2 means that you wants to use a peripheral interface adapter
-PIA- as input.This device receives/transmits a whole byte in parrallel.
Kind 3 is used as kind 2, but as an outputdevice.*nl*
Kind 4 gives you access to an asynchronous communications interface
adapter -ACIA- . This device receives/transmits only a bit at a time eg.
a parrallel byte is transformed to serial form when transmitting
and serial to parrallel when receiving.
*sj*
The format for the vector is:
+0: <kind>
+1: <name>
+5: <logical device number>
*rj*
*sj*
ex.
term: 4 ; kind:=4 (use ACIA)
<:term:> ; name:='term'
0,0 ; logical device no 0
ldxi Term;
Trap 6; create_ex_proc.
Let us look at a simple example:
A user wants to read a character from a terminal and output it on
a seven_segment_display.
term micro disp
!-------------!
! !
! !
! !
!----! ! ! !----!
/ ! ! ! ! !
! ! ! ! 8 ! !
! !------------->!ACIA PIA!------/-->! !
! ! ! ! ! !
!-----! !-------------! !----!
It is wise to study the following ex. in detail as it uses several of
the previously described monitorcall.
ex.
ldxi term ;
trap 6 ; create_external_process(term)
ldxi disp ;
trap 6 ; create_external_process(disp)
next: clra,clrb ;
ldxi mes1 ;
trap 0 ; send_message(0,0,mes1)
ldai answ>8 ;
ldbi answ ;
trap 3 ; wait answer
... ; make appropriate transformation and store result
... ; in location frst
clra,clrb ;
ldxi mes2 ;
trap 0 ; send_message(0,0,mes2)
ldai answ>8 ;
ldbi answ<8>8 ;
trap 3 ; wait answer
bra next ;
mes1: <:term:>
<:user:>
3<4 ; input
frst>8,frst ;
0,1,0 ; first_addr_to_put_data
mes2: <:disp:> ;
<:user:> ;
5<4 ; output
frst>8,frst ; first addr to get data
0,1,0 ;
answ: 0,r.14 ; answer area
frst: 0 ; data area
term: 4 ; kind:=4 ACIA
<:term:> ;
0,0 ;
disp: 3 ; kind:=3 PIA
<:disp:> ;
0,0 ;
TRAP 7
Passivate
===System_call..Do not use
TRAP 8
Release
Release the userprocess eg. allow other processes to get
cpu time . Is usefull when you preform long computations.
TRAP 9
Get_process_description(pointer_to_name)
On the basis of the process name the call returns the address of
the process' processdescription. See format in the trap 6 section.
call return
A none A des
B none B des
X name_address X process_desc_address
ex.
ldxi mes1 ; x:=pointer
trap 9 ;
mes1: <:term:>
<:user:>
.
.
this can be used when you want to inspect a given process
and maybe change something in the processdescription. If you want to se
if a process is busy do the following:
ex.
ldxi name ;
trap 9 ; get_address(name)
ldax 5 ; A:=state
btai 2.1<6 ; A:=A or 2.1<6 (test bit 6)
beq l1 ;
... ; BUSY
.
l1: . ; not busy
name: <:term:> ;
You can also get direct access to the devices
assigned the external process.
ex.
ldxi name ;
trap 9 ;
ldxx 12 ; get address device
... ; X:=address device
You can change the mask by:
ex.
ldxi name ;
trap 9 ;
ldai 2.1 ; A:=new mask
stax 16 ; pda+16:=A
TRAP 10
Add_A_to_X
Adds A and X regs and returns result in X
call return
A operand1 A des
B none B unchanged
X operand2 X operand1+operand1
ex.
ldai 10 ; operand1:=10
ldxi 20 ; operand2:=20
trap 10 ; X:=10+20
TRAP 11
Copy(vector_address)
Copies x bytes from a sourcearea to a destinationarea defined
in a vector.
call return
A none A unchanged
B none B unchanged
X vector_address X destroyed
ex.
ldxi desc ; X:=description
trap 11 ; copy
...
desc: srce>8,srce ; source
dest>8,dest ; destination
12 ; no_of_bytes_to_move
srce: <:text to move:>
dest: 0,r.12 ; room for moved text
TRAP 12
Compute_bytes(first,last,result)
Computes the number of bytes defined by first and last both
inclusive.
call return
A first.hi A des.
B first.lo B des.
X last X result:number 0 if out of range
ex.
ldai frst>8 ; AconB:=first
ldbi frst<8>8 ;
ldxi last ; X:=last
trap 12 ; X:=X-first+1
frst: ...
.
last: ; area to compute length of
TRAP 13
Put_buf(address_buf,address_buf)
___________
===System call do not use
Puts a buffer back to the common pool. For special use only
call return
A none A des.
B none B des.
X address_buf X address_buf
*rj*
TRAP 14*nl2*
clear_time_out*nl2*
In order to prevent thr userprocess to consume all CPU_time in an
endless loop, the monitor is supplied with a timer, which allows a process o
to run max 0,5 sec at a time. If you make a little program, which runs
in an endless loop you can see the userlamp on the frontpanel of the
micro extinguish every half second, letting the monitor be enabled. If
you then use trap 14 the monitor will be disabled letting the program
run forever. The effect af trap 14 is illiminated by a call of a
waitingpoint- wait_message, wait_event, passivate ...
*sj*
call return
A none A unchanged
B - B -
X - X -
ex1.
l1: nop ; no_op
bra l1 ; loop forever
ex2.
trap 14 ; clear_time_out
l1 nop ;
bra l1 ; loop forever!!!!!
TRAP 15
Get_clock(address)
_______
Gets the relative time in secs since the userprocess started.
call return
A none A unchanged
B - B -
X - X address_time_area
ex.
trap 15 ; get clock
... ; X:=time_area
; with the following meaning
; +0 most significant byte
; +1
; +2 least ssignificant byte
ex. get lsb
trap 15 ; get address
ldax 2 ; A:=lsb (addr+2)
TRAP 16
Wait_for_start
The process stops and waits for start from the host_computer.
Especially usefull when debugging new programs as they can be run
step_wise.
No call param. and no returnparam
TRAP 17
Regret_message(address_buf,result)
______
Used to regret a message to an external process. Adummy answer
is send to the calling process.
call return
A none A des.
B - B -
X address_buf X 0 if no receiver or buffer
else address sender
ex.
ldx savx ; get saved address_buf
trap 17 ; regret_message
ldx savx ;
ldai answ>8 ;
ldbi answ<8>8 ;
trap 3 ; wait_answer
TRAP 18
set_timer(no_to_count)
Changes the system time. The number to count should be
placed in reg A concatenated with reg B e.g. A = 195
and B = 80 gives 256=195+80= 50000 counts, and an
interrupt will be generated every 50000=1usec=50 msec.
A changing of the time has effect on the timeout values
for messages and for the timeslice given the userprocess.
call
A time Hi A unchanged
B time Lo B unchanged
X none X destroyed
TRAP 19
Post mortem dump (address)
Dumps the monitor store in a user defined area, starting
in address and 3 K .
call
A none A unchanghed
B none B unchanged
X address X destroyed
*rj*
*ef*
▶EOF◀