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 ;ReturnThis 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