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++ > Keypad Interrupt Handling

#1033 - Vortex - Mon Jan 13, 2003 8:58 pm

I am working on a small program trying to call the "Sleep" mode using some of the GBA BIOS functions.

My problem is I was not able to find any documentation how to implement a user interrupt handler for GBA. The only clue I have is from GBATEK:

Quote:

As shown above, a pointer to the 32bit/ARM-code user handler must be setup in [03007FFCh]. By default, 160 bytes of memory are reserved for interrupt stack at 03007F00h-03007F9Fh


The explanation sounds very obscure - for example I cannot figure out is [03007FFCh] just a pointer to a function or the function code itself starts there. Also are there any special requirements for the interrupt handling function (like saving registers, etc.)

Your help will be appreciated.

Thank you

#1035 - Splam - Mon Jan 13, 2003 10:40 pm

03007FFCh holds a pointer to the irq handler.

Check in your crt0.s you should see something setting it up to point to some code. eg

Code:

        ldr     r1, =INTR_VECTOR_BUF    @ set interrupt address
        adr     r0, intr_main
        str     r0, [r1]


where intr_main is then the irq handler code.

There should be code near that that sets up the stack pointer for irq mode.

The basic irq handler usually included in crt0.s tends to be a case of, check which intterupt has been triggered then vector through a C jump table array to the required C routine. That method is usually slower than necessary but is a good starting point because everything you would need is catered for. Personally I do my interrupt code in ARM and do the handler and the code all in go which saves time (but I'm a speed freak).

If you do have the interupt enabled crt0.s then check for the intr_main function, if you see that then you should also see something like ldr r1, =IntrTable
That is fetching the pointer to the C array of irq routines which would be like this....
Code:

const u32 IntrTable[]  =
{
   VBLANK,
   HBLANK,
   VCOUNT,
   TIMMER0,
   TIMMER1,
   TIMMER2,
   TIMMER3,
   COMUNICATION,
   DMA0,
   DMA1,
   DMA2,
   DMA3,
   KEYBOARD,
   CART
};


You then just define all of those functions like so..
Code:

void VBLANK()
{
   REG_IF |= INT_VBLANK;
      
}

One for each member of the array HBLANK, DMAs etc

That VBLANK code (and corresponding ones for each of the irq types) services the interrupt. You just add what you want to that routine.


Hope that helps some. I'm dragging this stuff from oooold files when I did things the C way so I've probably missed lots out.

#1103 - Vortex - Tue Jan 14, 2003 5:19 pm

Thank you, sir, for the excellent explanation. I think you have a real talent for technical tutorials. If you decide to write a GBA book at some point please let me know - I will be the first one to buy it.

Quote:

Personally I do my interrupt code in ARM and do the handler and the code all in go which saves time (but I'm a speed freak).


Also I am happy that there is at least one "speed freak" left in a world of bloatware and "platform independent" languages :-)