DEMO
SINGLE INTERRUPT
On this page we'll explain how SIO/2 interrupts
work and provide a
demonstration program for you to
burn into a ROM, or rewrite slightly as a standalone app.
Interrupt Service Routine (ISR)
Z80 Interrupt Mode 2 uses 16-bit addresses
for its interrupt service routines (ISRs) unlike the other three (0, 1, NMI) interrupt modes which are
confined to the first 0100h bytes of memory.
The Interrupt Register (IR) holds the high byte
and the peripheral device (SIO/2 or CTC, etc.) interrupting the CPU holds the low
byte of the 2-byte address.
The IR was set to 00h (line 128 of our
code) and the WR2 register in Channel B was
set to "E0h" (line 104 of our
code) using the SIO Channel
B Control Register, "SioB_C".
The combined 16-bit address is 00E0h in the boot ROM. It could
have been placed anywhere in memory but we chose the boot ROM to
simplify testing.
Interrupt Vector Table (IVT)
"00E0h" is the address of the start of the Interrupt
Vector Table (IVT). All IVT entries are 2 bytes in size. "00E0h" is
also the address of the table's first entry for the
Interrupt Service Routine (ISR) "IntRx". This ISR reads a terminal
key press and echoes it to your screen.
The second ISR entry in the IVT would be at address
00E2h if we were setup for multiple interrupt vectors.
The IVT is essentially a "jump index" to the ISRs. It's
important when adding these "jump entries" to the table that the
ISRs themselves start on
even address boundaries, otherwise things will get weird if they work
at all. Just adding a NOP to the previous ISR will even up the
starting address of the next ISR. It's the starting addresses of the
ISRs that you place in the IVT.
The IVT in our Example
If you examine the 4th item from the top in the
adjacent panel, you'll see a line that reads "; SIO/2 Interrupt
Vector Table". Below this line in the leftmost column is address
"00E0". We placed a ".ORG" statement to start the addressing at
"00E0". The next line contains the code "42 01"
in the second column which is the result
of placing the statement ".DW IntRx". This assembler directive will
save us having to figure out the location of our first ISR, IntRx.
So
the first entry in our IVT is "4201" indicating the address of the
first ISR is "0142h". Note that it's an even number. As stated
above, all of your ISR addresses in the table must be even
numbers.
For demo purposes we used ".DW SpeclErr" to
have the assembler determine where our next ISR is located. This is
at location 0152h as you can see.
In summary, location "00E0h" contains the
"jump
to address" (0142h) to our first ISR, and location "00E2" contains the
"jump to address" (0152h) to our second ISR.
SIO/2 UART
Interrupt Mode 2
Starting with the second object in the adjacent
panel, we have the screens associated with an SIO/2 running in
Interrupt Mode 2 but with just one interrupt.
In this second screenshot a letter was typed in TeraTerm (configured for
57,600bps) and you can see it echoed to the screen.
In the third screenshot, DSView Logic Analyzer was setup to trigger on
INT going low.
Logic Analyzer (LA) Screen
Third from the top in the adjacent panel is
the DSLogic+ Logic Analyzer thumbnail. If you click on the link you'll
find that it is designed to stay open in a separate browser window so you can <CTRL><Tab> between
it and the ISR screenshot (at the bottom of the adjacent panel) as you examine
it.
Clicking on the LA screen should reveal a
red, dashed vertical line on the left that denotes the low-going trigger set on the
bus' INT line. The
CPU was in the middle of a "JP 013Eh" instruction when the interrupt
occurred.
To
the right of the instruction you can read "E0" which is the low byte
of the ISR's 16-bit address. This is what the SIO/2 puts on the data
bus for the CPU to combine with the high byte of the IR to yield the
complete IVT address, 00E0h.
The
"01 3E" that follows is the current address being pushed onto the
stack. You can tell that's so because it's not in byte-reversed
Little Endian format. "42 01" follows but you cannot see the "01" -
it's missing although you could still read data lines D7 to D0 to realize it's
"01" . "01 42" is the location of the ISR found in the IVT
that the CPU will jump to now.
The next bytes you read should match the ISR
itself, byte for byte, starting in line 141 of the program. If you look above the
LA's code to the timeline, you can see the "EI" and "RETI" instructions around 1026uS. These
denote the end of the ISR.
Above and to the right of the "RETI" is the return address of "013E"
that was pushed on the stack earlier. At this point the system
returns to the endless looping.
Only One Interrupt
If you choose to write only one interrupt as we
have done above, then it would have to contain all of the needed
functions. Alternatively, you can use multiple Interrupt Mode 2
interrupts by enabling the Channel B WR1-D2 bit. |