18
ELEC-4601: Microprocessor Systems Lab 2: 80x86 Interrupts The Point Writing software to properly respond to a hardware interrupt is fussy. There is a hardware path from the incoming interrupt signal all the way to the microprocessor that needs to be correctly laid out and ‘enabled’ using specific bits within specific registers that are located at specific addresses in the I/O mapped memory space of the microprocessor. In this lab, the microprocessor is a member of the 80x86 family but the process or laying out and enabling this path is fundamentally the same for all microprocessors and microcontrollers. There are typically three places where interrupts can be enabled or disabled i.e. allowed to proceed or blocked from proceeding. The microprocessor itself usually has a global ‘Interrupt enable’ bit or bits as part of a CPU flags register e.g. IF bit in the FLAGS register in the 80x86. If there is a subsystem that is responsible for arbitrating incoming interrupts (in this case, the 8259 Programmable Interrupt Controller or PIC) then it will have registers and bits that need configuring to accept an interrupt and forward it on to the CPU. Finally, the interface subsystem that actually connects to the interrupt source will have some set of registers and bits that need to be configured in order to let the interrupt proceed on its way to the interrupt arbitrator (e.g. the PIC). Once the hardware path has been properly enabled and interrupts can actually reach the CPU, the software has to be written to recognize the interrupt, service it, and gracefully restore the system back to its normal ‘waiting for an interrupt’ state. The frustrating part of this process arises from the fact that unless everything is working and configured properly then the system will fail, usually in a fatal fashion. If all the hardware isn’t configured properly you will not see the interrupt. Once you can see the interrupt, incorrect software will fail (totally) and you will have to reset the hardware and try again. Debugging a hardware interrupt in real time is a notoriously difficult thing but once you have done it for a system such as this one you will know what to look for in any microprocessor system and you will be able to anticipate the amount of time to allocate to this part of the design process. This is something worth knowing. Introduction Interrupts offer an alternate way of responding to external events in a microprocessor system. The microprocessor can ‘poll’ for changes in the environment by constantly looking for those changes or it can wait until a device signals a change and ‘handle the interrupt’ caused by the change. For real time events, such as keyboard presses, internal time-of- day clock changes, printer-out-of-paper etc., an actual hardware digital signal, referred to as an IRQ (Interrupt ReQuest) can be generated. They are usually numbered according to their priority, with IRQ0 having the highest priority (the system time-of-day) and IRQ7 the lowest (the LPT1 printer port). For typical simple microprocessor systems, the following flowchart applies:

Lab 2: 80x86 Interrupts

  • Upload
    others

  • View
    9

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Lab 2: 80x86 Interrupts

ELEC-4601: Microprocessor Systems

Lab 2: 80x86 Interrupts The Point Writing software to properly respond to a hardware interrupt is fussy. There is a hardware path from the

incoming interrupt signal all the way to the microprocessor that needs to be correctly laid out and ‘enabled’ using

specific bits within specific registers that are located at specific addresses in the I/O mapped memory space of the

microprocessor. In this lab, the microprocessor is a member of the 80x86 family but the process or laying out and

enabling this path is fundamentally the same for all microprocessors and microcontrollers.

There are typically three places where interrupts can be enabled or disabled i.e. allowed to proceed or blocked

from proceeding. The microprocessor itself usually has a global ‘Interrupt enable’ bit or bits as part of a CPU flags

register e.g. IF bit in the FLAGS register in the 80x86. If there is a subsystem that is responsible for arbitrating incoming

interrupts (in this case, the 8259 Programmable Interrupt Controller or PIC) then it will have registers and bits that need

configuring to accept an interrupt and forward it on to the CPU. Finally, the interface subsystem that actually connects

to the interrupt source will have some set of registers and bits that need to be configured in order to let the interrupt

proceed on its way to the interrupt arbitrator (e.g. the PIC).

Once the hardware path has been properly enabled and interrupts can actually reach the CPU, the software has to be

written to recognize the interrupt, service it, and gracefully restore the system back to its normal ‘waiting for an interrupt’

state.

The frustrating part of this process arises from the fact that unless everything is working and configured properly

then the system will fail, usually in a fatal fashion. If all the hardware isn’t configured properly you will not see the

interrupt. Once you can see the interrupt, incorrect software will fail (totally) and you will have to reset the hardware

