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.

Coding > Interrupt Problem: Nonfunctional on Hardware.

#14201 - Lord Graga - Thu Jan 01, 2004 11:30 pm

Hey all!

It's a long time since I posted a problem, since I have been working with things that I was pretty routinated with (mode 0, sprites, etc).

Anyways, today I decided to duel a bit with interrupts, and finaly: It worked!

But not on real hardware :(

I'm trying to do HBlank.


CODE CHANGED, SEE LATEST CODE FURTHER DOWN!


If anyone could point out what's wrong I would be very happy.


Last edited by Lord Graga on Fri Jan 02, 2004 6:00 pm; edited 1 time in total

#14202 - poslundc - Fri Jan 02, 2004 12:34 am

Hm...

Well, right off the bat I notice that you are using hofs_counter in your enabled ISR without having initialized its value (which doesn't happen until you get into the main loop). Emulators automatically zero variables on declaration, but you may get garbage data on hardware before your variables have been initialized.

It might help if you told us what happened when you try to run it on hardware, versus what you get in emulation.

(Also, I notice from a logical standpoint you are using a u8 to store your hofs_counter but then comparing it to 360 in your ISR, which is outside the range of a u8 (0-255). So something is not kosher there. And this doesn't necessarily invalidate what I said above: your program might still be trying to access illegal values of your sin/cos table because the compiler is going to pad your global u8's to u32's anyway.)

Dan.

#14203 - poslundc - Fri Jan 02, 2004 12:43 am

Also... it's unlikely to be a problem since your ISR is so short, but you really should be compiling it as ARM code and putting it in IWRAM (versus Thumb/ROM which is the default).

Depending on what exactly happens when you try to run it on hardware, it could be symptomatic of your ISR taking too long. It might still work on emulation because the emulator doesn't correctly handle waitstates for ROM access, so it takes fewer cycles than it does on hardware. I ran into this problem when my HBlank ISR was taking too long on hardware (I was actually compiling it as ARM but putting it in ROM - which is about as silly as it gets - but it still worked just fine in emulation).

Again, more details about what goes wrong when you try it on hardware might help.

Dan.

#14204 - sajiimori - Fri Jan 02, 2004 12:57 am

Quote:

Well, right off the bat I notice that you are using hofs_counter in your enabled ISR without having initialized its value (which doesn't happen until you get into the main loop). Emulators automatically zero variables on declaration, but you may get garbage data on hardware before your variables have been initialized.

Globals will automatically be initialized to 0 during startup, as per the ANSI C spec.
Code:

REG_IF &= ~1;

Quoth GBATEK:
Quote:

Interrupts must be manually acknowledged by writing a "1" to one of the IRQ bits, the IRQ bit will then be cleared.

So, REG_IF = 1.

Dan is right about u8's. In fact, using anything other than int might be considered premature optimization.

#14208 - Lord Graga - Fri Jan 02, 2004 2:13 am

Thanks all, for pointing it out for me.
I did some small changes in the code according to your ideas/etc.

CODE CHANGED, SEE LATEST CODE FURTHER DOWN!

The most major change is the flags. Setting it to anything but it's old value makes the code kinda jaggy.

I did somethings to test it on GBA (currently only multiboot), and I found out that the GBA wasn't freezing, it simply didn't proceed the interupts (is it one of two r's?).


Last edited by Lord Graga on Fri Jan 02, 2004 5:59 pm; edited 1 time in total

#14216 - pbmtp - Fri Jan 02, 2004 12:41 pm

you should also declare u32 hofs_counter; and u32 vofs_counter; as volatile otherwise the C compiler will try to optimise and not force a reload of this var when reusing them (as this var are modified under Interrupt they should be declraed volatile).

I am using the code decribed by tepples in this post and it is working on real hardware
http://forum.gbadev.org/viewtopic.php?t=2019&highlight=interrupt

hope this help

#14220 - Lord Graga - Fri Jan 02, 2004 5:58 pm

I tried to change it according to Tepples instructions, but still no luck:

Code:
#include "lib/lglib.h"
#include "sincos.h"
#define BIOS_IF (*(u32*)0x03FFFFF8)
#define SPEED 2
int i;
volatile u32 hofs_counter;
volatile u32 vofs_counter;
void Intr_Hblank(void)
{
   unsigned int flags = REG_IF;
   hofs_counter+=SPEED;
   if(hofs_counter==360) hofs_counter = 0;
   REG_BG0HOFS = Sin[hofs_counter]>>5;
   REG_BG0VOFS = Cos[hofs_counter]>>5;
   REG_IF = flags;
   BIOS_IF |= flags;
   REG_IME = 1;
}

void AGBMain()
{
   int n;
   SET_MODE(MODE_0|BG0_ENABLE);
   REG_BG0CNT = BG_COLOR_256|SCREEN_MEM(24);
   for(i=0;i<32;i++) CharMem0[i+32] = 0x0101;
   BGPaletteMem[1] = 0xFFFF;
   BGPaletteMem[2] = 10|10<<5|10<<10;
   for(n=0;n<32;n++)   for(i=0;i<32;i+=2) ScreenMem24[i+n*32+n%2] = 1;

   REG_IME = 0;
   *(u32 *)0x03FFFFFC = (u32)Intr_Hblank;
   REG_DISPSTAT = 1<<4;
   REG_IE = 1<<1;
   REG_IME = 1;

   while(1)
   {
      WaitForVSync();
      vofs_counter+=SPEED;
      if(vofs_counter==360) vofs_counter = 0;
      hofs_counter = vofs_counter;
   }
}

#14884 - sasq - Wed Jan 14, 2004 10:09 am

Why do you write to IME in the irq, and why to 0300FFF8?

If you dont need to handle nesting irqs, you can simply do this in your irq-routine:
SETW(REG_IF, 0xFFFF);

and nothing else, it should work fine.

#14927 - tepples - Wed Jan 14, 2004 8:35 pm

sasq wrote:
Why do you write to IME in the irq

What, if anything, does the BIOS do with IME when an interrupt occurs?

Quote:
and why to 0300FFF8?

Write to 0x0300FFF8 (or 0x03007FF8 or 0x03FFFFF8) so that BIOS IntrWait() can keep up. Many programs use IntrWait() to use less batteries, and IntrWait() requires that the ISR 'or' the contents of IF into its global variable.

Quote:
SETW(REG_IF, 0xFFFF);

But then you'll miss a second IRQ that occurs between reading IF and writing IF. Best is to write what you initially read from IF back to IF.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#14928 - Lord Graga - Wed Jan 14, 2004 8:37 pm

Thanks, all, you have been very helpfull.

I finaly managed to get it to work :D