optimization levels in AVR Studio

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

Hello,

In AVR Studio 4.12 there are 4 optimization levels. Which ones can create reliable HEX files according to your experience? I personally once used the 'Os' optimization level and it created a HEX file which could not work properly! Since then I don't use any optimizations any more.

Best wishes,
Senmeis

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

Quote:
Since then I don't use any optimizations any more.
So your hex code is 10 times larger than necessary, right? :-)

All optimizations create reliable hex files IF you use them properly. And of course you get either larger code or faster code or smaller code depending on which you use.

Anyway it's about time you update to Studio 4.15 and the latest winAvr.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

The usual reason -Os programs don't appear to work correctly is explained in FAQ#1 - both below and in the actual user manual you'll get to if you click on that link...

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

senmeis wrote:
Hello,I personally once used the 'Os' optimization level and it created a HEX file which could not work properly! Since then I don't use any optimizations any more.

Senmeis,
it is a know feature that -O0 (no optimization) can cause problems if you use the math part (-lm) avr-libc. -Os is known to work reliable - debugging of course forces your brain a little more but the program works. Whenever you switch from -O0 to -Os and your program does not run as expected read the signature of Cliff and think what you have forgotten.:shock:

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

i really dont know how to optimization works?i have a program with -02 mode, I switch to -O0 mode, it doesn't work as expected. So, what is difference in optimization modes?

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

Quote:
I switch to -O0 mode,
This is zero optimisation. In this mode the code produced is probably the largest as the compiler will try and generate code as you have written it. Some stuff like _delay_ms (and maybe other stuff) does not work correctly.

The dafault of -Os should produce the smallest code (not necessarily the fastest) but it will rearrange bits of code so they may no longer be as you would expect, code that the optimiser deems as uselless will be thrown away, some functions may be inlined (ie instead of calling a function, the code of the function may be added in several places) a bit of a nightmare for debugging at times.

Then you have 2 more modes, some improve on code speed others on code size.

The C gurus will improve and enlarge on my explanation as soon as they wake up, I'm sure. :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Quote:
The C gurus ... as soon as they wake up

Sort of like waiting for an XMega, isn't it? :?

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org

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

The meaning of -O2 or -O0 (and all the -f options they actually switch on/off) are explained in the user manual:

http://gcc.gnu.org/onlinedocs/gc...

If you installed WinAVR you almost certainly have a copy of this manual on your hard disk somewhere beneath /winavr/doc

Cliff

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

js wrote:
Quote:
Since then I don't use any optimizations any more.
So your hex code is 10 times larger than necessary, right? :-)

All optimizations create reliable hex files IF you use them properly. And of course you get either larger code or faster code or smaller code depending on which you use.

Can you please help me determine why avr-gcc generates erroneous code for the following "dead simple" program when optimization (-Os) is used?

Note: I am an experienced AVR developer (10+yrs) but very new to avr-gcc.

Code that compiles incorrectly:-------------------

#include 
#include 

/*Global Varaibles*/
uint16_t UpdatePWM=0xFF;

