Copyright ©1997 Barleywood. All rights reserved. No part of this document may be copied or reproduced in any form or by any means without the prior written consent of Barleywood.
I (Thomas Scherrer) have permission to convert this document to HTML and put it online at my site, thanks to Barlewood and Mike Moore.
Z80® is a registered trademark of Zilog, Inc
This original page is available in word format from this link
Z80® Family Interrupt Structure
Interrupts provide the mechanism by which the Z80 can process asynchronous events such as timers, sensor input and peripheral communication.
When an interrupt is received the Z80 executes a sub-routine known as an Interrupt Handler. These subroutines are the same as any other machine code subroutine except that the following considerations need to be taken into account
The sub-routine can be executed at random points in the code and so must ensure that registers are saved before any data is lost.
Interrupts must be re-enabled as soon as possible once the registers have been saved and the data acquired
The RETI (RETurn from Interrupt) instruction must be used to return from an Interrupt Handler sub-routine.
Because the Z80 has only one interrupt line, the Z80 and its peripheral support chips negotiate for the CPUs attention by using a hardware based daisy-chain approach. The peripheral chip closest to the power line on the daisy-chain has the highest priority when it raises an interrupt request. This is because the interrupting chip indicates its need for service to the other peripheral chips through the IEO signal. Any chip which is physically closer to the CPU on the chain can be blocked from raising an interrupt by holding IEO (Interrupt Enable Output) on the interrupting device low. Any peripheral chip which is being blocked from the CPU in this way will simply keep the interrupt request signal (INT) active until either the CPU acknowledges the peripheral chip (or until it loses the data). The peripheral is acknowledged when IEI is high (and IEO low) at the time that INTACK is received.
Figure 1: The Z80 Interrupt Daisy-Chain
The INT signal is known as a maskable interrupt because the programmer can cause the CPU to ignore all interrupt requests by using the DI (Disable Interrupt) instruction. Maskable interrupts are automatically disabled by the CPU during the INTACK cycle and must be re-enabled by the programmer (using the EI - Enable Interrupts - instruction) before any more interrupts can be acknowledged. The EI instruction is normally executed as soon as possible in the interrupt handler code to avoid losing any interrupt signals from higher priority peripherals in the daisy-chain.
A skeletal interrupt handler sub-routine is shown in Figure 2.
Data acquisition in an interrupt handler is normally achieved using the IN instruction. The Z80 supports two forms of the IN instruction, direct input to the A register
IN A,(PORT)
or indirect input into any 8-bit register
LD C,PORT
IN E,(C)
If the interrupt handler is extremely small and fast, or loss of incoming interrupt signals is not a factor in the design of the interrupt handler, then an extremely fast alternative mechanism for saving the register set is the EXX (EXchange eXtended registers) instruction.
In this case the EI instruction should only be executed after the registers are restored since the execution of another EXX instruction effectively results in the restoration of the saved register values and possible register data corruption if executed by a subsequent interrupt handler sub-routine.
Each PUSH instruction in Figure 2 requires 11 T-states and each POP instruction requires 10 for a total 84 T-states required to save register values. The EX and EXX instructions in Figure 3 require 4 T-states each for a total 16 T-states.
The Z80 supports three different modes of operation when an interrupt signal is received. The IM (Interrupt Mode) instruction is used to determine which of the modes (0, 1 and 2) should be used.
Interrupt Mode 0 is not supported by the Barleywood Z80 Simulator. This mode requires specific hardware support by the memory sub-system as well as by the interrupting device. In Mode 0, the interrupting device is required to place a Z80 instruction on the DATA bus. The Z80 will then execute this instruction. Normally the RST instructions are used for this purpose, but any instruction (including multi-byte instructions such as CALL) can be used.
Interrupt Mode 1 always calls the subroutine beginning at address 38h. This mode requires that the interrupt handler is able to determine which interrupting device generated the interrupt and be able to take the appropriate action. Normally, the code beginning at address 38h is a register save sequence followed by a JP instruction.
Interrupt Mode 2 is the most frequently used interrupt mode with the Z80 and its related peripherals. The interrupting device automatically places a vector address on the DATA bus when it recognises the INTACK. This forms the lower eight-bits of a 16-bit address. The contents of the I register form the upper eight bits of the address.
All of the Z80 family peripherals (e.g. CTC, DART, PIO) can be easily programmed during initialisation to place a unique eight-bit value on the DATA bus in response to the INTACK signal.
This 16-bit address is a vector. That is, the two-byte value which is found beginning at the RAM location specified by the vector is yet another address. This second address is the start of the interrupt handler routine.
Figure 4 shows the basic interrupt mode 2 initialisation code.