Search code examples
carmembeddedgame-boy-advance

Can you store the memory location of a function into RAM using C?


I've been playing with Game Boy Advance coding in C. For interrupts to work, the address of your interrupt handler routine must be manually copied to RAM location 0x03007FFC. I know how to do this in ARM Assembly but not in C. I was trying something like this:

#define REG_INTERRUPT *(vu32*)0x03007FFC
void irqhandler()
{
    while(1){}
}

int main()
{
    REG_INTERRUPT = &irqhandler();

    while(1){}
    return 0;

}

But it doesn't work. From what I understand about C functions, it seems like C is thinking I'm trying to get the address of the return value of irqhandler (which there is none since it's a void) and that's where the error comes from. How do I tell C that I want the memory location of the function itself?


Solution

    • irqhandler() is wrong, you are calling the function instead of taking its address. You should write irqhandler or the 100% equivalent &irqhandler.
    • Don't use strange home-brewed types like vu32, nobody knows what that means. Use standardized types from stdint.h.
    • You can't assign a function pointer to an integer, they are not compatible types. You need an explicit cast to integer.

    Corrected code:

    #include <stdint.h>
    #define REG_INTERRUPT (*(volatile uint32_t*)0x03007FFCu)
    ...
    REG_INTERRUPT = (uint32_t)irqhandler;
    

    This of course assuming that the underlying hardware supports this and that something valid exists at address 0x3007FFC that expects a 32 bit integer access.

    For details check out How to access a hardware register from firmware?