0
\$\begingroup\$

I have a problem with below code. The variable loopTimes get reset to 0 after one loop. The program also has a ISR routine for TWI interface which updates the value as shown in the below code.

int main(void){
 //my var
 int loopTimes = 0;

 for(;;){

   if(loopTimes >= 0){ 
      loopTimes--;
      //Do some operations
   }
  // check if twi has data
   if(TWI_has_data()){

   //Read it into buffer
     twi_read_data(rxBuffer,2);
     if(loopTimes == 0){ // set the variable if it has reached zero
       loopTimes = rxBuffer[0];
     }
   }
 }
}

The setup is a ATMEGA 8L on a custom board running at 8 MHZ external crystal, program compiled using Atmel Studio 6 with compiler optimization at level 1. I am not able to find out why the variable gets to zero every time the loop goes through. The problem wont occur if i declare loopTimes outside main loop.

This solves the problem

int loopTimes = 0;
int main(void){
 //my var
 ... Rest of code is same
}

Can someone explain this a little more ?

\$\endgroup\$
  • \$\begingroup\$ Error is in code not shown. \$\endgroup\$ – Turbo J Jul 25 '13 at 7:02
  • \$\begingroup\$ @TurboJ I have updated the question \$\endgroup\$ – srinathhs Jul 25 '13 at 8:10
  • \$\begingroup\$ For full debugging, turn the optimizer off. It may be that sections of code are bring optimized out, especially with local variables (as per the first example). Making the variable global can tell the compiler not to optimize it as it could be being modified elsewhere. \$\endgroup\$ – Dave Jul 25 '13 at 8:23
  • \$\begingroup\$ Is there actual code where "// Do some operations" is commented? \$\endgroup\$ – Rev1.0 Jul 25 '13 at 9:11
  • \$\begingroup\$ @Rev1.0: Yes, I am simply fliping a port pin the # of times specified \$\endgroup\$ – srinathhs Jul 25 '13 at 9:38
4
\$\begingroup\$

I think I found the problem, see code comments:

int main(void){
   int loopTimes = 0;

   for(;;) {

   // compiler knows that this condition MUST be true the first time 
   // it runs, since loopTimes is 0
   if (loopTimes >= 0) { 
      loopTimes--;
   }

   // loopTime is now -1 !

   if(TWI_has_data()) {

       twi_read_data(rxBuffer,2);

       // this condition is NEVER true, because loopTime is -1 and will 
       // never be changed again since there are no further assignments
       if (loopTimes == 0) { 
           loopTimes = rxBuffer[0];
       }
   }
}
}

As a result, the compiler optimizes a whole bunch of code away, because it will never be executed or useful anyway. If the variable is global, the compiler can not make this assumption that easily.

Fix your problem by either changing

if (loopTimes >= 0)

to

if (loopTimes > 0)

or change

if (loopTimes == 0)

accordingly.

\$\endgroup\$
  • 1
    \$\begingroup\$ +1, I posted an answer earlier about the problem but deleted when the OP mentioned moving outside main made a difference, but that's a nice explanation and the change in global / local optimisation is likely to be causing it. \$\endgroup\$ – PeterJ Jul 25 '13 at 12:24
  • \$\begingroup\$ Or possibly make loopTimes an unsigned int \$\endgroup\$ – John U Jul 25 '13 at 13:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.