and try again. Debugging a hardware interrupt in real time is a notoriously difficult thing but once you have done it for a

system such as this one you will know what to look for in any microprocessor system and you will be able to anticipate

the amount of time to allocate to this part of the design process. This is something worth knowing.

Introduction

Interrupts offer an alternate way of responding to external events in a microprocessor system. The microprocessor

can ‘poll’ for changes in the environment by constantly looking for those changes or it can wait until a device signals a

change and ‘handle the interrupt’ caused by the change. For real time events, such as keyboard presses, internal time-of-

day clock changes, printer-out-of-paper etc., an actual hardware digital signal, referred to as an IRQ (Interrupt ReQuest)

can be generated. They are usually numbered according to their priority, with IRQ0 having the highest priority (the system

time-of-day) and IRQ7 the lowest (the LPT1 printer port). For typical simple microprocessor systems, the following

flowchart applies:

Page 2: Lab 2: 80x86 Interrupts

The software procedure, usually small and fast, that runs in response to an interrupt is referred to as an Interrupt

Service Routine (ISR). 80X86 processors operating in real-mode (the simple microprocessor mode used in the lab) make

use of an Interrupt Descriptor Table (IDT) which consists of 256 entries (numbered 0 through 255), each of which holds

the address of an ISR. The IDT starts at memory location 0000:0000. Most of these entries are for the 255 ‘software’

interrupts and processor exceptions that the processor supports. Some of the entries in this table have been set aside for

‘hardware’ interrupts, with IRQ0 to IRQ7 using up the IDT slots at positions 8 to 15, and IRQ8 to IRQ15 using up the IDT

slots at positions 0x70 to 0x77. In response to an interrupt, the processor will finish executing the current instruction,

immediately jump to the address stored in the IDT at the appropriate location, and continue executing instructions from

this new address.

Purpose

This lab will investigate a number of things in software:

- the steps necessary to get a typical microprocessor system to actually recognize that an external hardware

interrupt has occurred

- the steps necessary to service this interrupt and to clear the interrupting condition

This lab will look at a number of things related to hardware:

How to debug interrupts using the logic analyzer

How to measure the speed of interrupt handlers

Execute software instruction

Save state, jump to service

Service the interrupt

Restore state as before interrupt

Interrupt received?

YES

No

Page 3: Lab 2: 80x86 Interrupts

Equipment required

HP 16702B Logic Analyzer

PC/104 or ISA bus PC

HP33120A Function Generator for Part A

Windows PC with a serial port and running a terminal (TeraTerm Pro) program

Part A : Simple Squarewave Interrupts

This portion of the lab concerns setting up a simple square wave generator to input a TTL signal at a variable frequency

through the IRQ7 hardware interrupt of a conventional 80x86 PC. In addition, the lab involves writing software to allow

this interrupt to be recognized by the 80x86 processor and to display a count of the interrupts that have been recognized.

The student is expected to have tried to fill in the steps of the LAB2A.PAS text file that has been posted to the course

website. The steps are laid out in the source file with the actual setting/clearing of register bits, as required, left to the

student. All registers of interest for the purposes of this lab are I/O mapped i.e. the bits within each register can be

accessed through the standard instructions

MOV DX,<register address>

IN AL,DX ; read an 8-bit device register value whose I/O address is <register address>

OR AL,<some value> ; set one or more bits in the register

AND AL,<some value> ; clear one or more bits in the register OUT

DX,AL ; write an 8-bit value back to the device register

The registers of interest are documented in Appendix C at the end of this lab.

Procedure

1 . Fill in the necessary code in the LAB2A.PAS file that has been supplied. This is most of the work.

2. Create an executable (.EXE) file from this code using the supplied tools (MAKE.BAT, TPC.EXE, TURBO.TPL) e.g.

C>make lab2a.pas

3. Run the LAB2A.EXE file

4. Turn on the HP33120 function generator and set it for a squarewave at about 100Hz. Connect the SYNC output of this

function generator, using a supplied BNC cable, to the little black parallel port unit with the LED lights on it (there

should be a BNC connector on the end of this unit).

Page 4: Lab 2: 80x86 Interrupts

4. Observe the results, which should be the following

- the 8 bit LED display should show an incrementing binary count

- the LED display should count faster or slower as the frequency of the squarewave generator is increased or

decreased

5. Measure the response time of the software. The response time will be defined as the time difference between the

