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.

can't use __no_operation() or __delay_cycles()

Other Parts Discussed in Thread: MSP430G2553

Hi and hello!

I seem to never get out from these functions, and at this point I've tried everything (i know of) so i'm just gonna put everything on the table. I get no compilation errors or warnings and the rest of the code runs fine. I'm using the latest gcc compiler and i'm flashing the processor with Flasher.exe from the command line with "MSP430Flasher.exe -n msp430g2xx3 -w "main.hex" -v -z [VCC] -m SBW2" (i've also tried putting "-std=c99" at the end of it, with same results).

The full code is here: https://github.com/klaslofstedt/Zigbee_router_relay

Hope you can help me!

#include <msp430g2553.h>
#include <stdint.h>

enum Status { IDLE, READY };
volatile enum Status g_status = IDLE;


#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
    if(g_status == IDLE){
        g_status = READY;
    }
}

void do_this1()
{
    unsigned int ms = 500;
    while(ms > 1){
        P1OUT = (BIT6); // this happens
        __no_operation();
        P1OUT |= (BIT0); // this happens
        ms--;
    }
}

void do_this2()
{
    unsigned int ms = 500;
    while(ms > 1){
        P1OUT = (BIT6); // this happens
        __no_operation();
        ms--;
    }
    P1OUT |= (BIT0); // this is not happening
}

void do_this3()
{
    P1OUT = (BIT6); // this happens
    __delay_cycles(950);
    P1OUT |= (BIT0); // this happens, however i don't know if there is an actual delay
}

void do_this4()
{
    P1OUT = (BIT6); // this happens
    __delay_cycles(990);
    P1OUT |= (BIT0); // this is not happening
}

int main(void) 
{
    // stop watchdog
    WDTCTL = WDTPW | WDTHOLD;
    
    // 1 MHz
    DCOCTL = 0;                               
    BCSCTL1 = CALBC1_1MHZ;                    
    DCOCTL = CALDCO_1MHZ;
    
    // init leds
    P1DIR = (BIT0 | BIT6);
    P1OUT =~ (BIT0 | BIT6);

    // enable UART + interrupt
    P1SEL = (BIT1 | BIT2);
    P1SEL2 = (BIT1 | BIT2); 
    UCA0CTL1 = UCSWRST; 
    UCA0CTL1 |= UCSSEL_2;                     // SMCLK
    UCA0BR0 = 104;                            // 1MHz 9600
    UCA0BR1 = 0;                              // 1MHz 9600
    UCA0MCTL = UCBRS0;                        // Modulation UCBRSx = 1 
    UCA0CTL1 &= ~UCSWRST; 
    IE2 |= UCA0RXIE;                           //Enable USCI_A0 RX interrupt
    __bis_SR_register(GIE);
    
    for(;;) 
    {
        if(g_status == READY){
            // Comment away three of them so only one run at the time
            do_this1();
            do_this2();
            do_this3();
            do_this4();
            g_status = IDLE;
        }
    }
}
  • You seem to have unbalanced { and } in your USCI ISR.

    Beside that, the USCI was never enabled and it will never generate an interrupt to trigger that ISR.

    Your g_status will be initialized to be IDEL and stay that way forever. Thus do_this is never entered. You can never get out of somewhere if you never get in to that place to begin with ;)

  • Yeah i see now i messed up the {} but the isr is enabled in main and the enum works fine. It reads one byte (removed for increased readability) before going IDLE again. However this is not the issue, i KNOW i enter do_this() and i KNOW it gets stuck in both cases, but i can't figure out why. 

  • user3816116 said:
    ... i KNOW i enter do_this() and i KNOW it gets stuck in both cases ...

    I have to agree that you might think you KNOW, but I do not think you do. 

  • I wanted to focus on what didn't work in the first post, and remove what i knew was correct. I have now edited the first post so i don't leave out any important information.

  • I suggest that you slow it down as shown below in red:

    #include <msp430g2553.h>
    #include <stdint.h>

    enum Status { IDLE, READY };
    volatile enum Status g_status = IDLE;


    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCI0RX_ISR(void)
    {
      if(g_status == IDLE){
        g_status = READY;
      }
    }

    void hold_a_second()
    {
      __delay_cycles(1000000L); //now you see it for a second
      P1OUT =0;
      __delay_cycles(100000L);  //now you don't for 0.1 second
    }

    void do_this1()
    {
      long ms = 100000L;
      while(ms > 1){
        P1OUT = (BIT6); // this happens
        __no_operation();
        P1OUT |= (BIT0); // this happens
        ms--;
      }
      hold_a_second();
    }

    void do_this2()
    {
      long ms = 100000L;
      while(ms > 1){
        P1OUT = (BIT6); // this happens
        __no_operation();
        ms--;
      }
      P1OUT |= (BIT0); // this is not happening ???
      hold_a_second();
    }

    void do_this3()
    {
      P1OUT = (BIT6); // this happens
      __delay_cycles(950000L);
      P1OUT |= (BIT0); // this happens, however i don't know if there is an actual delay
      hold_a_second();
    }

    void do_this4()
    {
      P1OUT = (BIT6); // this happens
      __delay_cycles(990000L);
      P1OUT |= (BIT0); // this is not happening ????
      hold_a_second();
    }

    int main(void)
    {
      // stop watchdog
      WDTCTL = WDTPW | WDTHOLD;

      // 1 MHz
      DCOCTL = 0;
      BCSCTL1 = CALBC1_1MHZ;
      DCOCTL = CALDCO_1MHZ;

      // init leds
      P1DIR = (BIT0 | BIT6);
      P1OUT =~ (BIT0 | BIT6);

      // enable UART + interrupt
      P1SEL = (BIT1 | BIT2);
      P1SEL2 = (BIT1 | BIT2);
      UCA0CTL1 = UCSWRST;
      UCA0CTL1 |= UCSSEL_2; // SMCLK
      UCA0BR0 = 104; // 1MHz 9600
      UCA0BR1 = 0; // 1MHz 9600
      UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1
      UCA0CTL1 &= ~UCSWRST;
      IE2 |= UCA0RXIE; //Enable USCI_A0 RX interrupt
      __bis_SR_register(GIE);

      for(;;)
      {
        if(g_status == READY){
          // Comment away three of them so only one run at the time
          do_this1();
          do_this2();
          do_this3();
          do_this4();
          g_status = IDLE;
        }
      }
    }

  • I really appreciate your effort, but it didn't work either, however I solved it by disable and re-enable the interrupt in main like this:

    for(;;) 
    	{
    		if(g_status == READY){
    			__disable_interrupt();
    			do_thisX();
    			g_status = IDLE;
    			__enable_interrupt();
    		}
    	}

    I'm not sure why this matters, so i'd still like an explanation!

  • Instead of disable and enable interrupt inside main(), could you simply make this modification in your ISr?

    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCI0RX_ISR(void)
    {
        if(g_status == IDLE){
            g_status = READY;
        }
        UCA0RXBUF;
    }

     

  • Interrupts remain pending, even if the ISR has been called (an exception are the Timer CCR0 interrupts and the ADC10 interrupt which are considered as handled when the ISR is called).

    You need to clear the IFG bit that caused the ISR to be called, before you exit the ISR. In case of an RX interrupt, this can be done by clearing RXIFG or by reading RXBUF. Else the ISR will be called again immediately, as soon as you exit it. Over and over again. And main execution will effectively stop.

**Attention** This is a public forum