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.

C/C++ > Interrupt not responding...

#13240 - Burre - Tue Dec 09, 2003 6:55 pm

First of all thanks for helping out last time (with the makefile trouble). Seemed like there was a version conflict between the linkerskripts and not an error within the makefile.

Now to the question at hand...

As I mentioned before I'm swapping from HAM to DKA andhave therefor been forced to manually rebuild some wrappers/API that HAM provided.

Right now I'm trying to get interrupt working.

I have Jeff's crt0.S, but I've disabled his IRQ-handler to build one my self.

This is my code:
Code:

/* irqapi.cpp */

/***************************
 * Includes                *
 ***************************/
#include "irqapi.h"

/***************************
 * Functions               *
 ***************************/
u32 IntrTable[14]; // Function-table

/*****************************************************
 Function: SetupIRQ()
 *****************************************************/
void SetupIRQ()
{
    // Disable interrupts
    REG_IME = 0;

    // Set interrupt proc address (IRQHandler)
    REG_INTERUPT = (u32)&HandleIRQ;

    // Enable interrupts
    REG_IME = 1;
}

/*****************************************************
 Function: HandleIRQ()
 *****************************************************/
void HandleIRQ()
{
   
    void (*funcPtr)();

    // Disable interrupts
    REG_IME = 0;

    if(REG_IF & BIT0) == BIT0)
    {
        // Call Vblank func
        funcPtr = (void(*)())IntrTable[0];
        (*funcPtr)();

        // Reset interrupt (by writing to reg)
        REG_IF |= BIT0;
    }

    /* Continuing the same way with all IRQ */

    }

    // Enable interrupts
    REG_IME = 1;
}

/*****************************************************
 Function: StartIntHandler(u16 type, u32* func)
 *****************************************************/
void StartIntHandler(u16 type, u32* func)
{
    // Disable interrupts
    REG_IME = 0;

    switch(type)
    {
     case INT_TYPE_VBL:
        // Enable V-Blank IRQ.
        M_INTENA_VBL_ENABLE; // Macro, tested and working

        // Enable Display V-Blank IRQ also.
        REG_DISPSTAT |= BIT3;

        // Set IRQ func
        IntrTable[0] = (u32)&func;
     break;

     /* And so fourth for all IRQ */

     default:
     break;
    }

    // Enable interrupts
    REG_IME = 1;
}

/*****************************************************
 Function: StopIntHandler(u16 type)
 *****************************************************/
void StopIntHandler(u16 type)
{
    // Disable interrupts
   REG_IME = 0;

    switch(type)
    {
     case INT_TYPE_VBL:
        M_INTENA_VBL_DISABLE; // Macro, tested and working
     break;     default:

     /* And so fourth for all IRQ */

     break;
    }

    // Enable interrupts
    REG_IME = 1;
}


I know that this issue has been adressed before, but I've read all the prevous threads I could find on the forum and the do not contradict my method. Still, it will not work.

I've also checked the Cowbite spec and followed the instructions within. I've paid extra attention to the "algorithm" described below:
Quote:

So, the basic model for setting up interrupts is:

1. Place the address for your interrupt code at 0x03007FFC.

2. Turn on the interrupts you wish to use
- 0x04000004 (REG_STAT) tells which interrupts the LCD will send
- 0x04000200 (REG_IE) masks which interrupts the BIOS will actually
service(?) I presume that both of REG_STAT and REG_IE must have the correct
bits set for anything to work.
- 0x04000208 (REG_IME) Turns all interrupts on or off.

3. When the interrupt is reached, the code at the address at 0x3007FFC gets
loaded into the CPU. To prevent unwanted errors/behavior, the first thing
this code should do is disable interrupts.

4. To determine what interrupt this is, check the flags in 0x04000202
(REG_IF). Unset the flag by writing a 1 to that bit.

5. Once finished with the service routine, reenable interrupts and execute
a BX LR (*Not* a SUBS PC, LR #4, which is what the BIOS does). The BIOS
will then take over and return your program to where execution left off.


In my main-file I have a call to StartIntHandler(INT_TYPE_VBL,(u32*)&start_screen_vbl_func) to set it up for VBL IRQ.

I've tested my code both in VBA and stepped it through in Insight (5.1.1) using mixed source mode (ASM and C combo) and it does what I expect it to, except that it never make any calls to HandleIRQ().


Please help.
_________________
"The best optimizer is between your ears..."

#13306 - evil saltine - Wed Dec 10, 2003 10:31 pm

Maybe change

Code:
REG_INTERUPT = (u32)&HandleIRQ;

to
Code:
REG_INTERUPT = (u32)HandleIRQ;


I'm not sure.. I think just the name of the function gives the address.. I'm probably wrong but I remember that that's how it worked before.

#13307 - sajiimori - Wed Dec 10, 2003 11:09 pm

They're equivalent.

#13345 - Burre - Thu Dec 11, 2003 3:34 pm

evil saltine wrote:
Maybe change

Code:
REG_INTERUPT = (u32)&HandleIRQ;

to
Code:
REG_INTERUPT = (u32)HandleIRQ;


I'm not sure.. I think just the name of the function gives the address.. I'm probably wrong but I remember that that's how it worked before.


It should work. I think I've already checked it in the debugger. It must be something else. Can't figure out what...
_________________
"The best optimizer is between your ears..."

#13354 - tom - Thu Dec 11, 2003 6:41 pm

you're compiling that stuff as arm code, aren't you ?
HandleIRQ needs to be an arm function, the other functions can be arm or thumb.

#13386 - Burre - Fri Dec 12, 2003 10:22 am

I've tried to compile all the code as -marm -mthumb-interworking but that didn't help.

Secondly why does it need to be arm? I know that the interrupt adress is 32bit but HandleIRQs adress should return a 32bit value anyhow, or?
_________________
"The best optimizer is between your ears..."

#13387 - tom - Fri Dec 12, 2003 11:17 am

afaik the bios expects the function whose address is stored in REG_INTERUPT to be an arm function - it doesn't do a modeswitch.

read more in gbatek.txt (and forget the cowbite specs=).