rising edge of the IRQ7 interrupt signal (the squarewave) and the final execution of the code that is in the Interrupt

Service Routine. The logic analyzer will be required in order to make this measurement.

Performing time measurements on an interrupt driven system is sometimes tricky and you generally have to include your

own ‘markers’ (unique events that simplify triggering o f the logic analyzer) into the code. This code is removed after you

have done the tests that you want to do. A recommended event, immediately after you enter the ISR and save your

registers (notice that saving the DX register is now required because of this code) is the following : MOV DX,0379h ; read

the parallel port status, something unique

IN AL,DX

It is pretty much a certainty for this lab that you have the following code inside your ISR in some fashion, just before you

exit the ISR (hint here)

OUT 020h,020h ; send EOI to PIC and enable further interrupt processing

Unfortunately, this particular instruction is being executed all the time in a normal, simple PC system when other

interrupts, such as the system timer that keeps track of the time of day, are being handled. So a more unique condition

for our test would be to trigger on the two instructions: an I/O read from address 0379h followed by an I/O write to

address 020h. If you trigger on this event, a display on the logic analyzer of the IRQ7 rising edge, followed by the I/O read

and write, will give you a single picture from which you can make a timing measurement.

Measure the time from the IRQ7 rising edge to the execution of the ‘marker’ instruction above. This is the ‘interrupt

response time’ to get to the first part of your ISR. Knowing that the processor that we are using is a 40MHz 80386sx, and

knowing how many instructions are executed before executing the ‘marker’ (basically a few PUSH instructions), calculate

a more accurate value for the response time i.e. what you measured minus the time it takes to save some things on the

stack.

Now measure the time it takes to actually service the interrupt i.e. the time from the very first instruction of the ISR to the

very last. This is just the time that elapses between the ‘marker’ command and the ‘write EOI to PIC’ command. Now adjust

this time to account for the code that occurs just before the marker (the PUSH commands) and the code that occurs just

after the EOI write (the POP commands and the IRET).

6. Show the TA that you have made the measurements (two screen shots of the logic analyzer should be taken) and that

the little LEDs on the parallel port actually operate as expected.

Note:

Load your LAB1 configuration file for the Logic Analyzer. This time, you will need to add the IRQ, IOR and IOW pins to

your configuration. Refer back to Lab 1’s setup procedure, if you need more help. Refer to Appendix B for the pin layout.

**Note: IOR and IOW are located on the clock inputs. **

Page 5: Lab 2: 80x86 Interrupts

Part B : Serial Port Interrupts

This portion of the lab involves generating an interrupt by sending one or more serial characters over a connection

between the Windows PC at the lab station and the 80x86 microprocessor that we are testing. For the setup that we are

using, the hardware interrupt of interest is IRQ4 (serial port COM1 in a PC).

In addition, this lab involves writing software to handle this interrupt and to echo the received characters back to the

Windows PC over the serial connection. The software for this part of the lab is almost exactly the same as the previous

code, except for some setup of the serial communications chip and the use of a different IRQ signal.

Procedure 1

Make sure that you have TeraTerm Pro running on the Windows machine at your workstation and that is is setup as

shown in Appendix D. Run the ‘mode’ command on the 80x86 system as described in the appendix.

First, a quick check of the connection between the two machines. Run ‘debug; on the 80x86 machine as you did in Lab 1.

C>debug

-

Now press the ‘A’ key on the Windows machine keyboard while the TeraTerm Pro app has the focus. Then look at the

contents of the register at i/o address 0x3F8

Page 6: Lab 2: 80x86 Interrupts

- i 3F8

61

Hex 61 is the ASCII (a standard for encoding serial data) code for the lowercase letter ‘a’. Repeat this process (press key,

read port 0x3F8) for the letters ‘b’,’c’ and’d’ and note the codes.

Now look at the contents of the registers at 0x3F9 (IMR) and 0x3FA (IIR)

- i 3F9

00

- i 3FA

01

From the register information, this shows that no interrupts are enabled and no interrupts are pending. Now enable the

interrupt that occurs when a character is available from the serial port:

- o 3F9 01

Now press the ‘a’ key on the Windows keyboard and then read the register at 0x3FA

- i 3FA

04

This indicates that an interrupt has been generated and that the interrupt is related to the ‘Received Data Available

Interrupt’. Read the value of port 0x3FA several times to show that the interrupt is still pending (the value doesn’t

change).

