Skip to content
Victor edited this page Jan 17, 2024 · 19 revisions

SH-2

Unified interrupt handler

Toshiyasu Morita, Programming the 32x FAQ

The early revisions of the 32x use the 2.5 cut of the SH2, which has a problem with interrupts. Specifically, if a low priority interrupt occurs, and within a 3-cycle window a higher priority interrupt occurs, then the 2.5 revision of the SH2 will jump to the low priority interrupt vector and lose the high priority interrupt. The SR will still be set to the number of the higher priority interrupt, however.

The first half of the unified interrupt handler is to vector all the interrupts to a common routine, which checks the SR for the proper proper interrupt to handle. In this way, the higher priority interrupt is serviced first, which is the correct behavior.

The second component of the unified interrupt handler is the free-running timer's output is tied to the least significant bit of the interrupt request lines, which toggles the least significant bit of the interrupt request lines. If the interrupt request level is nonzero this will cause it to bounce between odd/even which effectively "retriggers" the interrupt, so the low-priority interrupt will be serviced.

To mask interrupts on the 32x you must put a "2" into the SR - putting a zero will allow the free-running timer to trigger interrupts, since it toggles the least significant bit of the interrupt request lines, which causes it to generate interrupt 0 and interrupt 1 requests continuously which will cause a degradation of CPU performance.

FRT Bumping

In the schematics, FTOA (FRTimer Output A) is connected directly to /IRL0 (on both CPUs). The FRT int is disabled, but the FRT is running with it set to set or clear the timer compare output when compare register A matches the FRT counter. The register is set to 1. It is also set to clear the FRT counter when the compare is equal. So the FRT is always running - counting up to 1, then setting/clearing FTOA, and clearing the counter, then counting up to 1 again.

The interrupt code toggles the bit in the FRT that tells it to set or clear FTOA. So FTOA is toggled hi/low every 1 count - and the FRT clock is set to Fs/8. So every 16 clock cycles, FTOA will toggle on/off once. This will change /IRL0 every 16 clock cycles. This is why every interrupt uses two levels - one is the real interrupt level, and the other is to allow FTOA to bump the int 16 clock cycles later.

So no FRT int occurs, but rather an IRL int occurs, then 16 clock cycles later, and IRL+1 int occurs... and continues to occur every 16 cycles until the system processes the IRL int that originally occured. You need to keep the int mask high enough to ignore level 1 ints or the cpu will get interrupted every 16 clock cycles by the FRT bump.

FRT Initialization

Initialization of the free run timer must be done whether or not interrupt is used in coping with SH2 interrupt.

Free running timer initialization - [1994-09-23]

Interrupt Problems on the 32X

When two or more types of interrupts are used by the SH2, an interrupt of the same level may be acknowledged twice consecutively in relation to the occurrence of a single interrupt.

Example

tech_27.png

Explanation

When the CMD INT occurs, the SH2 acknowledges the interrupt (recognized as level 8) and starts to process it. However, if a V-INT occurs before the SR is masked, the SH2 processes the V-INT instead since it has higher priority than the currently masked level (in this case, 8). Moreover, the FRT is set and the V-INT is cleared during this process, changing the external interrupt level as a result.

After the V-INT is processed, processing on the previously acknowledged CMD INT begins again. However, if the FRT output value changes before the SR is masked, the SH2 will judge that a higher priority level interrupt has occurred than the currently masked level (in this case level 8). As a result, the SH2 begins to process a CMD INT (acknowledged as level 9) instead. After this CMD INT is processed, the SH2 will process the CMD INT acknowledged as a level 8 interrupt once again. This means that processing on the CMD INT will occur twice, even though it actually occurred once. Refer to the interrupt handler in the bulletin (This code can also be found in the 32X Hardware Manual Supplement 2).

(Note: this problem only occurs on the 32X. It does not occur on the Saturn.)

32X Technical Bulletin #27 - SH2 Interrupt Problems on the 32X - [1994-12-08]

Bus conflicts between the two SH2's

Simultaneously writing to the same location in SDRAM from both CPUs will most likely lock up the system due to bus conflict.

68000

68000 interrupts & RV bit = 1

All 68000 interrupts must be prohibited during the period that the RV bit = 1.

32X Technical Bulletin #9 - 68K interrupts & RV bit = 1 - [1994-09-23]

About ROM read when RV=1

The following address data not normally read When RV=1:

  • $1070 - $1073 (4 bytes)
  • $2070 - $2073 (4 bytes)
  • $3070 - $3073 (4 bytes)

Total of 12 bytes

DMA between MEGA Drive and 32

