This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
strongest educational materials in computing,
bringing cutting-edge thinking and best learning
practice to a global market.
Under a range of well-known imprints, including
Prentice Hall, we craft high quality print and
electronic publications which help readers
to understand and apply their content,
whether studying or at work.
To find out more about the complete range of our
publishing please visit us on the World Wide Web
at: www.pearsoned.co.uk
9.4 Interrupt processing – service on demand 203
On entering an ISR the first job to be done is to protect those CPU
registers that will be used in the ISR from corruption. This simply
involves PUSHing the contents onto the stack, from where they will
be restored at the completion of interrupt pro- cessing. Then the
source of the interrupt has to be verified, perhaps by testing a
pe- ripheral device flag bit, and the cause of the interrupt
removed. Until this is done there is the danger of suffering a
repeated interrupt from the same source, even though all the
processing has been completed. It may then be necessary to
reinitial-
ize the peripheral device to ready it for another interrupt
request, although some- times this is not required. The end of the
ISR is marked by POPping the saved registers and the execution of
an rte instruction to restore the PC value.
The 8086 required the IVT to start at 0000. But the facility to
relocate the IVT any- where in main memory was introduced with the
80386 through the provision of the Interrupt Descriptor Table
Register (IDTR). To move the IVT you simply copy the con- tents,
with any needed revisions, into the new position and point the IDTR
to the base of the new table.
If a device requires only occasional attention then the interrupt
method works fine: the peripheral just demands CPU help when it
needs it. Using interrupts does require special hardware to be
installed, and the changeover from main program to ISR and back
again is a wasteful activity which often takes several microseconds
each time to complete.
Most peripheral devices can be configured to use the CPU interrupt
facility, but if there are many such devices triggering interrupt
requests there will be extra problems to be considered. When
several requests arrive at the same time there is a need to pri-
oritize the devices and queue the requests until they can be
serviced. The identifica- tion of the source of the interrupt may
require explicit device polling if the hardware is unable to return
an interrupt vector. Locating the appropriate interrupt routine in
memory is normally straightforward using the VBR and the IVT.
The various sources of interrupts may be put into six categories,
listed in Table 9.4. Some small microcontrollers do not allow
interrupt processing itself to be inter-
rupted. The ability to accept and honour interrupts at any time is
known as interrupt nesting. In this situation, a high-priority
device, such as a hard disk, could break into a low-priority
service routine without delay.
A further important use of modern interrupt facilities has been
introduced by the implementation of access modes. By allocating CPU
facilities and memory seg- ments either ‘User’ or ‘Privileged’
status, the system can protect its core functions from ordinary
users, reserving the more risky capabilities for ‘root’ (or
super-user).
Table 9.4 Possible sources of interrupts.
1. IO data transfer request
2. Software TRAP (SVC)
204 Chapter 9 Simple input and output
This is illustrated in Fig. 9.16, with the privilege levels
represented as concentric spheres. Such access control is essential
for modern multi-user operating systems and depends on all
interrupts switching the CPU into Privileged Mode.
Thus interrupts provide a small entry window to the system
facilities which can be policed by ISR code, which is now included
as part of the operating system. This could be seen as the most
significant use of the software interrupt or TRAP
instruction.
There is an extra problem when trying to debug systems running
interrupt rou- tines. With ordinary subroutines, the programmer
should be able to tell exactly when each subroutine will run,
taking into account the variation from moment to moment of
IF-THEN-ELSE statements which may test changeable environmental
conditions. In fact, some subroutines may never run at all because
it happens to be a leap year, or Sweden doesn’t recognize
Euro-travel Passes, or whatever. The role of interrupt rou- tines
is to run when the CPU interrupt signal gets activated by a
circumstance which is not always under the control of the
programmer. Thus we say that subroutines are predictable and
synchronous, while interrupt routines are asynchronous and unpre-
dictable. This makes debugging software systems where several
interrupts are likely to fire at any time much more demanding,
especially when the debugger software confuses the situation by
using the trace interrupt for its own ends!
Using the interrupts on digital computers has been criticized as
dangerous because of the unpredictability of their occurrence and
the resulting difficulty in thoroughly testing the system. Thus
programmers building embedded computer systems for life- critical
applications often try to avoid relying on interrupt facilities.
But when consid- ering less risky areas, hardware interrupts can
offer an efficient technique to introduce some measure of
responsive multitasking to the system. Windows and Unix provide
helpful viewer tools which enable you to watch the rate of
interrupt processing as it occurs on your machine. Unix has
perfmeter, which was introduced in Section 3.2, while Windows
offers Performance Meter which is illustrated in Fig. 9.17.
This useful administration tool allows you to inspect the IRQ
allocation, as well as some other interesting parameters. To fire
it up select:
StartS ProgramsS Administrative Tools 1Common 2 S
Performance MonitorS EditS Add to ChartS Interrupts>sec
Fig. 9.16 How interrupts assist operating system security.
9.5 Critical data protection – how to communicate with interrupts
205
Mouse
activity
Fig. 9.17 Displaying interrupt activity on Windows NT.
In Fig. 9.17 the interrupt activity is displayed as a running
average taken during 0.1 s intervals. When the mouse is oscillated
from side to side it generates a burst of in- terrupts which show
up as a rise in the average value. Such an increase would also re-
sult if the keyboard were to be used, or any other device which is
tied into the PC interrupt system.
Critical data protection – how to communicate with interrupts
As we started to discuss in Section 8.8, there is a particular
problem with passing data back from an ISR. Consider the situation
shown in Fig. 9.18 of a time-of-day (TOD) program which has two
parts. There is a real-time clock (RTC) ISR being triggered every
10 ms to increment the seconds, minutes and hours values, and there
is a dis- play routine to refresh a set of front panel digits
showing the TOD. The msecs, secs,
9.5
206 Chapter 9 Simple input and output
Fig. 9.18 Real-time clock and time-of-day display.
mins and hrs data is held in memory. The routine which refreshes
the display runs regularly, about twice a second as a low priority
task, perhaps in the main processing loop. It takes the current
seconds value, converts it to seven-segment format and writes it to
the display. Then it does the same for minutes and then for
hours.
The RTC ISR is more urgent and will break into any main process so
that it can update the clock data in main memory. Now, what happens
if the display is being refreshed when an RTC interrupt occurs?
Consider the situation 01:59:59, with the display refresh having
just written new values for secs and mins, and being poised
to
9.5 Critical data protection – how to communicate with interrupts
207
1. Disable interrupts
Table 9.5 Alternative solu- tions to protecting a critical
resource.
read the hrs from memory – and just then the RTC ISR occurs. It
will rollover incre- ment msecs to 00, then secs to 00, then mins
to 00, then hrs to 02. Having completed the ‘tick’ it returns
control to the main program. This happens to be right on the point
of refreshing the hrs display. This it does, leaving the incorrect
value 02:59:59 for all to see. The false value will remain visible
until the next display refresh occurs to correct it. In this
example, the clock values in memory have not been corrupted, so no
lasting damage is done (unless you missed your train). If the
display update rou- tine also served a network connection, there
would be scope for a larger disaster.
The problem described arises from the complexity of the data being
processed and the need for simultaneous unsynchronized access by
two or more processes. In a more general form you may encounter the
same problem when programming a multitasking application for Unix
or Windows. It is known as the critical resource problem. In this
case, it is worth noting that if time was simply stored as a 32 bit
integer there would be no problem, because the value would always
be valid: interleaved update and display op- erations could not
result in corrupted data unless the computer had multiple
processors!
There are several solutions which can be tried to clear up the
difficulty, as listed in Table 9.5.
If the interrupts were disabled to block the RTC interrupt request
on entry to the display update routines, and then re-enabled at the
completion of the display refresh, the display would remain
coherent but would progressively go wrong. When the sys- tem
receives an RTC interrupt its response would be delayed if the
interrupts were disabled, so there is a risk that the TOD would
become out of true. This is a more sig- nificant issue when the
ticks occur more rapidly than 100 Hz. In fact, turning off all of
the interrupts is far too drastic, because it would interfere with
other interrupt- driven activity, such as IO transfers. This
solution is only acceptable for small micro- controller systems,
where interrupt deferment would not be too disruptive.
A better solution in this clock example would be to serialize
access to the critical data region, as presented in Fig. 9.19. This
means moving all the code across from the RTC ISR to the main
program flow, just before the display refresh routines. This makes
it impossible to read partly updated data. But now the RTC ISR must
indicate to the main program through a flag or simple integer that
a tick has occurred since the last display update. A check on the
value of the RTC flag will determine whether a clock increment
needs to take place.