UMBC | CMSC 391 -- Programming Microcontrollers |
Interrupt | Vector |
---|---|
Reset | 0000h |
IE0 | 0003h |
TF0 | 000Bh |
IE1 | 0013h |
TF1 | 001Bh |
SERIAL | 0023h |
;---------------------------------------------------------; ; ; ; 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 retNOTE: 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.