jgroth wrote:
Code:
1383 .8849 COLDSTART
1384 .8849 d8 CLD ;Disable decimal mode
1385 .884a a2 ff LDX #$FF ;Initialize STACK POINTER
1386 .884c 9a TXS
1388 .884d a5 ab LDA #<DOINTERRUPT
1389 .884f 8d 02 03 STA INTERRUPTVECTOR
1390 .8852 a5 89 LDA #>DOINTERRUPT
1391 .8854 8d 03 03 STA INTERRUPTVECTOR+1
....
I suggest you insert
SEI as the first instruction in the above and then follow
STA INTERRUPTVECTOR+1 with
CLI. Once interrupt processing is in effect, re-executing the above code could result in an IRQ occurring between an
LDA and an
STA. If subsequent code pointed
INTERRUPTVECTOR to a new location, the temporary inconsistency of the vector as it is being initialized will likely cause a crash.
Quote:
Code:
1601 .89a8 INTERRUPT
1602 .89a8 6c 02 03 JMP (INTERRUPTVECTOR)
1604 .89ab DOINTERRUPT
1605 .89ab 85 ed STA AINTSAV ;Save ACCUMULATOR
1606 .89ad 86 ee STX XINTSAV ;Save X-REGISTER
1607 .89af 84 ef STY YINTSAV ;Save Y-REGISTER
1608 .89b1 ad e1 7f LDA SIOSTAT ;Read 6551 ACIA status register
1609 .89b4 29 88 AND #$88 ;Isolate bits. bit 7: Interrupt has occured and bit 3: receive data register full
1610 .89b6 49 88 EOR #$88 ;Invert state of both bits
.....
Using RAM as temporary register storage within an ISR as you are doing is not particularly good practice, as it precludes the possibility of processing nested IRQs. I recommend you push them to the stack and then pull them (in reverse order) at the termination of your ISR. Also, don't save registers that your ISR will not use, as all you'll be doing is wasting clock cycles.
Your code will be slightly faster and more efficient with the following change:
Code:
INTERRUPT JMP (INTERRUPTVECTOR)
DOINTERRUPT PHA ;save MPU state
PHX ;save if necessary
PHY ;save if necessary
LDA SIOSTAT ;Read 6551 ACIA status register
BPL NOT_ACIA ;skip ahead if ACIA is not interrupting
;
;...no reason to execute the following instructions if the ACIA wasn't the IRQ source...
;
AND #$88 ;Isolate bits. bit 7: Interrupt has occured and bit 3: receive data register full
EOR #$88 ;Invert state of both bits
...
Something else: values such as the two masks used in the final two instructions should not be hard-coded into your source. They should be symbolically defined and since they are masks, should be expressed in bit-wise notation so it is clear which bits are being manipulated. Although I and some others here can mentally translated hex values to binary equivalents (and in reverse), others may not. A year or two or three from now when you revisit the code you yourself may be pondering what you meant with the above code.
Documentation means not only commenting the intended effect of each instruction, it also means defining "magic numbers" referred to within your code. This is where INCLUDE files are put to use. A professional would put something like the following into an INCLUDE file somewhere and refer to it during assembly:
Code:
ACIAMASK = %10001000 ;mask used to analyze ACIA status
and later on:
Code:
AND #ACIAMASK
EOR #ACIAMASK
Of course, there is a more efficient way to analyze the 6551's status—you don't need to know about bit 7 once you fall through the
BPL NOT_ACIA instruction. However, that's for you to work out.
BTW, have you studied Garth Wilson's interrupt primer?