Now read the value at port 0x3F8 and then the value at port 0x3FA

- i 3F8

61

- i 3FA

01

This indicates that the act of reading the serial buffer register automatically clears the interrupt condition i.e. you have

‘handled the interrupt’

Procedure 2

Now make and run the LAB2B.PAS code that you have written for the lab.

Proper operation is indicated by a simple echoing of the character pressed at the Windows keyboard i.e. if you press the

‘a’ key, you will see an ‘a’ appear in the window.

Page 7: Lab 2: 80x86 Interrupts

Hopefully we will have a little demonstration station setup so that you can actually see the serial communication

waveforms on an oscilloscope and see how they change with the data and with changes to the communication

parameters.

Page 8: Lab 2: 80x86 Interrupts

Write up and Deliverables: 1. Parallel Port Interrupt

a. Print and submit well commented code for both of the interrupts.

b. Have a TA check and verify that your parallel port interrupt counter works from the 1 to 100Hz range.

c. Using your logic analyzer, monitor the IRQ, IOR, IOW and the ADDR lines. Track the changes in the

address lines. How long does it take from receiving the interrupt to the code jump? Print out a screenshot

and hand it in.

d. Speed up the incoming clock, and see if you can make the ISR fail. How might it fail?

2. Serial Interrupt

a. Demonstrate the serial interrupt echo.

Page 9: Lab 2: 80x86 Interrupts

Appendix A

PIC# (Base

Address) INT (Hex) IRQ Common Uses

00 - 01 Exception Handlers -

02 Non-Maskable IRQ Non-Maskable IRQ (Parity Errors)

03 - 07 Exception Handlers -

PIC#1 (0x20) 08 Hardware IRQ0 System Timer

09 Hardware IRQ1 Keyboard

0A Hardware IRQ2 Redirected

0B Hardware IRQ3 Serial Comms. COM2/COM4

0C Hardware IRQ4 Serial Comms. COM1/COM3

0D Hardware IRQ5 Reserved/Sound Card

0E Hardware IRQ6 Floppy Disk Controller

0F Hardware IRQ7 Parallel Comms.

10 - 6F Software Interrupts -

PIC#2 (0xA0) 70 Hardware IRQ8 Real Time Clock

71 Hardware IRQ9 Redirected IRQ2

72 Hardware IRQ10 Reserved

73 Hardware IRQ11 Reserved

74 Hardware IRQ12 PS/2 Mouse

75 Hardware IRQ13 Math's Co-Processor

76 Hardware IRQ14 Hard Disk Drive

77 Hardware IRQ15 Reserved

78 - FF Software Interrupts -

Table 1 : x86 Interrupt Vectors

Page 10: Lab 2: 80x86 Interrupts

Appendix B Channel Number