/*Main-------------------*/
void main( void ){
uint16_t MainLoopCounter; //loop counter
     
//infinite loop
while(1){
MainLoopCounter+=1;				//increment loop counter
	
//if we have reached 65500
if (MainLoopCounter>=65500){
MainLoopCounter=0;    //reset counter
PORTE.OUT|=0x80;      //Toggle PIN E7
UpdatePWM+=1;         //increment Update Variable
TCC1.CCA=UpdatePWM;  //Set Compare A Value
}

----------------------------------

The compiled code (verified by analyzing the .lss file) completely "optimizes" out the incrementing and checking of MainLoopCounter... it never happens. If optimization is turned off (-O0), the code works correctly, albiet, not very efficiently or elegantly.

A slight change to the program will make it compile correctly, with or without optimization....

Code that compiles correctly:-------

#include 
#include 

/*Global Varaibles*/
uint16_t UpdatePWM=0xFF;

/*Main-------------------*/
void main( void ){
uint16_t MainLoopCounter; //loop counter
     
//infinite loop
while(1){
MainLoopCounter+=1;				//increment loop counter
	
//if we have reached 65500
if (MainLoopCounter>=65500){
MainLoopCounter=0;    //reset counter
PORTE.OUT|=0x80;      //Toggle PIN E7
//UpdatePWM+=1;         //increment Update Variable
TCC1.CCA+=1;        //Set Compare A Value
}
------------------------------------

As a quick glance will reveal, this is not the infamous ISR/main shared variable not declared as volatile problem...

Thank you very much for you help!

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
PORTE.OUT|=0x80; //Toggle PIN E7 

Don't know where PORTE.OUT is being declared. Or for that matter TCC1.CCA. It this Xmega code?

Anyway if you use the CODE button before and after posting the format is maintained

#include 
#include 

/*Global Varaibles*/
/*--------------------------------------------------------------------------*/
uint16_t UpdatePWM=0xFF;


/*Main----------------------------------------------------------------------*/
void main( void ){
	uint16_t MainLoopCounter;			//main loop counter
	
	//infinite loop
	while(1){
		MainLoopCounter+=1;				//increment loop counter
		
		//if we have reached 65500
		if (MainLoopCounter>=65500){
			MainLoopCounter=0;			//reset counter
			PORTE.OUT|=0x80;			//Toggle PIN E7
			UpdatePWM+=1;				//increment Update Variable
			TCC1.CCA+=UpdatePWM;		//Set Compare A Value
		}
	}
}

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I could not get it to compile at all. With a small change as follows it compiled correctly for the Xmega128A1

//#include  //Commented out ******
#include 

/*Global Variables*/
/*--------------------------------------------------------------------------*/
uint16_t UpdatePWM=0xFF;


/*Main----------------------------------------------------------------------*/
int main( void ){                //Changed to int instead of void *******

	volatile uint16_t MainLoopCounter;			//main loop counter		

	//infinite loop

	while(1){
		MainLoopCounter+=1;				//increment loop counter
		
		//if we have reached 65500
		if (MainLoopCounter >=65500)
		{
			MainLoopCounter=0;			//reset counter
			PORTE.OUT |= 0x80;			//Toggle PIN E7
			UpdatePWM += 1;				//increment Update Variable
			TCC1.CCA += UpdatePWM;		//Set Compare A Value
		}
	}
}

Edit I think I see your problem MainLoopCounter never gets incremented. Changing it to volatile it works, don't ask me why, the C gurus will tell you. :lol:

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

John,

Thanks for your quick response.... its very much appreciated.

Yes, this is for an Xmega128a1 device. I also declared MainLoopCounter to be volatile and saw that it worked... but there is absolutely no reason it needs to be volatile. Nothing outside the scope of the main while loop has access/visibility to it. This would imply to me that ANY variable needs to be declared volatile or you don't know that the compiler will do to it.

I really need to understand this, because it really takes my confidence in using avr-gcc way down (being my first try to use it). I will post the problem in the AVR GCC technical forum to see what comes up.

PS:
Thanks for the tip on posting code... This was my first post, so I'm still learning the interface. I will use that the next time!

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

Quote:
I really need to understand this,
This is like trying to understand women.. :wink: The "optimiser" (I call it the Terminator) and I don't get along too well.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

I know this is an old thread.

A thing to note. The operations are done only on SFRs inside it. I think the compiler does not treat SFRs as "valid" variables and hence it thinks MainLoopCounter & UpdatePWM are unimportant.

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

Quote:
I think the compiler does not treat SFRs as "valid" variables and hence it thinks MainLoopCounter & UpdatePWM are unimportant.
It thinks MainLoopCounter is unimportant because it is unimportant. Removing the variable does not change the action of the program. It does change the timing of the loop, but C cares nothing about timing.

UpdatePWM is important, so the optimization did not remove it. And the reason the optimizer knows that it is important is specifically because it affects the value of an SFR variable. So no, your analysis is wrong.

Regards,
Steve A.

The Board helps those that help themselves.

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

My bad. Thanks for correcting me