You are on page 1of 14

The 8086 Interrupt Mechanism: The 8259A PIC

Introduction The original 8088/8086 PCs used an Intel 8259A PIC (Programmable Interrupt Controller) to manage its eight hardware interrupts (also called IRQs, which is short for Interrupt Requests). This separate chip communicates with the processor and tells it when an interrupt needs to be serviced and which ISR (Interrupt Service Routine) to call. Therefore, any device that generates interrupts is connected to one the interrupt pins on the PIC, not to the CPU. The interrupt (or IRQ) pins on the PIC are numbered 0 to 7 where IRQ 0 is the highest priority interrupt and IRQ 7 is the lowest priority. The PIC connects to the processor's single maskable interrupt pin. If an interrupt occurs, the PIC lets the processor know by asserting this interrupt pin. The Interrupt Flag One of the flags in the 8086 processor is the interrupt flag, usually referred to as IF. This flag can be set or cleared with the sti and cli instructions respectively. When set (1), the processor monitors its interrupt pin. When it is cleared (0), the processor ignores the signals on its interrupt pin. Therefore, interrupts can be enabled or disabled by setting and resetting the IF flag. However, this essentially disables communication between the PIC and the processor, disabling all external interrupts. To disable individual interrupts, a mask value can be written to the PIC instead. However, this will not be necessary for this class. The 8259A's Registers The 8259A has three 8-bit registers that determine its behavior: the IMR (Interrupt Mask Register), the ISR (In-Service Register), and the IRR (Interrupt Request Register). The bits of these registers are numbered 0 through 7, where 0 is the least significant and 7 is the most significant bit. Each bit of each of these registers corresponds to the respective interrupt pin on the PIC. That is, bit 7 corresponds to IRQ 7, bit 6 corresponds to IRQ 6, and so on. The IMR. This register allows the programmer to disable or "mask" individual interrupts so that the PIC doesn't interrupt the processor when the corresponding interrupt is signaled. For an interrupt to be disabled, its corresponding bit in the IMR

