Interrupts

An interrupt is break in execution that occurs when either the system state needs to be update or recovered or a hardware device needs to be controlled. Some interrupts, when triggered, invoke a subroutine-called an ISR (Interrupt Service Routine) or interrupt handler-so that code can be run to notify the program that an interrupt has taken place. This interrupt handler must be careful to preserve both all register contents and flags. There is a special instruction that will pop the flags as well as the program counter from the stack when executed: the instruction RTE should be used in place of RTS at the end of an ISR.

Auto Interrupts

The first kind of interrupt is one triggered by a clock to run at certain frequency or by a hardware device. Software has no control over when this interrupt will occur. Grayscale, for instance, is based on an auto interrupt that occurs roughly at 350 Hz. There are seven of these auto interrupts, named auto interrupts 1-7. When a certain auto interrupt is triggered, the address of the ISR is taken from one of the following memory addresses, respectively:

auto interrupt 1 - $64

auto interrupt 2 - $68

auto interrupt 3 - $6c

auto interrupt 4 - $70

auto interrupt 5 - $74

auto interrupt 6 - $78

auto interrupt 7 - $7c

When an assembly program is run, the TI-OS interrupt handlers are enabled; to change any one of these, load a new pointer into the correct address as listed above. However, since the memory from $000 to $128 is protected, you must first reset bit 2 of port $600001, and afterwards, it would be wise to set the bit again.

Here are the functions of each of these auto interrupts:

Auto interrupt 1:TI-OS uses this interrupt to handle getkey, the status bar, and the busy indicator among other things. This interrupt occurs at approximately 350 Hz and is ideal for implementation of grayscale.
Auto interrupt 2:TI-OS uses this interrupt for keypresses such as 2nd, shift, diamond and alpha. It is occurs at a frequency of approximately 600 Hz when keys other than ON are held down.
Auto interrupt 3:Unused by the TI-89.
Auto interrupt 4:This interrupt is triggered by the detection of data being received by the link port.
Auto interrupt 5:This is triggered when the programmable rate generator overflows. The programmable rate generator decrements the value in port $600016 at a frequency of 5600 Hz; when the timer value reaches the value of the last byte written to this port, auto interrupt 5 is triggered and the timer value wraps around to $00. Thus, the frequency of this interrupt can be programmed. You should note that to have the interrupt occur after 15 decrements, a value of -15 should be written to ($600016). TI-OS uses this interrupt for APD and writes an initial value of -78 to this port, so after you finish using it, you must write -78 back. Auto interrupt 5 is ideal for the kinds of synchronization used in game programming.
Auto interrupt 6:This interrupt is triggered when the ON key is pressed.
Auto interrupt 7:This is triggered when protected memory $000 to $120 is written to. Naturally, this interrupt cannot occur when bit 2 of ($600001) is reset.

Trap Interrupts

The second kind of interrupt is one triggered by software, and these are called trap interrupts. There are 16 trap interrupts called traps 0-15 that are invoked by the instruction trap #x, where x is the trap interrupt number you wish to invoke. On the 68000, these are usually supervisor programs that perform functions that cannot be done in user mode. To change the location of a trap interrupt handler, change the pointer at the appropriate RAM addresses according to the following table, again resetting bit 2 of ($600001):

trap 0 - $80

trap 1 - $84

trap 2 - $88

trap 3 - $8c

trap 4 - $90

trap 5 - $94

trap 6 - $98

trap 7 - $9c

trap 8 - $a0

trap 9 - $a4

trap 10 - $a8

trap 11 - $ac

trap 12 - $b0

trap 13 - $b4

trap 14 - $b8

trap 15 - $bc

TI-OS uses the following trap routines; the others are unused:

trap 0:This trap will call a subroutine anywhere in the first 64KB of ROM, as determined by the value of d0.w. Literally, it does the following: jsr ($400000+d0.w)
trap 1:This will set the bottom 16 bits of the status register with d0.w. The status register before the change will be returned in d0.l.
trap 2:This will reset the calculator.
trap 3:Unknown.
trap 4:This will turn off the calculator and wait for the ON key to be pressed to turn back on.
trap 5:Unknown.
trap 6:Unknown.
trap 7:Unknown.
trap 8:Unknown.
trap 9:This will take the value of d0.w and return a pointer to a certain subroutine or RAM address in a0.l as determined by a jump table. In ROM 1.00 this table is located at $4004f8.
trap 10:This will enter the self test

Disabling Interrupts

All auto interrupts can be disabled using the status register and trap 1. Bits 10, 9 and 8 of SR represent the lowest interrupt priority to be enabled (auto interrupt 1has the highest priority, auto interrupt 7 has the lowest priority). So, if these bits are %011 (4) respectively, then only the auto interrupts 5, 6 and 7 will be enabled. For example, then, to disable all the interrupts, you would execute the following:

 move.w #$0700,d0          ;set bits 8,9 and 10

 trap #1                   ;put d0.w into SR

 move.w d0,oldSR           ;save old SR

Other Interrupts

There is another kind of trap interrupt called an exception. This occurs after an instruction performs an illegal operation, such as accessing an odd address of memory with a word or longword, dividing by zero, or executing a nonexistent opcode.

All interrupts use what's called an interrupt vector table to look up the location of the ISR. Here is a table of all these locations:

AddressISR
0000 to 0007Reset vector (initial SSP and PC)
0008 to 000BBus error vector
000C to 000FAddress error vector
0010 to 0013Illegal instruction vector
0014 to 0017Zero divide vector
0018 to 001BCHK instruction vector
001C to 001FTRAPV instruction vector
0020 to 0023Privilege violation vector
0024 to 0027Trace vector
0028 to 002CLine 1010 emulator vector
002C to 002FLine 1011 emulator vector
0030 to 003BUnassigned, reserved
003C to 003FUninitialised interrupt vector
0040 to 005FUnassigned, reserved
0060 to 0063Spurious interrupt vector
0064 to 007FLevel 1-7 interrupt auto-vectors
0080 to 00BFTRAP #0-15 instruction vectors
00C0 to 00FFUnassigned, reserved
0100 to 03FFUser interrupt vectors

For example code showing how to implement an auto interrupt, see the grayscale tutorial.

That about covers interrupts on the 89 ... happy coding ;-)


© 1998 - 1999 ACZ