UMBC CMSC 391 -- Programming Microcontrollers  


Interrupts

Technically speaking, the Reset is not an interrupt, but it does have a vector and sort of fits here.
Interrupt Vector
Reset 0000h
IE0 0003h
TF0 000Bh
IE1 0013h
TF1 001Bh
SERIAL 0023h
Let's look at the PAULMON source to see what is at those addresses:
;---------------------------------------------------------;
;							  ;
;		     Interrupt Vectors			  ;
;  (and little bits of code crammed in the empty spaces)  ;
;							  ;
;---------------------------------------------------------;

	.org	base
	ljmp	poweron		;reset vector

	.org	base+3
	ljmp	vector+3	;ext int0 vector

r6r7todptr:
	mov	dpl, r6
	mov	dph, r7
	ret

	.org	base+11
	ljmp	vector+11	;timer0 vector

dptrtor6r7:
	mov	r6, dpl
	mov	r7, dph
	ret

	.org	base+19
	ljmp	vector+19	;ext int1 vector

dash:	mov	a, #'-'		;seems kinda trivial, but each time
	ajmp	cout		;this appears in code, it takes 4
	nop			;bytes, but an acall takes only 2

	.org	base+27
	ljmp	vector+27	;timer1 vector

cout_sp:acall	cout
	ajmp	space
	nop

	.org	base+35
	ljmp	vector+35	;uart vector

dash_sp:acall	dash
	ajmp	space
	nop

	.org	base+43
	ljmp	vector+43	;timer2 vector (8052)

OK, what is base and vector?

; These two parameters control where PAULMON2 will be assembled,
; and where it will attempt to LJMP at the interrupt vector locations.

.equ	base, 0x0000		;location for PAULMON2
.equ	vector, 0x2000		;location to LJMP interrupt vectors

That means if we wish to take advantage of those interrupts, we have to put some code there.

.equ	pgm, 0x2000		;default location for the user program

As you can see, no work is done at those interrupt addresses. When you design your own monitor, you will be faced with a couple of important decisions. Can I do the interrupt handling within eight bytes? Do I want to?

The "can" part of the decision is easy, will the necessary code fit in eight bytes, yes or no? The "want" is more difficult to answer. Is there something that I want to do that will happen more often and I want to process it faster than handling the interrupt. You figure out which will save you the greatest number of cycles or bytes of memory, assuming that a few extra cycles will not adversely affect the interrupt handler. For instance, setting up the data pointer and saving it might be done so often from within the address range of 0000h to 2000h, that the bytes will add up, since ACALL is two bytes and LCALL is three bytes. In this case, both require two cycles.

    1 0000                      org     0000h
    2 0000 022000               ljmp    start
    3 0003              begin:
    4 0003 8E82                 mov     dpl, r6
    5 0005 8F83                 mov     dph, r7
    6 0007 22                   ret
    7 0008              begin1:
    8 0008 1103                 acall    begin
    9 000A 22                   ret
   10 000B              
   11 2000                      org     2000h
   12 2000              start:
   13 2000 1106                 acall    start2
   14 2002 120003               lcall    begin
   15 2005 22                   ret
   16 2006              start2:
   17 2006 8E82                 mov     dpl, r6
   18 2008 8F83                 mov     dph, r7
   19 200A 22                   ret

NOTE: Remember that the savings only occurs when the call is within the same page of memory! Look at the two calls for BEGIN.

To amplify the importance of this, There is a comment in PAULMON2 that says:

;---------------------------------------------------------;
;							  ;
;     More subroutines, but less frequent used, so	  ;
;     they're down here in the second 2k page.		  ;
;							  ;
;---------------------------------------------------------;
Looking at PAULMON2, we see that the code sends things to the address of "vector + " offset, where the offset in vector is the same as base. (That means each handler still has the eight byte restriction.) This must be accounted for in our code:
0000:                   .org    0x0000
0000: 02 20 00          ljmp    begin
                   
2000:                   .org    0x2000
                   
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   ;; Equates                                  ;;
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   
                   
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   ;; Code                                      ;;
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   
                   begin:
2000: 02 20 2C              ljmp    work   ;  We will not do the work here.
                   
                   ;
                   ;        We got here because an interrupt, we must
                   ;       leave as an interrupt handler (RETI).
                   ;
                   
2003:                       .org    begin + 3
                   ; INT0 goes here but must either fit in 8 bytes
                   ; or jump somewhere else.
                   
2003: 32           inter0:  reti
                   
200B:                       .org    begin + 11
                   ; TIMER0 goes here but must either fit in 8 bytes
                   ; or jump somewhere else.
                   
200B: 32           timer0:  reti
                   
2013:                       .org    begin + 19
                   ; INT1 goes here but must either fit in 8 bytes
                   ; or jump somewhere else.
                   
2013: 32           inter1:  reti
                   
201B:                       .org    begin + 27
                   ; TIMER1 goes here but must either fit in 8 bytes
                   ; or jump somewhere else.
                   
201B: 32           TIMER1:  reti
                   
2023:                       .org    begin +35
                   ; UART goes here but must either fit in 8 bytes
                   ; or jump somewhere else.
                   ;
2023: 32           uart:    reti
                   
202B:                       .org    begin + 43
                   ; TIMER2 goes here but must either fit in 8 bytes
                   ; or jump somewhere else.
                   
202B: 32           TIMER2:  reti
                   
                   work:    
                   ;
                   ; Now, to solve the real problem here!
                   ;
202C: 22                   ret
                   
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   ;; Data                                      ;;
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Actually, in this example, I could have used VECTOR as the label instead of BEGIN. VECTOR was the name in PAULMON2, but it is not available here, so there is no conflict.

PAULMON2 source

PAULMON2 equates

Stay tuned

We will look at TIMER0, TIMER1 and SERIAL at a later time.


©2004, Gary L. Burt