gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Low Level Description of Interrupts

#27430 - ScottLininger - Tue Oct 12, 2004 10:05 pm

Can anyone point me at a reference that describes what actually happens when an interrupt fires?

Specifically, I'm trying to understand what happens if an HBLANK or VBLANK interrupt calls a function that takes too long to execute. I mean, if your VBLANK function contains a lot of calculations that go beyond the length of the VBLANK, will the next VBlank INTERRUPT the function? Similarly, will an HBLANK interrupt itself if it goes too many cycles? Might this cause a crash?

I have a bug where I am changing the blending register every HBLANK to create a fog effect, and on hardware it seems to be causing a crash. Here's the code:

Code:
void HBLANK(void)
{
   // alter the transparency of our "fog" layer
   REG_COLV = FogAmount[REG_VCOUNT+80-(statusWindowTop>>1)];

   REG_IF |= INT_HBLANK;
}


FogAmount is a pre-calculated array of valid REG_COLV values that creates a gradient of transparency.

statusWindowTop contains a u16 that changes as a "window" appears on the bottom of the screen, which offsets the fog.

With this code in place, my game will run for anywhere from 1-12 minutes before it totally crashes on hardware. With it commented out, no crash. I'm assuming it has something to do with how my interrupts are playing together. I'm running a VBLANK and a TIMER interrupt besides this one.

Thanks!

-Scott

#27433 - abilyk - Tue Oct 12, 2004 10:44 pm

Scott,

I made a post a little while ago that went in depth into how interrupts work... or, at least, how I believe they work from the research I've done. Take a look, and if you still have questions afterwards, let me know and I'll see if I can help.

http://forum.gbadev.org/viewtopic.php?p=27057#27057

#27434 - DekuTree64 - Tue Oct 12, 2004 11:00 pm

Check out the last post in this topic for everything you ever wanted to know about interrupts. I learned a lot of little details about them that I didn't know about from that.

Normally when say the HBlank interrupt runs so long that it's still going when the next HBlank fires, the next one will set the HBlank bit in REG_IF, but not actually interrupt the CPU. Then as soon as you return from the first HBlank, the second will fire off because its bit it still set in IF.

Well, that's how it should work anyway. The way you're doing it now it sets IF just before returning, so it would just cancel out the second HBlank entirely. It's better to clear the flag you're handling in IF as soon as possible after the interrupt was triggered, although it doesn't make any difference unless an interrupt of the same type occurrs before you're finished processing.

What could cause problems though, is that REG_IF |= INT_HBLANK. I think that will acknowledge the HBlank, as well as any other interrupts that have occurred since your HBlank started, so they will get skipped. Instead, just do REG_IF = INT_HBLANK and it will leave the other bits alone, to re-interrupt the CPU as soon as your HBlank returns.

EDIT: Dangit, the very guy I was pointing you to beat me to it.
BTW, thanks a lot for writing up that post, Abilyk. It should be preserved in the GBADev docs section, I think, or maybe put into the FAQ.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#27436 - abilyk - Tue Oct 12, 2004 11:14 pm

Thanks for the comments, Deku. I've learned a ton from this board, so I'm glad to be able to contribute. I'll convert the post to a document and submit it to Simon sometime soon.