Technical Reference

Appendix I

I.1   INTERRUPT DRIVEN SERIAL INPUT/OUTPUT

This appendix is designed to show the methodology involved in driving the Sirius 1 in interrupt mode when communicating via the serial port(s). Some pitfalls are described, and tested sample routines are included. There are, currently, no system level facilities that enable this task to be accomplished easily, and some chips, namely the PIC 8259, PIT 8253, SIO 7201 and the VIA 6522 will require re-programming. It is up to the programmer to reset the machine to the original state prior to exiting the interrupt driven application.

A typical interrupt driven application will normally follow the steps outlined below:

  1. Save the original vector, set the new vector.
  2. Set the direction bits.
  3. Enable clocks (internal or external).
  4. Reset SIO 7201 device, define your communication characteristics.
  5. Set the baud rate.
  6. Set the PIC 8259 to enable SIO interrupts.

These steps will be discussed in more detail throughout the text.


I.2 Interrupt Vectors

There are 256 software interrupts available to the Sirius 1. Most are reserved for system functions, and diagnostics. A block of vectors from 80H through BFH are set aside for applications.


I.2.1 Vectors available on the Sirius 1
     00-1Fhex  Intel reserved
     20-3Fhex  Microsoft reserved
     40-7Fhex  Victor reserved
     80-BFhex  Applications reserved
     C0-FFhex  Victor reserved

