#45541 - DiscoStew - Sat Jun 11, 2005 9:27 pm
Right now I'm at a point in my GBA project that I'd like to start cleaning up my code for bugs and errors, but before I can do that, I have to fix whatever is the problem with the ISR that I'm working with. It works fine, but when I activate the VBlank, I get almost 60 errors a second, and tons more when I activate the HBlank. I used the ISR example that Cearn used for his demos, which was taken from wintermute's "libgba". I've stripped everything down to just setting up the ISR. Here are the files with the code, both C\C++ and Assembly
"single_ints.s"
"interrupt.h"
"interrupt.c"
"main.c"
The "gba.h" file is just the header that contains all the normal memory registers and stuff. I'm assuming it is a single line in the "single_ints.s" file that is bring up the error, since I get an average of 58 errors a second with just the VBlank interrupt enabled. I've been meaning to work with Assembly more, but things happen, so I haven't a clue abuot what the problem is.
Anyone have any thoughts?
_________________
DS - It's all about DiscoStew
"single_ints.s"
Code: |
@
@ Interrupt switch block @ Taken from wintermute's libgba (www.devkit.tk) @ @--------------------------------------------------------------------------------- .section .iwram,"ax",%progbits .extern IntrTable .code 32 .global IntrMain @--------------------------------------------------------------------------------- IntrMain: @--------------------------------------------------------------------------------- @ Single interrupts support mov r3, #0x4000000 @ REG_BASE ldr r2, [r3, #0x200] @ Read REG_IE and REG_IF and r1, r2, r2, lsr #16 @ r1 = REG_IE & REG_IF ldrh r2, [r3, #-8] @\mix up with BIOS irq flags at 3007FF8h, orr r2, r2, r1 @ aka mirrored at 3FFFFF8h, this is required strh r2, [r3, #-8] @/when using the (VBlank)IntrWait functions add r3, r3, #0x200 ldr r2, =IntrTable ands r0, r1, #1 @ V-Blank Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #2 @ H-Blank Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #4 @ V Counter Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #8 @ Timer 0 Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x10 @ Timer 1 Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x20 @ Timer 2 Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x40 @ Timer 3 Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x80 @ Serial Communication Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x100 @ DMA0 Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x200 @ DMA1 Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x400 @ DMA2 Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x800 @ DMA3 Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x1000 @ Key Interrupt bne jump_intr add r2, r2, #4 ands r0, r1, #0x2000 @ Cart Interrupt strneb r0, [r3, #0x84 - 0x200] @ Stop sound if cart removed (REG_SOUNDCNT_X) loop: bne loop @ Infinite loop if cart removed @--------------------------------------------------------------------------------- jump_intr: @--------------------------------------------------------------------------------- strh r0, [r3, #2] @ Acknowlegde int (will clear REG_IF) ldr r0, [r2] @ Jump to user IRQ process bx r0 @ required for assembling on dkAdv (but not dkARM) .align .pool |
"interrupt.h"
Code: |
// interrupt.h:
// interrupt header file // // (Created: 2003-11, Modified: 2004-05-21, Cearn) #ifndef GBA_INTERRUPT #define GBA_INTERRUPT #include "gba.h" // === CONSTANTS ====================================================== // interrupt enums enum eIntrIndex { INT_VBLANK=0, INT_HBLANK, INT_VCOUNT, INT_TM0, INT_TM1, INT_TM2, INT_TM3, INT_COM, INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3, INT_KEYS, INT_CART }; // === GLOBALS ======================================================== extern fnptr IntrTable[]; // === PROTOTYPES ===================================================== // default interrupts void IntrMain(); // see single_ints.s for definition void int_init(); // Must be called for interrupts to work // advanced interrupt en/disable // NOTE: uses the II_xx enums, not the INT_xx flags void int_enable(enum eIntrIndex eii); void int_disable(enum eIntrIndex eii); #endif // GBA_INTERRUPT |
"interrupt.c"
Code: |
// interrupt.c:
// interrupt implementation file // // (Created: 2003-11, Modified: 2004-05-21, Cearn) #include "interrupt.h" void VBlankInterruptHandler() { }; void HBlankInterruptHandler() { }; void UnusedInterruptHandler() { }; // === CLASSES ======================================================== // used for int_enable_ex and int_disable_ex typedef struct tagINT_SENDER { u16 reg_ofs, flag; } INT_SENDER; // === GLOBALS ======================================================== fnptr IntrTable[] = { VBlankInterruptHandler, // INT_VBLANK HBlankInterruptHandler, // INT_HBLANK UnusedInterruptHandler, // INT_VCOUNT UnusedInterruptHandler, // INT_TM0 UnusedInterruptHandler, // INT_TM1 UnusedInterruptHandler, // INT_TM2 UnusedInterruptHandler, // INT_TM3 UnusedInterruptHandler, // INT_COM UnusedInterruptHandler, // INT_DMA0 UnusedInterruptHandler, // INT_DMA1 UnusedInterruptHandler, // INT_DMA2 UnusedInterruptHandler, // INT_DMA3 UnusedInterruptHandler, // INT_KEYS UnusedInterruptHandler, // INT_CART }; // yeah, yeah, I really should use the registers and defines // I have else where. // NOTE: haven't really tested this very much; if inaccurate, // plz tell me static const INT_SENDER _int_senders[] = { { 0x0004, 0x0008 }, // REG_DISPSTAT, VID_INT_VB { 0x0004, 0x0010 }, // REG_DISPSTAT, VID_INT_VH { 0x0004, 0x0020 }, // REG_DISPSTAT, VID_INT_VC { 0x0102, 0x0040 }, // REG_TM0CNT, TM_INT { 0x0106, 0x0040 }, // REG_TM1CNT, TM_INT { 0x0108, 0x0040 }, // REG_TM2CNT, TM_INT { 0x0102, 0x0040 }, // REG_TM3CNT, TM_INT { 0x0128, 0x4000 }, // REG_SCCNT_L{14} // unsure { 0x00ba, 0x4000 }, // REG_DMA0CNT_H, DMA_INT_ON>>16 { 0x00c6, 0x4000 }, // REG_DMA1CNT_H, DMA_INT_ON>>16 { 0x00d2, 0x4000 }, // REG_DMA2CNT_H, DMA_INT_ON>>16 { 0x00de, 0x4000 }, // REG_DMA3CNT_H, DMA_INT_ON>>16 { 0x0132, 0x4000 }, // REG_P1CNT, KEY_CNT_INT { 0x0000, 0x0000 }, // none }; // === PROTOTYPES ===================================================== // === FUNCTIONS ====================================================== // IntrMain is an asm function in single_ints.s void int_init() { REG_INTMAIN = IntrMain; } void int_enable(enum eIntrIndex eii) { REG_IME=0; const INT_SENDER *is= &_int_senders[eii]; *(u16*)(0x04000000+is->reg_ofs) |= is->flag; REG_IE |= 1 << eii; REG_IME= 1; } void int_disable(enum eIntrIndex eii) { u16 tmp= REG_IME; REG_IME= 0; const INT_SENDER *is= &_int_senders[eii]; *(u16*)(0x04000000+is->reg_ofs) &= ~is->flag; REG_IE &= ~(1 << eii); REG_IME= tmp; } void int_setvcount(u8 Scanline) { u16 tmp = REG_IME; REG_IME = 0; if(REG_DISPSTAT & 0x0020) { REG_DISPSTAT &= ~0xFF00; REG_DISPSTAT |= Scanline; } REG_IME = tmp; } |
"main.c"
Code: |
#include "gba.h" #include "interrupt.h" int main() { int_init(); int_enable(INT_VBLANK); int_enable(INT_HBLANK); while(1); return (0); } |
The "gba.h" file is just the header that contains all the normal memory registers and stuff. I'm assuming it is a single line in the "single_ints.s" file that is bring up the error, since I get an average of 58 errors a second with just the VBlank interrupt enabled. I've been meaning to work with Assembly more, but things happen, so I haven't a clue abuot what the problem is.
Anyone have any thoughts?
_________________
DS - It's all about DiscoStew