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 > does vba not count right, or does gcc optimize too much?

#86994 - Ant6n - Sun Jun 11, 2006 7:24 am

Hi,

i have a little issue with a high speed timer on VBA. i am running timer 2 and 3 in count up style with timer 2 in mode 1 (cpu clock speed), and i have an u32 count up everytime timer 3 overflows - to get a general purpose 64bit timer.
everything seems to work fine, but my main loop, which looks like this...:

Code:

    while(1)
   {
        x = time_cycles();
        y = time_cycles();
        sprintf(text,"time %d,  %d \n",x,y);
        agbprint(text);
   }



...prints this:

Quote:

time 108, 108
time 28444, 28500
time 78660, 78660
time 129580, 129740
time 188100, 188100
time 248012, 248012
time 307420, 307800
time 368220, 368220
time 429400, 429780
time 491948, 491948
...


Now, why are some of the numbers the same (which would imply that gcc just optimized the two calls to time_cycles() despite everything being volatile, even the return type of that function), yet others are different?
My suspicion is that the emulator doesnt do timers that well, but i am still puzzled about this?
does anybody know why the loop takes like 30~50K clock cycles; does VBA only allow a print every 1ms or something?
thx

anton

#86995 - poslundc - Sun Jun 11, 2006 8:23 am

A few notes:

1. If you're using "mode 1", the timer will increment every 64 cycles, not every cycle, so you could easily get disparities in some lines but not others.

2. Interrupts take additional processing time, so if one of them is triggered it could be messing with your stuff as well.

3. You might want to make sure you are zeroing out the timer values before turning them on, to be certain that you are getting the full 16-bit scope on them.

4. Perhaps most importantly, VBA is not all that reliable when it comes to cycle-accuracy.

The most likely reason for the delay between loops is because you are using sprintf() to convert from base 2 to base 10, which calls the painfully slow GCC division routine. Still, 30-50K seems awfully steep, so it may be some other VBA-related issue.

Dan.

#87092 - Ant6n - Sun Jun 11, 2006 9:52 pm

ok, emm,

1. I just named it mode1 because the clock cycle multiplier is 1, i have something like this:
#define TMR_MODE1 0
#define TMR_MODE64 1

2. I only have interrupts every 256 seconds

4. Yeah, i think vba decides to count up only every like 100 cycles or so (but then adds 100 cycles)

I dont think sprintf takes that long, because the first... o right, it has to be sprintf.

thank you for the tips.

3. here is my initcode


Code:
/* sets up the timer, but starts at seconds.cycles. notice that
   the higher 8 bits of cycles are ignored (should still give you more than 190 days) */
void time_initat(u32 seconds, u32 cycles){
    if (((cycles & 0xffff) + SAVECYCLES) > 0xffff){
        cycles = (cycles & 0x00ff0000) + 0x010000;
        if (cycles > 0x00ffffff) seconds+= cycles >> 24;
    }                                       // insert padding so that tmr2 doesnt overflow during init
    overflow = seconds >> 8;                // the overflow value comes in increments of 256 seconds
    u16 tim2 = cycles & 0xffff;             // the lower 16 bit of cycles go in timer 2
    u16 tim3 = ((cycles & 0x00ff0000) >> 16)// the lower 8 bit of tmr3 come from cycles...
              +((seconds & 0xff) << 8);     // ..the higher 8 bit from come seconds

    TMR2_CONTROL = 0;       // stop timer 2 so that it cant affect timer 3
    TMR3_CONTROL = 0;       // stop timer 3 so that it doesnt overflow and call an interrupt
    TMR2_COUNT = tim2;      // set up initial values for timers
    TMR3_COUNT = tim3;
    irq_set(IRQ_TIMER3, tmr3overflow, 0);
    TMR3_CONTROL = TMR_COUNTUP | TMR_IRQENABLE | TMR_START;
                            // start timer in countup mode, with irq enabled, initial value will
                            // be tmr3 - it doesnt start yet because timer2 is stopped
    TMR3_COUNT = 0;         // make sure that after overflow timer will be at 0;
    TMR2_CONTROL = TMR_MODE1 | TMR_START; //start timer - SAVECYELCES inserted here
    TMR2_COUNT = 0;         // when timer overflows next time it'll start 0
}