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.

problem with infinite loop

Other Parts Discussed in Thread: CC430F6137

Hi,

 

when compiling this program (for testing the timer A0 on cc430f6137) with msp430-gcc 4.4.5 there is a problem. It seems as if the controller hangs up. According to the debugger (mspdebug, also used for flashing the controller) the Timer0_Start doesn't jump back to main(). I tried some combinations and it looks like the instruction/ function call before the infinite-loop  isn't executed correctly. When adding code into the loop the controller hangs there, so the loop i executed only once. I compiled with -O0, so I don't think the compiler is optimizing someting imporant away. Do you see any problems?

 

#include <cc430x613x.h>
#include <signal.h>



int Timer0_Start(uint16_t ticks)
{   
 
                     
 
    // Clear and start timer now   
    // Continuous mode: Count to 0xFFFF and restart from 0 again - 1sec timing will be generated by ISR
    TA0CTL   |= TASSEL0 + MC1 + TACLR;          
 
    TA0CTL |= MC_2;  
    // Delay based on current counter value
     TA0CCR0 = TA0R + ticks;
 
    // Reset IRQ flag    
    TA0CCTL0 &= ~CCIFG; 
              
    // Enable timer interrupt    
    TA0CCTL0 |= CCIE;

return 0;
}

//prints 'h' on the display
void print()
    {   
         unsigned char * lcdmem;

        // Clear entire display memory
        LCDBMEMCTL |= LCDCLRBM + LCDCLRM;

        // LCD_FREQ = ACLK/16/8 = 256Hz
        // Frame frequency = 256Hz/4 = 64Hz, LCD mux 4, LCD on
        LCDBCTL0 = (LCDDIV0 + LCDDIV1 + LCDDIV2 + LCDDIV3) | (LCDPRE0 + LCDPRE1) | LCD4MUX | LCDON;

        // LCB_BLK_FREQ = ACLK/8/4096 = 1Hz
        LCDBBLKCTL = LCDBLKPRE0 | LCDBLKPRE1 | LCDBLKDIV0 | LCDBLKDIV1 | LCDBLKDIV2 | LCDBLKMOD0;

        // I/O to COM outputs
        P5SEL |= (BIT5 | BIT6 | BIT7);
        P5DIR |= (BIT5 | BIT6 | BIT7);

        // Activate LCD output
        LCDBPCTL0 = 0xFFFF;  // Select LCD segments S0-S15
        LCDBPCTL1 = 0x00FF;  // Select LCD segments S16-S22

        // LCD_B Base Address is 0A00H page 30 y in SALS554 document
        // show 'h'
        lcdmem     = (unsigned char *)0x0A21;
        *lcdmem = (unsigned char)(*lcdmem | (BIT2+BIT1+BIT6+BIT0));
       
    }

interrupt (TIMER0_A0_VECTOR) foo(void)
{
    print();
}

interrupt (TIMER0_A1_VECTOR) bar(void)
{
    print();
}

int main()
{   
    Timer0_Start(5);

//wait for interrupts
    while(1)
    {
    }
    return 0;
}

  • I think your code has many problems.

    (a) GIE was never set.

    (b) TIMER0_A1 ISR did not clear the interrupt flag.

    (c) The |= operator usage is questionable.

    (d) Placement of pin control statements is questionable.

    (e) print() has no effect after used once. LCD always show 'h' after the first call.

     

  • blablabla said:
    According to the debugger (mspdebug, also used for flashing the controller) the Timer0_Start doesn't jump back to main().

    Unlikely with this code.

    A typical error is to not clear the IFG bit inside the TIMER_A1_VECTOR ISR. This causes an endless ISR loop. However, you do not enable an interrupt for TIMER0_A1_VECTOR and TIMER0_A0_VECTOR will clear its IFG bit automatically (it is somewhat unique in this, as there is only one single trigger for this vector)

    Nevertheless, since you never enable interrupts by setting GIE ( BIS_SR(GIE); or similar), none of the ISR will ever be called. Your code should run through Timer0_Start(), return to main and then loop endlessly inside teh while loop.

    However, you did not disable the WDT nor do you trigger it, so maybe what the debugger sees is that the MSP resets due to WDT timeout. (mspgcc3 did disable the WDT in the startup code, but I think this has been removed later, as it is not a good idea to disable the WDT without the user knowing or controllign this. Sometimes you need the WDT always on.)

    As OKY already mentioned,

    blablabla said:
        TA0CTL   |= TASSEL0 + MC1 + TACLR;        
        TA0CTL |= MC_2;
    is questionable. |= only sets but never clears bits. However, MC1 is equal to MC_2, so it doesn't hurt in this case. Only in this case.

    Anyway, you already reset TAR to 0 by setting TACLR bit. No need to assign TA0R+ticks to TACCR0. just 'ticks' is enough and doesn't waste another clock cycle, as TA0R is always 0 at this point.

     

     

  • Thanks! Enabling Interrupts and disabling the WDT helped ;)  Nevertheless my debugger seems to be buggy, it doesn't like empty loops and doesn't jump into interrupt routines... But the (test)program works correctly.

     

  • empty loops may be optimized away bvy the compiler. From the compiler view they don't have any significance except wasting time and space. The compiler does not know that wasting time is maybe exactly what you want. If it is, use the __delay_cycles(x) intrinsic instead. It tells the compiler that you want to wast a given number of CPU cycles and will generate the proper code.

    If the loop has been optimized away, the debugge rwon't find it in the device and will not step through it or place a breakpoint on it as it simply isn't there.

    Also, you must knwo the way the CPU works and the debugger works, to explain some things that are strange at first. The CPU fetches the next isntruction while executing the current one, if the current one does not require a memory write. Since breakpoints are triggered when the instruction is fetched, the breakpoint is triggered during execution of the previous one.
    So if you set a breakpoint in an ISR and one directly after entering LPM (or setting GIE, with interrupts pending), the breakpoint in main will be triggered before the breakpoint in the ISR, even if the ISR will be executed first. This is because of the pipelined structure of the processor core. It up to you to know this and place the breakpoints on proper places. :)

**Attention** This is a public forum