[Pin #] POD 1 POD 2 POD 3

Pin Name

DATA Pin Name

ADDR Pin Name

MISC

GND GND GND GND 0 SD0 SA0 SA16 1 SD1 SA1 SA17 2 SD2 SA2 SA18 3 SD3 SA3 SA19 4 SD4 SA4 IRQ4 5 SD5 SA5 IRQ5 6 SD6 SA6 IRQ3 7 SD7 SA7 IRQ7 8 SD8 SA8 MEMR 9 SD9 SA9 MEMW

10 SD10 SA10 BALE 11 SD11 SA11 REFRESH 12 SD12 SA12 AEN 13 SD13 SA13 OSC 14 SD14 SA14 SYSCLK 15 SD15 SA15 - CLK IOR IOW

Table 2: Logic Analyzer Pin Assignments

Page 11: Lab 2: 80x86 Interrupts

Appendix C (also available as a separate document) Links : http://retired.beyondlogic.org/serial/serial.htm http://retired.beyondlogic.org/spp/parallel.htm

Dir = direction, R=read, W=write, R/W=read and write

Register offset : add this to the base I/O address to access the register itself

Device Base address Register

offset

Dir Bit functions

PIC

0x20

0 W Command

1

R/W

IMR Interrupt Mask Register

7 6 5 4 3 2 0

for IRQn, n=0..7

Bit n = 0, interrupt IRQn enabled

Bit n = 1, interrupt IRQn disabled

LPT1 0x378 0 W data port

a read returns the last byte

written

1 R status port

2 R/W control port

7 5 4 3 2 1 0

Page 12: Lab 2: 80x86 Interrupts

7..6 : unused

5 : enable bi-directional port

4 : enable IRQ through the pin 10

3 : select printer

2 : reset printer

1 : auto linefeed

0 : strobe

Device Base address Register

offset

Dir Bit functions

COM1

0x3F8

0 R/W Data register

Read receiver data

Write transmitter data

0

R/W Baud rate divisor low

if DLAB bit=1 in LCR below

low byte of 16-bit baud rate

divisor

1

R/W

IER

Interrupt Enable Register

7 6 5 4 3 2 1 0

Page 13: Lab 2: 80x86 Interrupts

enable=1, disable=0

7..4 : reserved

3 : enable modem status int.

2 : enable receiver line status int.

1 : enable transmitter empty int.

0 : enable receiver full int.

1 R/W Baud rate divisor high

if DLAB bit=1 in LCR below

high byte of 16-bit baud rate

divisor

2 R IIR

Interrupt Identification Register

Device Base address Register

offset

Dir Bit functions

COM1 0x3F8 3 R/W LCR

Line Control Register

7 6 5 4 3 2 1 0

Page 14: Lab 2: 80x86 Interrupts

7 : DLAB=0 normally

: DLAB=1 to access baud rate

divisor bytes

6 : set break enable if 1

5..3 : parity select code

X X 0 no parity

0 0 1 odd parity

0 1 1 even parity

1 0 1 parity bit always high

1 1 1 parity bit

always low

2 : one stop bit =

0 two stop bits = 1

1..0 : word length

1 1 = eight bit data

1 0 = seven bit data

0 1 = six bit data

0 0 = five bit data

4 R/W MCR Modem Control Register

5 R/W LSR Line Status Register

Page 15: Lab 2: 80x86 Interrupts

Table of Baud Rate Divisor Values for a serial port Values

based on the following calculation : divisor = 1843200/16/baud_rate

e.g. for 2400 baud rate, divisor = 1843200/16/2400 = 49 (decimal) = 0x30

bps (bit/sec) divisor (decimal) latch high byte (hex) latch low byte (hex)

50 2304 09h 00h

300 384 01h 80h

600 192 00h C0h

2400 48 00h 30h

4800 24 00h 18h

9600 12 00h 0Ch

19200 6 00h 06h

38400 3 00h 03h

57600 2 00h 02h

115200 1 00h 01h

Page 16: Lab 2: 80x86 Interrupts

Appendix D

Running TeraTerm Pro on the Windows machine in the lab.

Somewhere on the desktop of the Windows machine at the lab station will be an icon for the serial terminal program

TeraTerm Pro. HyperTerminal is the classic terminal program for windows but it doesn’t normally come with Windows 7

(the version in the lab). Start up this program and you should get an option for either a ‘TCP/IP’ connection or ‘serial’

connection. Choose the serial connection over COM1 (the communication port in the Windows machine). A window

should appear that looks like the the following:

a

Serial communication connections have setup information that you need to configure. You can get at this information

through the main menu:

Page 17: Lab 2: 80x86 Interrupts

Selecting the ‘Serial port…’ option will finally bring up the place where communications parameters can be changed:

For this lab, these default settings are fine.

For communication to the 80x86 system to work, we need to ensure that the 80x86 system is physically connected to

the Windows 7 with a serial cable. The cable is what is referred to as ‘DB-9’ . The ‘DB’ specifies the shape and style of the

connectors on the end of the cable (a letter ‘D’ rectangular shape) and the 9 specifies the number of pins on the

connector. You should also see the words ‘NULL’ or ‘NULL MODEM’ on the cable. This ensures that the pins used to

transmit and receive data are connected properly between the machines i.e. the transmitted data from one machine is

connected to the received data of the other and vice versa.

Page 18: Lab 2: 80x86 Interrupts

Ensure that the serial cable is connected to the Serial1 connector on the 80x86 machine. This is also referred to as

COM1:

Now ensure that the serial communication parameters on the 80x86 system are the same as the Windows machine.

From a command prompt on the 80x86 system, type the following:

C>mode com1: 9600,n,8,1

This will execute the ‘MODE’ command on the port ‘COM1’ (the one connected to the Windows machine) and set the

parameters for 9600 baud, no parity, 8 data bits, 1 stop bit. This should match the Windows machine and now serial

communication should be possible.