This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Loop on a global variable that is changed in interrupt



Hi all,

I'm developing an application to understand how to manage global variable, loops and interrupts.

I post a little piece of code, to keep it simple:

 

volatile unsigned int test = 0;

int main( void )

{

  volatile unsigned int i;

  int result;

  // stop watchdog timer to prevent time out reset

  WDTCTL = WDTPW + WDTHOLD;

  // init mcu ports

  init_ports();

  // dco calibration

  for( i = 0; i < 0xFFFF; i++){}            // delay for ACLK startup

  result = TI_SetDCO(TI_DCO_4MHZ);

  if( result == TI_DCO_SET_TO_SLOWEST )     // returned result if DCO registers hit min

  {

    while(1);                               // trap the CPU if hit

  }

  else if( result == TI_DCO_SET_TO_FASTEST )// returned result if DCO registers hit max

  {

    while(1);                               // trap the CPU if hit

  }

  else if( result == TI_DCO_TIMEOUT_ERROR ) // returned result if DCO takes >10000 loops

  {

    while(1);                               // trap the CPU if hit

  }

  // smclk = mclk / 4

  BCSCTL2 = SELM0 | DIVS1;

  // set test global variable to 0

  test = 0;

  // led0 on

  P5OUT &= ~(0x01 << 4);

  // configure timer

  TAR = 0;

  CCTL0 = CCIE;

  CCR0 = 32768;

  // start timer

  TACTL = TASSEL_1 | MC_1;

  // lpm0 + gie

  _BIS_SR(LPM0_bits + GIE);

  // while loop

  while(test < 2);

  // stop timer

  TACTL &= ~MC_1;

  // led1 on

  P5OUT &= ~(0x01 << 5);

  return 0;

}


#pragma vector=TIMERA0_VECTOR

__interrupt void TimerA0_ISR (void)

{

  // increment test global variable

  test++;

  // led2 toggle

  P5OUT ^= (0x01 << 6);

}

 

The behaviour I was expecting from this software was: led0 on, led2 toggle 2 times and the variable test should be = 2, then the while loop on main should break and timer be stopped and led1 turned on.

The behaviour I'm seeing is: led0 on, led2 toggle forever and led 1 never turns on. 

It seems that the while loop in main is looping indefinitely and I can't understand what is wrong.

 

Thanks for your support.

Regards,

Samuele.

  • Samuele Forconi said:

    if( result == TI_DCO_SET_TO_SLOWEST )     // returned result if DCO registers hit min

      {

        while(1);                               // trap the CPU if hit

      }

      else if( result == TI_DCO_SET_TO_FASTEST )// returned result if DCO registers hit max

      {

        while(1);                               // trap the CPU if hit

      }

      else if( result == TI_DCO_TIMEOUT_ERROR ) // returned result if DCO takes >10000 loops

      {

        while(1);                               // trap the CPU if hit

      }

     

     

    HEllo,

    how are You supposed to reach code beyond youre infinite while-loops?

    Am i wrong or are you never gonna reach the Code below?

     

  • Those are only checks in case the DCO calibration function fails. If it succeds the code never reaches those while loops.

    And in fact my led0 ( P5OUT &= ~(0x01 << 4) ) turns on.

  • Hi,

     

    Debug the code with a breakpoint inside the TimerA0_ISR. Based on your description it seems that this interrupted isn’t requested. You are sourcing TimerA with the ACLK clock, check it to see if it’s working properly.

     

    Best Regards,

    AES

  • I'm sorry, I can't use the IAR debugger with my current platform.

    But from what I see, it seems that the interrupt service routine TimerA0_ISR is being executed, because I see my led2 ( P5OUT ^= (0x01 << 6) ) toogling continuously.

    The problem seems to be that inside the main, the variable called "test" seems to be always < 2, even if the ISR is incrementing it every time it is executed.

  • Hi,

     

    I think that I understand now what the problem is. With the instruction  _BIS_SR(LPM0_bits + GIE); the CPU goes off. The CPU only wakes up to run the ISR (and increment the test variable). The CPU never reaches the instruction while(test < 2);

     

    To solve it use _BIS_SR(GIE) (never enters in LPM)

     

    Or if you need to turn off the CPU try to use   _BIC_SR_IRQ(LPM0_bits)  inside the ISR (if variable temp is bigger than 2 exit LPM0)

     

    Best regards,

    AES

  • You're right!

    I've just tested the code removing the LPM0 and now it works.

    Thank you very much for your help.

     

    Best regards,

    Samuele.

**Attention** This is a public forum