must be 1. To be enabled, its bit must be 0. Interrupts can be enabled or disabled by the programmer by reading the IMR, setting or clearing the appropriate bits, then writing the new value back to the IMR. The IRR. This register indicates when an interrupt has been signaled by a device. As soon as a device signals an interrupt, the corresponding bit in the IRR is set to a 1. This register can only be modified by the PIC and its contents are usually not important to the programmer. However, it can be used to tell which interrupts are waiting for service. The ISR. This register indicates which interrupts are currently being serviced (i.e., which ISRs have begun execution and have not yet finished). A 1 bit indicates that the corresponding ISR is currently in-service. Several interrupts can be in-service at the same time because of interrupt nesting. The PIC uses this register to determine the highest priority of the interrupts currently being serviced. With this information, the PIC will only interrupt the processor if the highest priority set bit in the IRR has a higher priority than the highest priority set bit in the ISR. In other words, the PIC will never interrupt an in-service interrupt in order to service another interrupt of the same or lower priority. Before an ISR finishes executing, it must send to the PIC the end of interrupt command (EOI) so that the PIC knows that it can safely clear the highest priority bit in the ISR and signal any other pending interrupts. Be careful not to confuse "In-Service Register" with "Interrupt Service Routine", both of which use the "ISR" acronym. Processor/PIC Actions When an interrupt occurs, if the interrupt is enabled in the IMR (i.e., it's IMR bit is 0) and if the processor's IF flag is set (IF=1), then hardware does the following: 1. The PIC informs the processor that an interrupt has occurred by asserting the processor's interrupt pin. 2. The processor finishes the currently executing instruction. 3. The processor sends an acknowledgement signal to the PIC. 4. The PIC then passes to the processor the vector number for the interrupt that occurred. 5. The processor uses this vector number to determine the address where the ISR (interrupt service routine) is stored. The vector number is used as an index into the interrupt vector table (or interrupt descriptor table), which starts at address 0:0. The corresponding entry in the interrupt vector table contains the address (segment and offset) for the ISR. 6. The processor pushes the flags, CS, and IP onto the stack (in that order).

7. The processor clears IF, disabling interrupts. 8. The processor then sets CS and IP to the segment and offset of the ISR that was read from the vector table and begins execution. The vector number that is passed to the CPU by the PIC corresponds to the interrupt that occurs. IRQ 0 corresponds to vector number 8, IRQ 1 corresponds to vector number 9, and so on. ISR Actions Once execution begins in the ISR, your code that makes up the ISR should do the following (in the order given): 1. Save the context of whatever was running by pushing all registers onto the stack, except SP, SS, CS, IP, and the flags. 2. Enable interrupts to allow higher priority IRQs to interrupt. 3. Run the interrupt handler, which is usually a C function that does the work for this interrupt. 4. Disable interrupts. 5. Send the EOI command to the PIC, informing it that the handler is finished. 6. Restore the context of what was running before the interrupt occurred by popping the registers saved in step 1 off the stack. 7. Execute the iret instruction. This restores in one atomic operation the values for IP, CS, and the flags, which were automatically saved on the stack by the processor when the interrupt occurred. This effectively restores execution to the point where the interrupt occurred. Important note: When using an RTOS (Real-Time Operating System) it is also usually necessary to call an OS function after step 1 to inform the OS that an ISR has begun execution. Then another OS function must be called after step 5 to inform the RTOS that the ISR is finished. In the RTOS you will build, these functions correspond to YKEnterISR() and YKExitISR(). This will allow the RTOS to know when execution is supposed to return to task code and allows the RTOS to return control to the highest prority ready task rather than the interrupted task. Remember that the handling of the IRR and ISR registers in the PIC is done for you automatically as interrupts occur. Additionally, you do not need to read or set the IMR since the PIC will automatically ignore interrupts of the same or lower priority while an interrupt is being serviced. For the labs in this class, if you do not wish to use an interrupt, you should simply create an ISR that does not call an interrupt handler.

Do not push or pop the registers SP or SS when saving and restoring context! This is not necessary since SS and SP must already be correct before executing "pop ss" or "pop sp". Also, the "push sp" instruction behaves differently on some 8086 clones. In an RTOS it will be necessary to save and restore SS and SP as part of a task's context, but this should be handled in a different way (e.g., the movinstruction). The EOI Command: In order for interrupts to work correctly, the PIC must be told when the end of an interrupt has occurred. To tell the PIC that the end of an interrupt has occurred we send it what is called a nonspecific EOI command (or unspecific EOI). To do this we simply write the value 0x20 to port 0x20, which is one of the PIC's ports.
mov register al out al, 0x20 0x20, al ; Load nonspecific EOI value (0x20) into ; Write EOI to PIC (port 0x20)

This code should be executed by every ISR right before it restores the context and executes the iret instruction.

AN INTRODUCTION TO INTERRUPTS
INTERRUPTS There are two main types of interrupt in the 8086 microprocessor, internal and external hardware interrupts. Hardware interrupts occur when a peripheral device asserts an interrupt input pin of the microprocessor. Whereas internal interrupts are initiated by the state of the CPU (e.g. divide by zero error) or by an instruction. Provided the interrupt is permitted, it will be acknowledged by the processor at the end of the current memory cycle. The processor then services the interrupt by branching to a special service routine written to handle that particular interrupt. Upon servicing the device, the processor is then instructed to continue with what is was doing previously by use of the "return from interrupt" instruction. The status of the programme being executed must first be saved. The processors registers will be saved on the stack, or, at very least, the programme counter will be saved. Preserving those registers which are not saved will be the responsibility of the interrupt service routine. Once the programme counter has been saved, the processor will branch to the address of the service routine. Edge or Level sensitive Interrupts Edge level interrupts are recognised on the falling or rising edge of the input signal. They are generally used for high priority interrupts and are latched internally inside the processor. If this latching was not done, the processor could easily miss the falling edge (due to its short duration) and thus not respond to the interrupt request. Level sensitive interrupts overcome the problem of latching, in that the requesting device holds the interrupt line at a specified logic state (normally logic zero) till the processor acknowledges the interrupt. This type of interrupt can be shared by other devices in a wired 'OR' configuration, which is commonly used to support daisy chaining and other techniques.

Maskable Interrupts The processor can inhibit certain types of interrupts by use of a special interrupt mask bit. This mask bit is part of the flags/condition code register, or a special interrupt register. In the 8086 microprocessor if this bit is clear, and an interrupt request occurs on the Interrupt Request input, it is ignored. Non-Maskable Interrupts There are some interrupts which cannot be masked out or ignored by the processor. These are associated with high priority tasks which cannot be ignored (like memory parity or bus faults). In general, most processors support the Non-Maskable Interrupt (NMI). This interrupt has absolute priority, and when it occurs, the processor will finish the current memory cycle, then branch to a special routine written to handle the interrupt request. Advantages of Interrupts Interrupts are used to ensure adequate service response times by the processing. Sometimes, with software polling routines, service times by the processor cannot be guaranteed, and data may be lost. The use of interrupts guarantees that the processor will service the request within a specified time period, reducing the likelihood of lost data. Interrupt Latency The time interval from when the interrupt is first asserted to the time the CPU recognises it. This will depend much upon whether interrupts are disabled, prioritized and what the processor is currently executing. At times, a processor might ignore requests whilst executing some indivisible instruction stream (read-write-modify cycle). The figure that matters most is the longest possible interrupt latency time. Interrupt Response Time The time interval between the CPU recognising the interrupt to the time when the first instruction of the interrupt service routine is executed. This is determined by the processor architecture and clock speed.

The Operation of an Interrupt sequence on the 8086 Microprocessor: 1. External interface sends an interrupt signal, to the Interrupt Request (INTR) pin, or an internal interrupt occurs. 2. The CPU finishes the present instruction (for a hardware interrupt) and sends Interrupt Acknowledge (INTA) to hardware interface. 3. The interrupt type N is sent to the Central Processor Unit (CPU) via the Data bus from the hardware interface. 4. The contents of the flag registers are pushed onto the stack. 5. Both the interrupt (IF) and (TF) flags are cleared. This disables the INTR pin and the trap or single-step feature. 6. The contents of the code segment register (CS) are pushed onto the Stack. 7. The contents of the instruction pointer (IP) are pushed onto the Stack. 8. The interrupt vector contents are fetched, from (4 x N) and then placed into the IP and from (4 x N +2) into the CS so that the next instruction executes at the interrupt service procedure addressed by the interrupt vector. 9. While returning from the interrupt-service routine by the Interrupt Return (IRET) instruction, the IP, CS and Flag registers are popped from the Stack and return to their state prior to the interrupt.

Multiple Interrupts If more than one device is connected to the interrupt line, the processor needs to know to which device service routine it should branch to. The identification

of the device requesting service can be done in either hardware or software, or a combination of both. The three main methods are: 1. Software Polling, 2. Hardware Polling, (Daisy Chain), 3. Hardware Identification (Vectored Interrupts). Software Polling Determination of the Requesting Device A software routine is used to identify the device requesting service. A simple polling technique is used, each device is checked to see if it was the one needing service.

Having identified the device, the processor then branches to the appropriate interrupt-handling-routine address for the given device. The order in which the devices appear in the polling sequence determines their priority.

Summary of Software Polled I/O Polling is the most common and simplest method of I/O control. It requires no special hardware and all I/O transfers are controlled by the CPU programme. Polling is a synchronous mechanism, by which devices are serviced in sequential order. The polling technique, however, has limitations. 1) it is wasteful of the processors time, as it needlessly checks the status of all devices all the time, 2) it is inherently slow, as it checks the status of all I/O devices before it comes back to check any given one again, 3) when fast devices are connected to a system, polling may simply not be fast enough to satisfy the minimum service requirements, 4) priority of the device is determined by the order in the polling loop, but it is possible to change it via software.

