Hello Expert GCCers...
Can you please help me determine why avr-gcc generates erroneous code for the following "super simple" program when optimization (-Os) is used?
Please Note:
(1) I am an experienced AVR developer (10+yrs) but very new to avr-gcc.
(2) I researched this problem for several days before posting my question... and I still don't understand it.
(3) I have removed all setup/initialization code not necessary to demonstrate the compile problem. I know the program would not be useful as is :)
Here is the problem code for an Xmega128a1:
#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 PWM Var TCC1.CCA=UpdatePWM; //Set Compare A Value } } }
When compiled with optimization turned on (-Os) the MainLoopCounter variable never gets incremented or compared against 65500. The PORTE.OUT register gets updated every single main loop cycle, as does the TCC1.CCA register. This was verified/determined by analyzing the assembly code in the *.lss file.
When compiled with optimization off (-O0), the code compiles functionally correct, albeit not very efficiently for speed or code size.
As small change to the code will make the compile functionally correct with or without optimazation.
Code that compiles correctly:
#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 PWM Var TCC1.CCA+=1; //Set Compare A Value } } }
For testing, I have also declared MainLoopCounter as volatile, and that works, but it shouldn't be declared as volatile... nothing outside the scope of the main while() loop has access/visibility to it. Declaring it as volatile makes the code unnecessarily big and slow with expense calls to SRAM.
As this is my first experience with the gcc compiler, I really need to understand this problem. Am I missing something or is this a serious bug in the compiler? Any help would be GREATLY appreciated.
I am using WinAVR-20100110....
Thanks,
Jim