cr1901 wrote:
BigDumbDinosaur wrote:
In POC's ISR, interrupt sources are read and cleared immediately after the MPU state has been pushed—interrupt state for each I/O device is also pushed, since indexed stack accesses are convenient and efficient with the '816. Once that is done, the ISR proceeds to act on each interrupt status value.
Basically, for each I/O device:
- Read the register that has the interrupt data for the I/O device.
- Push it.
- Clear the relevant interrupt bit/send it back to the device (if necessary).
- Read and push all registers for the current device.
Do you do a.-c. or a.-d.?
Here's a synopsis of how I do it:
- Push the MPU state. As POC V1.1 is a general purpose computer, every 65C816 register is pushed, including DB and DP.
- Read the interrupt status register (ISR) for each device that can interrupt and push it. In POC V1.1, that would be the SCSI controller, real-time clock, and DUART. In the SCSI controller and RTC, reading the ISR also clears the device's interrupt output. It's a little more involved with the DUART, which continues to interrupt as long as RxD and TxD FIFOs are full (RxD) or empty (TxD).
- Examine each ISR value that was pushed to see if the corresponding device interrupted. If it did, its interrupt code is executed, the code being arranged in blocks. Otherwise, skip that device and try the next one.
- Clean up the stack. With the '816, this can be done by simply loading the stack pointer (SP) into .C (the 16 bit accumulator), adding the number of bytes that were pushed during step B and then copying .C back to SP.
- Restore the MPU state and RTI.
The source code and a
ROM listing are posted on my POC website if you are interested (scroll down to line 3373 in the ROM listing). It's not the most up to date version, but close enough for discussion.
Quote:
The fact that POC 1.1 works at 12.5MHz with wired-OR is reassuring. I do miss the concept of interrupt priorities (though I could always code the ISR in such a manner- rotating priority sounds appealing
) where only one device is serviced per interrupt, but this is me coming from 8259 land.
Better to service all possible interrupt sources
en masse. The 65C816 will consume eight clock cycles responding to an IRQ and another eight clock cycles executing RTI at the end of the ISR. If you process only one interrupt that 16 clock cycle overhead has to be repeated N times if all devices are interrupting.
Quote:
Also, using your scheme, isn't it possible for a second device to signal an interrupt between the time the interrupt state of the device is read and the "Interrupt needs servicing" bit of the I/O device is cleared, thereby missing an interrupt, unless using some sort of atomic instruction? EDIT: Apparently, this can't be done according to your '816 Interrupt primer.
It would depend on the device in question. I don't use any 65xx I/O silicon in my design, so I can't speak for how a, say, 65C22 would behave in that scenario. However, if while servicing an interrupt the device generates another one, it will be interrupting the MPU when your ISR finishes up with RTI. So you would immediately start working on the new interrupt.
Chip errata can mess up things for you. As an example, the 6526 complex interface adapter (CIA) that was used in the Commodore 64, B-128 and C-128 had a bug in which if the interrupt status register was read one or two clock cycles before timer B was schedule to underflow and interrupt, the timer B interrupt would not occur (this bug often caused the fake RS-232 routines in the C-64 and C-128 to mess up). This error was not present in all devices, but had to be considered in writing code that was to rely on timer B interrupts. Hence it was necessary to check timer B in software to see if it had relatched, since the interrupt itself was unreliable.
All of the devices that I use provide detailed status about why they are interrupting, and operate asynchronously to the Ø2 clock, unlike the 65xx silicon. If they change state while interrupt processing is going on it doesn't cause any problem. As soon as the IRQ handler has finished up and returned to the foreground a new interrupt will occur.
Quote:
EDIT 2: "Operating the 65C816 at Ø2 rates over 8 MHz often necessitates the use of hardware wait-states when I/O devices must be accessed." Is this true with 14MHz parts?
The WDC 65C21, 65C22 and 65C51 are specified for 14 MHz operation and thus require no wait-states. I suspect those parts can be run faster, but don't know if that's the case. You should note that chip selects for those devices, as well as the state of R/W, must be valid before the rise of Ø2. In other words, the 'C21, 'C22 and 'C51 run synchronously with the MPU.