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.

How does any code go around in an infinite loop in the MSP430 MCU (c code wise) ??



Hi,

Happy Holidays to everyone. :-)

I want to know which line  of the code given below  makes the program run in an infinite loop, i want to know exactly how the MCU is able to run the loaded program several times once we load the program, remove the debug-interface and power it  up again.

The code example :

//******************************************************************************
//   msp430x26x Demo - USCI_B0, SPI 3-Wire Master Incremented Data
//
//   Description: SPI master talks to SPI slave using 3-wire mode. Incrementing
//   data is sent by the master starting at 0x01. Received data is expected to
//   be same as the previous transmission.  USCI RX ISR is used to handle
//   communication with the CPU, normally in LPM0. If high, P1.0 indicates
//   valid data reception.  Because all execution after LPM0 is in ISRs,
//   initialization waits for DCO to stabilize against ACLK.
//   ACLK = n/a, MCLK = SMCLK = DCO ~ 1048kHz.  BRCLK = SMCLK/2
//
//   Use with SPI Slave Data Echo code example.  If slave is in debug mode, P1.1
//   slave reset signal conflicts with slave's JTAG; to work around, use IAR's
//   "Release JTAG on Go" on slave device.  If breakpoints are set in
//   slave RX ISR, master must stopped also to avoid overrunning slave
//   RXBUF.
//
//                    MSP430F261x/241x
//                 -----------------
//             /|\|              XIN|-
//              | |                 |  
//              --|RST          XOUT|-
//                |                 |
//                |             P3.1|-> Data Out (UCB0SIMO)
//                |                 |
//          LED <-|P1.0         P3.2|<- Data In (UCB0SOMI)
//                |                 |
//  Slave reset <-|P1.1         P3.3|-> Serial Clock Out (UCB0CLK)
//
//
//  B. Nisarga
//  Texas Instruments Inc.
//  September 2007
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
//******************************************************************************
#include  <msp430x26x.h>

unsigned char MST_Data,SLV_Data;

void main(void)
{
  volatile unsigned int i;

  WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer
  if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
  {  
    while(1);                               // If calibration constants erased
                                            // do not load, trap CPU!!
  }    
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
  DCOCTL = CALDCO_1MHZ;
  for(i=2100;i>0;i--);                      // Wait for DCO to stabilize.
                                       
  P1OUT |= 0x02;                             // P1 setup for LED and slave reset
  P1DIR |= 0x03;                            //
  P3SEL |= 0x0E;                            // P3.3,2,1 option select
  UCB0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    //3-pin, 8-bit SPI master
  UCB0CTL1 |= UCSSEL_2;                     // SMCLK
  UCB0BR0 = 0x02;                           // /2
  UCB0BR1 = 0;                              //
  UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  IE2 |= UCB0RXIE;                          // Enable USCI_A0 RX interrupt

  P1OUT &= ~0x02;                           // Now with SPI signals initialized,
  P1OUT |= 0x02;                            // reset slave

  for(i=50;i>0;i--);                        // Wait for slave to initialize

  MST_Data = 0x001;                         // Initialize data values
  SLV_Data = 0x000;                         //

  UCB0TXBUF = MST_Data;                     // Transmit first character

  _BIS_SR(LPM0_bits + GIE);                 // CPU off, enable interrupts
}

#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCIA0RX_ISR (void)
{
  volatile unsigned int i;

  while (!(IFG2 & UCB0TXIFG));              // USCI_B0 TX buffer ready?
  if (UCB0RXBUF==SLV_Data)                  // Test for correct character RX'd
    P1OUT |= 0x01;                          // If correct, light LED
  else
    P1OUT &= ~0x01;                         // If incorrect, clear LED

  MST_Data++;                               // Increment data
  SLV_Data++;
  UCB0TXBUF = MST_Data;                     // Send next value; "TX/RX of master happens here"

  for(i=30;i>0;i--);                        // Add time between transmissions to
}                                           // make sure slave can keep up

