Supplement to Microprocessors Lecture 14

Interrupts (1)

Of all the new ideas which you have to understand in this course the idea of interrupts seems to be the most difficult to grasp. Interrupts solve two problems which can occur in a computer system which runs simple sequential programs of the sort we have been looking at.
  1. Quick response to an external event
    It is obviously possible for the processor to check the condition of control lines and inputs at regular intervals to see if special attention is required. Sometimes, however, this process can be too slow when an event occurs which requires instant action. For example, in a process control computer there will be lines monitoring the power supply so that if a power failure occurs everything can be shut down in an orderly and safe fashion. Clearly this shutdown must be initiated the moment an impending failure occurs; it is no good waiting until the line is next checked. The same applies to inputs going out of range; a temperature or pressure too high. In ordinary computer systems some peripheral devices, such as magnetic-tape drives require or generate data at a fixed (and quite high) rate. If the processor does not take the data within the time available then it will be lost.
  2. Wasting time
    Obviously it is possible to achieve the above by testing all the appropriate inputs very frequently but this results in a lot of time being wasted. Checking for a power failure is time wasted virtually every time it is done. When you are on a terminal connected to the VAX you expect and get a fairly quick response when you press a key (and remember that keypress has to be received by the computer and retransmitted before you even see the character on the screen). With over 350 terminals on the VAX if this was done by checking every line every half second then a great deal of computer time would be wasted.
The answer is to have a signal to the processor which diverts the processor from its current program sequence into some other program sequence. This is the interrupt input, and as its name implies it interrupts the processor in mid-program and tells it to do something else. Its like receiving a telephone call now telling me to go and show a party of prospective students round the department. If this is considered to be a higher priority task than what I'm doing now I would have to go and do it. But before I did I would have to make a note of where I was in this document (or the lecture) so that I can carry on where I left off on my return.

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:

  1. How does the processor know what program to run? There are probably many sources of interrupts.
  2. How does the processor know where to pick up the current program after handling the interrupt exactly where it left off?

Storing the Processor Status

Dealing with the second problem first, it obviously not practical for the processor to stop what it is doing in the middle of an instruction - that would leave the processor in an ill-defined state with partial results formed etc. So the processor continues to the end of the current instruction, This clearly places a limit on how quickly the processor can respond since some instructions (e.g. PSHS All) takes 17 cycles.

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.

Interrupt Vectors

There are not many options when it comes to telling the processor where the program to handle interrupts is stored. Essentially a special memory location must be set aside for this purpose and it is usually at the very bottom of memory (location $0000) or at the very top (location $FFFF). This is built into the design of the processor and is not something that the system designer can do anything about but must be taken into account when deciding what type of memory to put where in the address space. It would obviously not make sense to put interface devices at locations used for this purpose.

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

IRQ Interrupt

The 'normal' interrupt input is the IRQ input and its vector is stored at $FFF8 & $FFF9. Thus when the processor responds to an interrupt on this line it jumps to the address stored at that these locations.

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.

Reset

When the power is switched on it is important to ensure that the correct program starts running on the processor initially. This is done by means of the reset input which should be zero when power comes on and then goes to a one after about 10 clock cycles. This initialises the processor and it then starts running the program by jumping to the address in locations FFFE & FFFF i.e. the Reset vector. This process can be initiated at any time by supplying a reset signal. This is obviously useful when a program has crashed or is in an infinite loop.

The use of Dr A J Tollyfield's notes is gratefully acknowledged


| Back | Next |