By: Larry Mayhew
Re: Re: 8259 pic
---------------------------------------------------------------------------
HS> How to use the 8259 programmable in controller. I know the I/O
HS> ports to use but wht to put there and when?
I wish there were some really simple answers to your question.
:-) My answer will oversimplify some details (for example, I
ignore the non-maskable interrupt), but it's a start.
When a hardware interrupt N occurs (say N=9, keyboard interrupt),
interrupts are disabled in two distinct ways: (1) The CPU's
Interrupt Flag is cleared by the interrupt mechanism. This
prevents any other hardware interrupt from occurring. (2) The
PIC's internal registers prioritize interrupts so that only
hardware interrupts numbered < N are allowed.
Inside the handler for Int N, an STI will enable interrupts from
the CPU's point of view, though leaving some still masked out by
the PIC. In the case of a keyboard handler (INT 9), executing
STI allows timer interrupts (INT 8) to interrupt the keyboard
service routine. Before the IRET in a hardware interrupt
handler, interrupts >= N must be re-enabled at the 8259. This
requires sending an EOI command to the 8259, which is ordinarily
done by this familiar code sequence:
mov ah,20h
out 20h,ah
When the 8259 receives the EOI, it then notes to itself that it
can reenable any interrupts that were previously disabled by
the occurrence of INT N. A programmer's most common interaction
with the 8259 is to send EOI to it.
A fairly typical scenario is to use STI early in an interrupt
handler, and to send EOI just before the IRET. Whether this is
appropriate for _your_ hardware service routine is something you
must decide by careful analysis of the whole system. IMO, PC
programmers too often fail to do the necessary analysis and wind
up writing interrupt service routines that have bugs, or at
least that are likely to cause intermittent failures in other
ISR's under special conditions.
It's probably also worth mentioning the IMR (interrupt mask
register) in the 8259. This allows hardware interrupts to be
masked out individually for periods of time without otherwise
affecting higher or lower numbered interrupts. Knowing when/
whether to use IMR-masking in the 8259 depends again upon an
analysis of your application and normal system operation.
There are other internal 8259 registers that control its
operations but are normally of no interest to the programmer,
(IRR,ISR). One might want to read these registers, however,
when debugging a problem involving the 8259.
Rarely, one may need to reprogram the 8259 to revector the
hardware interrupts to other INT numbers. This sort of thing is
ugly and should ordinarily be left to the people who write
OS code.
The best general advice I know to give would be this: (1) Keep
higher priority (lower numbered) interrupts disabled for as
short a time as possible. (2) Keep in mind that lower priority
interrupts can be lost if you fail too long to send EOI to the
8259. (3) If you call the original owner of the interrupt
before processing it, keep in mind that that owner may already
have sent EOI to the 8259. To send EOI again creates subtle,
very hard to find bugs in the system. (4) If EOI is sent to the
8259 before your routine is done, you need to choose between
disabling all interrupts (usually a bad idea) or writing your
routine so it's reentrant. (5) Your interrupt handler should
set up its own stack and switch to it unless a careful analysis
shows that stack overflow (when other routines interrupt yours)
is impossible. (6) It's usually a good idea to CLI just before
sending EOI, since conceivably another interrupt could occur
just before your final register pop(s) and IRET. While this
ordinarily won't hurt anything, it's conceivable that the
few extra items on the stack could lead to stack overflow for
the interrupting routine.
To discuss all of this thoroughly here would take us beyond the
scope of the C_Echo. I'd be happy to answer specific questions
from you in NetMail, but the basic thrust of my answer is that
to use the 8259 properly you need a pretty good understanding of
how your interrupt routine is related to other interrupt
routines in the system. Even so simple a question as when to
send EOI can raise complex issues.