SH2 contains a 2 channel DMA. If transfer request is set to auto request and is within the SH2 address space, transfer betwwen memories can be performed (at generation inside the DMA).

When transfert request is done by an external request (DREQ), DMA transfer can be done by the dual address mode for:

  • channel 0 from FIFO to SH2-side RAM;
  • channel 1 PWM sound source pulse width register.

DMA transfer can be done by the dual address mode. External requests should be used by the edge trigger, not the level trigger.

image

DMA transfer from the MEGA Drive to 32X is done through the FIFO packaged 32X. If data is set to this FIFO from the MEGA Drive, transfer request (DREQ0) occurs for the DMA of SH2. In the SH2 side, DMA channel 0 is set in externalrequest and FIFO is specified and transferred to the source address.

This sets data tot FIFO from the MEGA Drive side.

CPU Write is the method for writing to FIFO by 68000 directly for each word. At a time, if the Full bit of the DREQ control register is 0 write is possible and if Full bit is 1 then it is FIFO Full.

https://gendev.spritesmind.net/forum/viewtopic.php?p=17527#p17527

Chilly Willy:

When doing 68K to 32X DMA via the FIFO in the 32X, it has a tendency to lose data randomly. Specifically, the DREQ fails to trigger the DMA under unknown circumstances, which means the SH2 DMA stops. If you are checking the FIFO full flags, it will "stick" at full because the DMA is no longer emptying the FIFO.

I would guess that's why ob1 doesn't check the FIFO flag in SVDP. It's probably also the source of the occasional drop-outs in the video you see.

If you ignore the FIFO full flag, the next store to the FIFO "bumps" the hardware and DMA resumes... but you lose one word. On a DMA transfer of 65536 words, it typically lost between 20 and 120 words (usually closer to 20 than 120).

I'll try to find why it loses the DREQ, but it might be that this is something that will have to be worked around... a hardware bug not fixed before the production model chips were made.

A work around would be to send packets of data (say 256 words), don't check the FIFO full flag, and send extra words at the end to make sure the SH2 DMA finishes. Then put a checksum for the packet into the COMM registers. If the checksum is good, go on to the next packet, and if it's bad, retry the packet.

https://gendev.spritesmind.net/forum/viewtopic.php?t=3206

ob1:

I've noted that I had to wait some time between setting CPU WRITE ($A15107b.2) and the first transfer from 68k to DREQ FIFO. 11 NOPs seems to be the bare minimal, but I'm more at ease with ~100 cycles. This delay might be needed for the DREQ circuitry to warm-up, or the SH2 to get all the needed infos.

Z80

32X Technical Notes:

  1. (supposedly fixed) Z80 writes to $84000-$9FFFFF and $A15100-$A153FF will lock the 68000. Writes to MD work RAM and PSG are allowed.
  2. The Z80 bank shift register must not be set to $000000-$3FFFFF or $840000-$9FFFFF. The 68000 may get inconsistent data, and the 32X registers may become corrupted.

General

Interrupt handlers

As a rule of thumb, all interrupt handlers on both SH-2's and the 68K must run from RAM.

Word-RAM-to-VRAM-capture-DMA

When a CD is used, Word-RAM-to-VRAM-capture-DMA has a problem in the timing of data fetch, and since data becomes undefined, it can not be used.

SuperVDP

Shift bit precaution

The shift bit becomes invalid when the lower byte of the base address set in the line table is $FF. Therefore, make sure the lower byte in the table is not $FF when using shift.

32X Technical Bulletin #14 - VDP shift bit precaution - [1994-09-23]

Auto Fill and DRAM (VRAM) access

The SH2's cannot access DRAM (VRAM) while the auto fill is executing. In practice, this means the following:

  • only one SH2 can use the filler
  • MUST run from cart
  • not access DRAM while the fill is in progress
  • the other SH2 must not access DRAM during that time as well

Undocumented mirroring

  • 24000000 - 24020000 DRAM
  • 24020000 - 24040000 OVERIMAGE
  • 24040000 - 24060000 DRAM MIRROR
  • 24060000 - 24080000 OVERIMAGE MIRROR(?)

Miscellaneous

Tom Forsyth, programmer

The SH2s had odd pipelining where one multiply cost 3 clocks, but if you started a second multiply it only cost 2 clocks more. So you got 2 multiplies in 5 clocks.

So to explain this I wrote some code on-screen, compiled, ran the test, to show coloured scanlines (old-school demo coder style) and you could clearly see the performance delta.

People came up to me afterwards and said how bizarre it was to see someone coding live on-stage at a dev conference. In retrospect it was only because the tools were so reliable that it was a sane thing to do!

page 225 of the programming manual