It is important to remember that an interrupt may occur at any moment in the running of a program and of course this will usually be in the middle of carrying out some instruction.
There are clearly two problems to solve in order to make this work:
Once the instruction is completed the state of the processor is defined by the contents of all the registers. In particular the PC indicates which instruction comes next and the CC register holds any important flags showing what happened in the previous instruction. Therefore if all the registers are stored then it is perfectly possible for the processor to resume later on.
Where should these registers be stored? We have the same options as we did for the subroutine return address except that the amount of data concerned is much greater. Again the obvious solution is on the stack for the same reasons - in particular this allows nesting of interrupts as would be needed if the processor was responding to a keypress when a higher priority interrupt from a tape drive occurred. It is worth noting that some processors do use alternative approaches, such as the Z80 which has a second set of registers which can be brought into use. This allows a very fast interrupt response since nothing has to be stored but does not allow easy nesting. The Texas 9000 range had a novel approach which was to have no registers inside the processor and to use an area of memory for its registers. To respond to an interrupt a different area of memory was used. This allows fast interrupt handling but very slow normal processing.
What is actually stored at the special address is not the interrupt program itself but a pointer to the interrupt program. The reason for this will become clear later on. When the processor responds to an interrupt the registers are first stored on the stack and then the processor performs an indirect jump to the address stored in the interrupt vector location. When the interrupt routine is completed a RTI (Return from Interrupt) instruction restores all the registers from the stack and processing carries on as before.
As we shall see later there is an alternative to this approach which is for the device which is causing the interrupt to supply the interrupt vector (or part of it). As we have seen interface devices are usually programmable which makes it relatively easy to initialise the interface with the interrupt vector it should generate. Other systems simply have a number of interrupt lines each with a separate vector. To be effective there must be sufficient interrupt lines for every device to have one - which is rarely the case.
The 6809 has three interrupt inputs, but rather than being intended for each of three different devices these are different standards of service. There in fact 7 interrupt vectors although only 3 are true interrupts and the others interrupt-like events.
Interrupt Vector Location
MS Byte LS Byte
FFFE FFFF Reset
FFFC FFFD NMI
FFFA FFFB swi
FFF8 FFF9 IRQ
FFF6 FFF7 FIRQ
FFF4 FFFS SWI2
FFF2 FFF3 SWI3
Suppose we want to write a program such as that in Lab 2 which flashes the LEDs on and off continuously but also counts interrupts so that when an interrupt occurs the LEDs show the count for four seconds then go back to flashing.
;This is the main program
ORG $0020
main LDA #$FF ;Initialise VIA
STA $FE02
CLR $0010 ;Initialise interrupt counter
ANDCC #$EF ;Enable interrupts
CLRA ;LEDs ON
loop STA $FE00
LDB #$01 ;One second delay
JSR delay
COMA ;Switch LEDs to 'other' state
BRA loop
;Delay routine - Number of seconds in B
delay PSHS A,B,X ;Save registers
loopl LDA #$02
loop2 LDX #$C646 ;This gives half a second
loop3 LEAX -1,X
BNE loop3
DECA
BNE loop2
DECB
BNE loopl
PULS A,B,X ;Restore registers
RTS ;& return
;Interrupt routine
;N B interrupts occuring while in this routine
;will not be counted
ORG $0100
intpt INC $0010 ;Increment interrupt counter
LDA $0010 ;display it
STA $FE00
LDB #$04 ;for 4 secs
JSR delay
RTI ;Return
This will work only if the interrupt vector locations FFF8 and
FFF9 contain the address of the start of the interrupt routine
i.e. $0100. Note that when the processor responds to an interrupt
the interrupt flag is set which inhibits further interrupts.
This is done after storing the status register on the stack so
that when the return from interrupt occurs the previous value
(which must have been zero) will be restored and interrupts re-
enabled.
Whilst nested interrupts are often desirable it is important to establish the source of the interrupt and ensure that the cause is removed before it is safe to enable interrupts to allow other higher priority devices to cause an interrupt. If this is not done it is very easy to get an infinite loop created which very rapidly uses up the stack and wreaks havoc with memory.
The use of Dr A J Tollyfield's notes is gratefully acknowledged