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.

DS development > Interrupts and VBlank

#78197 - qw3rky - Wed Apr 05, 2006 10:12 pm

I am having serious trouble getting the vblank swi to work on the DS. I'm building my own minimalistic DS library for educational purposes and because I'm absurdly picky over naming things, and I've done the same already with the GBA, so I'm no n00b at coding interrupts. I've tried compiling the ISR as ARM only, putting it in ITCM, putting it in IWRAM, and it just won't work. My current code does work fine in iDeaS, but not in Dualis (which is becoming my favorite emulator) or actual hardware.

here's my SWI call: (carried over from my GBA code)
Code:

#ifdef __thumb__
#define vsync() asm volatile("swi 0x5")
#else
#define vsync() asm volatile("swi 0x50000")
#endif


here's my interrupt initialization:
Code:

   disableInterrupts(); // IME = 0
   InterruptHandler = (uint32) isr;
   InterruptEnable |= VBLANK_INTR_ENABLE;
   DisplayStatus   |= VBLANK_INTR_REQUEST;
   enableInterrupts(); // IME = 1


and here's my isr:
Code:

void isr()
{
   /* disable interrupts */
   disableInterrupts();

   /* acknowledge flags */
   InterruptCheck |= VBLANK_INTR_ENABLE;
   InterruptFlags |= VBLANK_INTR_ENABLE;
   
   /* re-enable interrupts */
   enableInterrupts();
}


DSTek says that an ARM9 interrupt can be either ARM or THUMB code, so it seems there's no need to compile it separately as ARM like we had to do with the GBA. So it seems like my code should work perfectly fine, which it does on iDeaS, but if it doesn't work on hardware, I consider it completely useless. The Vsync is the most essential timing mechanism you can have in a console game, so obviously this is pretty important for me to sort out. Does anyone know what I'm doing wrong?
_________________
I've coded about 17 different implementations of Pong. It's the game dev's "hello, world".
DualScheme - Scheme Interpreter for DS

#78205 - DekuTree64 - Wed Apr 05, 2006 10:48 pm

What is InterruptCheck defined as, and where do you have DTCM located? Is it declared volatile?
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#78210 - qw3rky - Wed Apr 05, 2006 11:18 pm

i'm still using the linker scripts from DevKitARM, so the DTCM is defined at 0x00800000 (in ds_arm9.ld) and InterruptCheck is my name for what libnds calls VBLANK_INTR_WAIT_FLAGS (the register at 0x00803FF8), which has to be one of the most inaccurate, inappropriate names I've seen in the entire library (so hopefully you can understand my interest in rolling my own).
_________________
I've coded about 17 different implementations of Pong. It's the game dev's "hello, world".
DualScheme - Scheme Interpreter for DS

#78211 - qw3rky - Wed Apr 05, 2006 11:22 pm

I've declared all the registers as volatile (InterruptCheck, InterruptEnable, InterruptFlags, MasterInterrupt, etc.). Did you mean: have I declared DTCM volatile? Because if that's the case, no, how would you go about doing that?
_________________
I've coded about 17 different implementations of Pong. It's the game dev's "hello, world".
DualScheme - Scheme Interpreter for DS

#78212 - qw3rky - Wed Apr 05, 2006 11:29 pm

Oh, and if it helps, here are my definitions in my own personal interrupts.h:

Code:

#define MasterInterrupt (* (volatile uint16*) 0x04000208)
#define enableInterrupts()  MasterInterrupt = 1
#define disableInterrupts() MasterInterrupt = 0

#define InterruptEnable (* (volatile uint32*) 0x04000210)
#define InterruptFlags  (* (volatile uint32*) 0x04000214)
#define VBLANK_INTR_ENABLE 0x00000001

#define InterruptHandler (* (volatile uint32*) 0x00803FFC)
#define InterruptCheck   (* (volatile uint32*) 0x00803FF8)

_________________
I've coded about 17 different implementations of Pong. It's the game dev's "hello, world".
DualScheme - Scheme Interpreter for DS

#78514 - qw3rky - Fri Apr 07, 2006 8:49 pm

Okay, I feel a little stupid. Let this be a lesson to the less experienced coders on this board, always triple check your defines and declarations before making a post. It turns out that everything in my code was correct and working fine EXCEPT for one thing. In my constants for Display Status, I defined the 0th bit as V-Blank IRQ Enable instead of the 3rd as it has been stated in both DSTek (http://neimod.com/dstek/) and GBATek (http://nocash.emubase.de/gbatek.htm#lcdiointerruptsandstatus). So, uhh, nothin' to see here folks.

Here was my code before:
Code:

/* --- Display Status --- */
#define DisplayStatus (* (volatile uint16*) 0x04000004)

/* bit 0, vertical blank interrupt enable */
#define VBLANK_INTR_REQUEST 0x00000001  // WRONG!


and here's my code now:
Code:

/* --- Display Status --- */
#define DisplayStatus (* (volatile uint16*) 0x04000004)

/* bit 3, vertical blank interrupt enable */
#define VBLANK_INTR_REQUEST 0x00000008


Now I am well on my way towards coding up a more descriptively named (though maybe a bit verbose) library for the DS. Thank you DekuTree for trying to help.
_________________
I've coded about 17 different implementations of Pong. It's the game dev's "hello, world".
DualScheme - Scheme Interpreter for DS