Vectors 40H through 47H are those belonging to devices controlled by the Programmable Interrupt Controller (PIC).

     40hex     Sync IRQ
     41hex     SIO 7201
     42hex     Timer 8253
     43hex     General Interrupt Handler (all 6522 IRQ's)
     44hex     IRQ4
     45hex     IRQ5
     46hex     Keyboard - keystroke
     47hex     8087 math processor
I.2.2 Location of Vectors

Vectors consist of a long pointer (double word) to an interrupt service routine. This pointer is a 4 byte entry consisting of the Segment and Offset of the Interrupt Service Routine. The vectors are stored in a table that has its origin at 0000:0000. The first entry in this table is, therefore, Interrupt 0; the vector for Interrupt 1 is the second, with its vector having an origin of 0000:0004. the interrupt vector for Interrupt 41hex (the SIO 7201) will be found at location 0000:0104 (4*41hex).

To set a vector into this table, the MS-DOS function 25hex can be used, but since it is desirable to restore the old vector prior to the application program exiting, it is less cumbersome to simply set the new vector "by hand", and restore the old vector when the application terminates.

I.2.3 Set Vector - Assembler Example
;store old vector, and set new vector for SIO

     cli                                ;clear interrupts
     xor  ax,ax                         ;AX=0000
     mov  ES,ax                         ;access table via ES
     mov  ax,word ptr ES:[104h]         ;get old offset       
     mov  word ptr old_offset,ax        ;save old offset in DS
     mov  ax,word ptr ES:[106h]         ;old segment
     mov  word ptr old_segment,ax       ;save old segment
     mov  ax,my_sio_isr                 ;get offset to my code
     mov  word ptr ES:[104h],ax         ;set vector offset
     mov  word ptr ES:[106h],CS         ; and the new segment
     sti                                ;enable interrupts
     ret                                ;all done, exit

;to replace the old vector prior to exit

     cli                                ;clear interrupts
     xor  ax,ax                         ;AX=0000
     mov  ES,ax                         ;access table via ES
     mov  ax,word ptr old_offset        ;get old offset
     mov  word ptr ES:[104h],ax         ;restore old offset
     mov  ax,word ptr old_segment       ;get old segment
     mov  word ptr ES:[106h],ax         ;restore old segment
     sti                                ;enable interrupts
     ret                                ;all done, exit
I.3 Enabling Internal and External Clocks

In an asynchronous environment the transmit clock is generated internally, as opposed to a synchronous environment where the transmit clock is typically provided by an external source.

Internal clocking is selected by masking off the appropriate bit in register 1 of the keyboard Versatile Interface Adaptor (VIA).

The keyboard VIA, register 1, is located at E804:0001. The appropriate bits are:

     Bit 0 (PA0) for Port A
     Bit 1 (PA1) for Port B

Thus, by setting PA0 to zero, the internal clock is enabled for port A; setting PA1 to zero will enable the internal clock for port B. Setting PA0 or PA1 to one will enable the external clock disabling the internal clock. CAUTION: Care must be taken to leave the other bits in the pre-selected state.

To enable internal clocks for ports A and B then mask off the two least significant bits in register 1:

     mov  ax,0e804h                ;keyboard VIA segment
     mov  ES,ax                    ;select the segment register
     and  byte ptr ES:[0001],0fch  ;A & B internal clocks done

To enable external clocks on either channel then set the relevant bit by OR'ing the bit in. The following sample sets the external clocks for both ports A and B:

     mov  ax,0e804h                ;keyboard VIA segment
     mov  ES,ax                    ;select the segment register
     or   byte ptr ES:[0001],03h   ;A & B external clocks done
I.3.1 Providing Clocks

In a synchronous environment it sometimes becomes necessary to provide transmit and receive clocks from the Sirius 1. This requires that the cable used has to have pins 15, 17 and 24 jumpered at the Sirius 1 end. The Sirus 1 always has a clock on pin 24, this being provided by the internal baud rate generator; thus by jumpering pin 24 to both pins 15 and 17, this clock becomes available for both the transmitter and the receiver, at both ends of the cable.

When providing clocks from the Sirius 1, the external clock must be set as well as a baud rate selected. In synchronous mode, the "divide by rate" of the PIT 8253 is 1, therefore the values used to set the required baud rate is 1/16 the values used in an asynchronous environment. (see section 3.8.2 for values).

I.4 Initialising the SIO

There is little magic used in this step, but it is recommended that the programmer read the entire Intel/NEC 7201 chip data sheet. The SIO segment is found in segment location E004hex. The offsets for the data ports A and B and control ports A and B are at 0, 1, 2, 3 respectively.

The following example of initialising the SIO 7201 is for Port A:

     cli                           ;disable interrupts
     mov  ax,0e004h                ;the SIO segment
     mov  ES,ax                    ; using ES
     mov  byte ptr ES:[0002h],18h  ;channel reset

;now delay at least 4 system clock cycles

     nop  
     nop                           ;delay for 7201

     mov  byte ptr ES:[0002h],12h  ;reset external/status
                                   ; interrupts

;and select register 2

     mov  byte ptr ES:[0002h],14h  ;non-vectored
     mov  byte ptr ES:[0003h],02h  ;select CR2 B
     mov  byte ptr ES:[0003h],00h  ;set vector to 0

;set for clock rate of 16*; 1 stop bit; parity disabled

     move byte ptr ES:[0002h],04h  ;select CR4 A
     move byte ptr ES:[0002h],44h  ;

;this register defines the operation of the receiver:
;7 data bits; auto enable and receive enable

     mov  byte ptr ES:[0002h],03h  ;select CR3 A
     mov  byte ptr ES:[0002h],61h  ;

;CR5 controls the operation of the transmitter
;7 data bits, dtr; assumes half-duplex

     mov  byte ptr ES:[0002h],05h  ;select CR5 A
     mov  byte ptr ES:[0002h],0a0h ;

;set status: affects the vector, interrupt on every character,
;enable transmitter interrupt

     mov  byte ptr ES:[0002h],01h  ;select CR1 A
     mov  byte ptr ES:[0002h],17h  ;

     sti                           ;enable interrupts
I.4.1 Baud Rate for SIO

At this point, baud rate must be selected. In an asynchronous environment the PIT 8253 divides the supplied baud rate by 16; but in a synchronous environment the baud rate is divided by 1. Thus, to set the baud rate in an asynchronous environment, the value written to the PIT 8253 is 16 times the desired baud rate value. The common baud rate values, and the method of establishing the baud rates, are shown in section 3.8.2 of this manual.

I.4.2 Set the PIC to Enable SIO Interrupts

In the Sirius 1 the PIC is normally initialised to operate the SIO in a polled environment. The following lines of code sets the PIC to operate the SIO in an interrupt environment:

The PIC resides at segment E000hex and the register required here is at offset 0001:

     cli                           ;disable interrupts
     mov  ax,0e000h                ;get the PIC segment
     mov  ES,ax                    ;
     and  byte ptr ES:[0001h],(not 02h) ;mask off bit 1
     .
     .
     sti                           ;allow interrupts

Prior to exiting the interrupt driven application, the PIC should be returned to operating the SIO in polled mode. This is done by setting bit 1:

     cli                           ;disable interrupts
     mov  ax,0e000h                ;get the PIC segment
     mov  ES,ax                    ;
     or   byte ptr ES:[0001h],02h  ;set polled
     sti                           ;allow interrupts
I.5 Interrupt Service Routine - ISR

When an interrupt occurs in non-vectored mode, SIO register CR2 B contains the vector number of the interrupting device. Assuming the SIO was initialised as earlier described in this appendix, CR2 B contains a value in the range 0-7, which serves as the index to the following interrupt vector table

I.5.1 Sample Interrupt Service Routine
data segment   public    'data'
int_vectors    dw   tx_int_b            ;tx int for port B
               dw   ext_status_b        ;external status changed
               dw   recv_int_b          ;recv int port B
               dw   recv_err_b          ;recv error port B
               dw   tx_int_a            ;tx in for port A
               dw   ext_status_a        ;external status changed
               dw   recv_int_a          ;recv in port A
               dw   recv_err_a          ;recv error port A
data ends

code segment   public    'code'
     assume    CS:cgroup, DS:dgroup

sio_isr:
     mov  word ptr CS:current ss,SS     ;save stack seg
     mov  word ptr CS:current_sp,SP     ; and stack pointer
     mov  SS,word ptr CS:ss_origin      ;internal stack
     mov  SP,offset dgroup:stack top    ;defined in DS (dgroup)

     push ax                            ;save environment
     push bx
     push cx   
     push dx
     push bp
     push DS
     push ES

     mov  DS,dgroup                     ;set to internal data
     mov  ax,0e004h                     ;set SIO segment
     mov  ES,ax                         ;
     mov  byte ptr ES:[003h],02h        ;select CR2 B
     mov  al,ES:[0003h]                 ;read int device
     add  al,al                         ;word align
     mov  ah,0                          ; hi = 0
     mov  bx,offset int_vectors         ;get vector table
     add  bx,ax                         ;point to entry
     call [bx]                          ;service routine
     cli                                ;keep disabled

;now an "end of interrupt" (EOI) must be issued to the 
;SIO (port A) and to the PIC.

     mov  ax,0e000h                     ;PIC segment
     mov  DS,ax                         ;
     mov  byte ptr [0042h],38h          ;EOI to ctrl A of SIO
     mov  byte ptr [0000h],61h          ;EOI to PIC ctrl port A

     pop  ES                            ;restore environment
     pop  DS
     pop  bp
     pop  dx
     pop  cx
     pop  bx
     pop  ax

     mov  SS,word ptr CS:current_ss     ;get SS
     mov  SP,word ptr CS:current_sp     ;get SP
     iret                               ;interrupt return

;the SS origin is stored here during initialisation
ss_origin      dw   0                   ;stack segment origin
current_sp     dw   0                   ;SP on ISR entry
current_ss     dw   0                   ;SS on ISR entry

NOTE: Some variables are stored within the code segment, as the CS register is the only register containing a known value at the time of interrupt.

I.6 Setting Direction Bits

This function need only be performed once, and is performed by the operating system BIOS following a hardware reset. This step need not be implemented, therefore, if a standard Sirius operating system is used. If a standard operating system is not used, then this step needs to be performed immediately prior to the enable clock code.

;The offset to the data direction register is 0003hex.

     cli                                ;disable interrupts
     mov  ax,0e804h                     ;kbd VIA segment
     mov  ES,ax                         ;
     mov  al,byte ptr ES:[0003h]        ;get the old value
     or   al,03h                        ;set for output
;
;set the PA2-5 to zero, to enable DSR and RI input
;
     and  al,0c3h                       ;mask in
     mov  byte ptr ES:[0003h],al        ;rewrite new value
     .
     .
     sti                                ;enable interrupts    


BACK


All contents of this website (including text, images, design, and presentation) are Copyright � 1999-2004,
ACT Sirius 1 User Group (UK) unless explicity stated otherwise. All Rights Reserved.
E-Mail: siriususer@eurobell.co.uk

Last revision 22/01/2003