Please let me know the line, because of which the program runs again and again. Thanks.

  • There's a couple of potentially infinite loops in your code:

    janmay b c said:
      if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
      {  
        while(1);                               // If calibration constants erased
                                                // do not load, trap CPU!!
      }    

    Your own comment describes exactly what will cause the CPU to get into that one!

    janmay b c said:
      while (!(IFG2 & UCB0TXIFG));              // USCI_B0 TX buffer ready?

    That loop is potentially infinite if the USCI_B0 TX buffer somehow gets stuck in the "not ready" state

    because of which the program runs again and again

    That's not because of any line in your program - but becuase of a missing line from your program!

    When you write a program for a PC or suchlike, your main() function is called by the operating system, and returns to the operating system when it exits.

    On a small microcontroller such as an MSP430 where you have no operating system, there is nothing to return to if main() exits - so you need to ensure that main() never exits!

    If main() does exit, the system will effectively crash, and restart; hence the program will appear to keep re-running - as you observe.

    You could watch this happening in the debugger.

    Quite possibly, at the end of main(), the CPU will just keep fetching instructions from flash until it reaches the end of flash, and wraps around to the start of the flash again...

  • Thanks for the quick response Andy, yes, i will make  sure that main never exits.

    best wishes

    janmay

  •  Hi Janmay, this program has many thing to be corrected, delay loop are bad programming practice if on interrupt service I marked RED, DCO stabilize immediately I mark them yellow, same for USART release from reset. I dont know why some delay added after the USART initiation, green marked.

    Correct transmission handling may be interrupt driven or main loop waiting to transmit char.

     Regards

     Roberto

    janmay b c said:

    ...................................... snip ..................

    //  September 2007
    //  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A
    //******************************************************************************
    #include  <msp430x26x.h>

    unsigned char MST_Data,SLV_Data;

    void main(void)
    {
      volatile unsigned int i;

      WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer
      if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)                                     
      {  
        while(1);                               // If calibration constants erased
                                                // do not load, trap CPU!!
      }    
      BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
      DCOCTL = CALDCO_1MHZ;
      for(i=2100;i>0;i--);                      // Wait for DCO to stabilize.
                                           
      P1OUT |= 0x02;                             // P1 setup for LED and slave reset
      P1DIR |= 0x03;                            //
      P3SEL |= 0x0E;                            // P3.3,2,1 option select
      UCB0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB;    //3-pin, 8-bit SPI master
      UCB0CTL1 |= UCSSEL_2;                     // SMCLK
      UCB0BR0 = 0x02;                           // /2
      UCB0BR1 = 0;                              //
      UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
      IE2 |= UCB0RXIE;                          // Enable USCI_A0 RX interrupt

      P1OUT &= ~0x02;                           // Now with SPI signals initialized,
      P1OUT |= 0x02;                            // reset slave

      for(i=50;i>0;i--);                        // Wait for slave to initialize

      MST_Data = 0x001;                         // Initialize data values
      SLV_Data = 0x000;                         //

      UCB0TXBUF = MST_Data;                     // Transmit first character

      _BIS_SR(LPM0_bits + GIE);                 // CPU off, enable interrupts
    }

    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCIA0RX_ISR (void)
    {
      volatile unsigned int i;

      while (!(IFG2 & UCB0TXIFG));              // USCI_B0 TX buffer ready?
      if (UCB0RXBUF==SLV_Data)                  // Test for correct character RX'd
        P1OUT |= 0x01;                          // If correct, light LED
      else
        P1OUT &= ~0x01;                         // If incorrect, clear LED

      MST_Data++;                               // Increment data
      SLV_Data++;
      UCB0TXBUF = MST_Data;                     // Send next value; "TX/RX of master happens here"

      for(i=30;i>0;i--);                        // Add time between transmissions to
    }                                           // make sure slave can keep up

  • Hi  Roberto,

    Thanks for going through the code and for the suggestions.

    Apart from the code, i had one more doubt. Does the MCU send the next 8-bits of data only after there is some sort of acknowledgement from the AD9834.

    Because after running and pausing the program i see the numbers being loaded to UCB0TXBUF(22, 50, C7, etc), BUT UCB0RXBUF just has either a 00 or FF value. Why is this happening?

    You seem to have some experience with the AD9834/33 chip, please let me know how you are able to make it generate the required waveform.

    Thanks

    best wishes

    janmay

  • Andy Neil said:
      while (!(IFG2 & UCB0TXIFG));              // USCI_B0 TX buffer ready?

    That loop is potentially infinite if the USCI_B0 TX buffer somehow gets stuck in the "not ready" state[/quote]And using any kind of busy-waiting inside an ISR perverts the meaning of an ISR (even if TI uses this in some of their sample code - and in these examples, the wait is superfluous too by design)

    Andy Neil said:
    On a small microcontroller such as an MSP430 where you have no operating system, there is nothing to return to if main() exits

    That's not exactly true. Right, there is no OS (usually. There are OS's available for the MSP but that's a perversion of the microcontroller idea (heve you heard of Microsofts .Net for microcontrollers? I thought it's April 1st when I read about it), but normally there is none.

    However, the compiler puts some code around main. Before main to initialize variables and call the constructor of any global C++ class instances, after main to call the desctructor of any golbal C++ class instances. And some compilers just enter LPM4 after leaving main.
    However, this behavior is compiler specific and normally, the programmer should ensure that main never exits (well, what's the purpose of a microcontroller whose code execution ends? There are only a few applications for this, maybe a one-button remote control where the button provides power to run the MCU for a one-time action)

    Andy Neil said:
    Quite possibly, at the end of main(), the CPU will just keep fetching instructions from flash until it reaches the end of flash, and wraps around to the start of the flash again...

    or rather cause a reset due to instruction fetch from vacant memory or other access violations.

  • Dear Sir,

    Thanks for your input, for beginners the TI code examples are the only source of guidance. These kind of discussions will surely help me program better in the future.

    Thanks a lot and a very happy new year to you :-)

    best wishes

    janmay

**Attention** This is a public forum