Counter variable doesn't increment

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm evaluating an Xmega Xplained board whose code examples are in AVRGCC. They work fine, but I'm more familiar with ICCAVR, so I'm trying to get them to work with that compiler.

In the snippet below, counter is declared as a volatile unsigned int, and x as an unsigned char initialized to 0 (I've omitted the rest of the code the snippet comes from as I think it's irrelevant and would just make for a longer and more confusing extract).

The nop() is in the AVRGCC code but is unrecognized by ICCAVR, so I commented it out and replaced it with x++ hoping to achieve a similar effect. However, while x gets incremented as expected, counter only goes from 0 to 2 before resetting (both in simulation and emulation). If I compile the code as shown with AVRGCC, counter increments as it should, but AVR Studio won't let me set a breakpoint on the x++ line or let me run-to-cursor on that line, saying it's not a valid source line.

I'm mostly interested in learning what's causing the first issue, though I'm curious about the second, as well. Regarding the latter, my guess would be that, unlike ICCAVR, AVRGCC realizes x isn't used anywhere and omits it from the object code, so there's nothing to break on, but maybe something else is going on.

Thanks from a newb.

while (1)
   {
        LEDPORT.OUTTGL = 0xff;
        // Delay
        for ( counter=0; counter<10000; counter++) 
		{
//			nop();
			x++;
		}
   }
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any human being can see that your code is simply:

// note that not only would counter be pulled out of the loop
// but also it would be removed since it is never used
// counter = 10000;   
while (1)
   {
        LEDPORT.OUTTGL = 0xff;
        x += 10000;
   }

I would guess that the loop takes about 8 instructions. If you are running at 32MHz, this meads your LEDs are flashing at 2MHz.

Young people have very good eyesight. I can not see that fast.

If you want a delay, use or equivalent.
One day ICCAVR will understand the concept of optimisation. If you want to obstruct the optimiser, use the 'volatile' modifier.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Any human being can see that your code is simply:
Unless counter or x are marked as volatile, the optimizer probably sees it as:

while (1)
{
    LEDPORT.OUTTGL = 0xff;
}

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

(The reason that it works for the original gcc code is probably that "nop()" is defined as something like

__asm__ __volatile__ ("nop")

, which would defeat the optimization.)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

the optimizer probably sees it as:

Depends if x is global or local.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Depends if x is global or local.
Not really. It is an endless loop and no function is called within it, so the code flow never leaves that loop. Even if x is global the assignment can (and will) be optimized out.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
Any human being can see that your code is simply:
Unless counter or x are marked as volatile, the optimizer probably sees it as:

while (1)
{
    LEDPORT.OUTTGL = 0xff;
}

OP explicitly stated that counter was volatile.
He also stated that counter never passed 2.
He also stated that simulation and emulation agreed on that point.
The described situation is hard enough to believe that I suspect that OP is mistaken about what he has done.

It's time for OP to make an example small enough to post.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the feedback everyone. I've been away from my PC all day and will continue to be so most of tomorrow. Will post more code over the weekend.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK. I've developed three short programs to illustrate the problem. It appears to be an ICCAVR issue, so I should probably post on their mailing list, but I thought I'd post here, too, just to complete the thread. If someone sees what my problem is, by all means, chime in.

The following two programs execute as expected when compiled with AVRGCC. The only difference is whether the nop() or x++ is commented out:

#include "../avr_compiler.h"
volatile unsigned int counter;

int main( void )
{
   volatile unsigned char x = 0;
   while (1)
   {
        for ( counter=0; counter<10000; counter++) 
		{
			nop();
//			x++;
		}
   }
}

#include "../avr_compiler.h"
volatile unsigned int counter;

int main( void )
{
   volatile unsigned char x = 0;
   while (1)
   {
        for ( counter=0; counter<10000; counter++) 
		{
//			nop();
			x++;
		}
   }
}

The following program does not execute as expected when compiled with ICCAVR. x increments as it's supposed to, but counter goes from 0 -> 1 -> 2 -> 0 -> 1 -> 2 ....

#include 

volatile unsigned int counter;

void main( void )
{
   volatile unsigned char x = 0;
   while (1)
   {
        for ( counter=0; counter<10000; counter++) 
		{
			x++;
		}
   }
}

I should point out that AVRGCC throws a warning that "main is not int" if its return type is void, even though it doesn't return anything (maybe all mains return something in AVRGCC; as I said I'm unfamiliar). ICCAVR throws a warning if it *isn't* void.

Thanks loads for your help, and I apologize for dropping an ICCAVR problem here. Should've done more homework first.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What happens when you write code that actually does something?

Regards,
Steve A.

The Board helps those that help themselves.