Software/Hardware Driven Identification (Daisy Chain) This is significantly faster than a pure software approach. A daisy chain is used to identify the device requesting service.

Daisy Chain Polling Arangement

Daisy chaining is used for level sensitive interrupts, which act like a wired 'OR' gate. Any requesting device can take the interrupt line low, and keep it asserted low until it is serviced. Because more than one device can assert the shared interrupt line simultaneously, some method must be employed to ensure device priority. This is done using the interrupt acknowledge signal generated by the processor in response to an interrupt request.

Each device is connected to the same interrupt request line, but the interrupt acknowledge line is passed through each device, from the highest priority device first, to the lowest priority device last. After preserving the required registers, the microprocessor generates an interrupt acknowledge signal. This is gated through each device. If device 1 generated the interrupt, it will place its identification signal on the data bus, which is read by the processor, and used to generate the address of the interrupt-service routine. If device 1 did not request the servicing, it will pass the interrupt acknowledge signal on to the next device in the chain. Device 2 follows the same procedure, and so on.

Hardware Identification (Vectored Interrupts) This is the fastest system. The onus is placed on the requesting device to request the interrupt, and identify itself. The identity could be a branching address for the desired interrupt-handling routine. If the device just supplies an identification number, this can be used in conjunction with a lookup table to determine the address of the required service routine. Response time is best when the device requesting service also supplies a branching address.

Priority Interrupt Management Controller Priority Interrupt Controller Chips (PIC's) are hardware chips designed to make the task of a device presenting its own address to the CPU simple. The PIC also assesses the priority of the devices connected to it. Modern PIC's can also be programmed to prevent the generation of interrupts which are lower than a desired level. The decoded location is connected to the output of a priority encoder. The input of the priority encoder is connected to each device. When a device requests service, the priority encoder presents a special code combination (unique for each device) to the decoded memory location. The port thus holds the value or address associated with the highest device requesting service.

The priority encoder arranges all devices in a list, devices given a lower priority are serviced when no other higher priority devices need servicing. This simplifies the software required to determine the device, resulting in an increase in speed. The disadvantages are: 1) 2) 3) 4) the extra chip required, resultant increases in cost, more board space and power consumption, fixed priority in hardware.

You might also like