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.

MSP430FR5994: Exiting the LPM during debugging without push-button functionality

Part Number: MSP430FR5994

I am using the BOOSTXL-playback as a reference for running an audio detection code on the MSP430FR5994. The MSP used is external and is successfully detected by the launchpad. In the code, I use a switch-case structure to move between the 'DEFAULT' and 'RECORD' modes as available in the BOOSTXL-example. The code for my execution is as follows:

void runApplication(void)
{
    while(1)
    {
        P5IE &= ~BIT7;      // Disable interrupt on P5.7 // vm1010
        P5IE &= ~BIT6;      // Disable interrupt on P5.6
        P5IE &= ~BIT5;      // Disable interrupt on P5.5

        switch(applicationMode)
        {
            case RECORD:
            {
            ...............
            ...............
            break;
            default: break;
            }
        }

        // Toggle app mode
        applicationMode = DEFAULT;

        P6OUT &= ~BIT1;                 // vm1010

        // Set a Switch debounce to 500ms
        __delay_cycles(0.01 * __SYSTEM_FREQUENCY_MHZ__);

        P5IFG &= ~BIT6;                 // Clear interrupt on P5.6
        P5IE |= BIT6;                   // Enable interrupt on P5.6
        P5IFG &= ~BIT5;                 // Clear interrupt on P5.5
        P5IE |= BIT5;                   // Enable interrupt on P5.5
        P5IFG &= ~BIT7;                 // Clear interrupt on P5.7 // vm1010
        P5IE |= BIT7;                   // Enable interrupt on P5.7 // vm1010
        
        // vm1010 mode pin, o/p, high for WoS mode
        P6OUT |= BIT1;  // vm1010

        __bis_SR_register(LPM4_bits + GIE);

        int16_t spectrum[SIGNAL_ROWS1][SIGNAL_COLS1];

        if(FFT_data[1] != 0)
        {
        ..............
        ..............
        }
        
        
        

After uploading the code on the external MSP, when I tried to run this code - the program fails to exit the LPM4 while checking the 'DEFAULT' case of the application. I am aware that this happens due to the ISR being used in this case as it uses the push-button functionality to exit the mode. The code for the ISR is as follows:

#pragma vector=PORT5_VECTOR
__interrupt void port5IsrHandler(void)
{
    switch (__even_in_range(P5IV, P5IV_P5IFG7))
    {
        case P5IV_NONE: break;
        case P5IV_P5IFG0: break;
        case P5IV_P5IFG1: break;
        case P5IV_P5IFG2: break;
        case P5IV_P5IFG3: break;
        case P5IV_P5IFG4: break;
        case P5IV_P5IFG5: break;
        case P5IV_P5IFG6:
            // Toggle record mode
            applicationMode = RECORD;
            //exit LPM mode on exit
            __bic_SR_register_on_exit(LPM4_bits+GIE);
            break;
        case P5IV_P5IFG7:
            // Toggle record mode
            applicationMode = RECORD;
            //exit LPM mode on exit
            __bic_SR_register_on_exit(LPM4_bits+GIE);
            break;
        default:
            break;
   }
}

However, the external circuit I am using has no push-button available on it and thus, I need to exit the LPM4 directly to enable the recording of audio data after the initial checks performed by the MSP430. I am evaluating the entire application using the in-built debugger and in the current scenario - using the Push Button after entering the LPM4 allows the MSP to check the 'if' condition and then enter the 'RECORD' mode. 

While I found various articles describing the possibility of using interrupts to exit the LPM, I am not sure how I can make it work in my case as I don't want to change the structure of the entire code for a single step in the execution. I have also tried the possiblity of using a different ISR but this doesn't work as the push-button functionality is still involved in the execution.

Please let me know if any other information is necessary and I will get back at the earliest.

  • Siddhant,

    Simplest answer here is just have your host MCU toggle a GPIO that's connected to the same GPIO that's tied to the pushbutton. Otherwise, you just need to change the code to interrupt and wakeup the device by whatever you want your trigger to be. 

  • Jace,

    Thanks for the reply. So, ideally I would not like to include a toggling of the GPIO at all. In case of changing the code to interrupt - can I do the redirection in a way that the code branches to check the If Condition which is present immediately after the LPM is entered. I tried using the following:

            __bis_SR_register(GIE);
            __no_operation();

    While the code does move out of the sleep state, this method does not work with : __bis_SR_register(LPM4_bits+GIE). 

    Additionally, in the above case the code keeps looping and never enters the other application mode that is defined. I am not sure what I can try here in terms of changing the interrupt. Would I need to remove the push-button ISR completely and then add the new condition or could they both remain in the code?

    Thanks.

  • Hello,

    If you go into a low power mode, you need a way to get out of it via an interrupt. Almost any interrupt will do (depending on level of LPM as some have restrictions). You will need to decide in your application how you want to  handle that. You can code it however you want.

  • Hello Jace,

    I managed to solve the issue using a timer function where I wake the MSP out of the LPM after 1 ms. However, I want to actually replace this with the digital signal obtained from the microphone. I am unsure as to how this would work as the microphone signal is interfaced to the P5.6 which is configured to the Push-Button switch. How could I use the signal available here as an interrupt to wake my program out of the LPM without using the Push-button functionality? 

  • Hello Siddhant,

    From MCU perspective, it doesn't matter if there is a pushbutton on a pin or just an electrical signal coming in. To interrupt on a pin, you are just looking for a high to low transition or a low to high transition. You can configure this on GPIO register. 

  • Hello,

    Alright, that clears the confusion I had. Based on this, I am uploading my modified code and the functionality I need. Please let me know if you can observe any structural issues with the same:

    void runApplication(void)
    {
        while(1)
        {
            P5IE &= ~BIT7;      // Disable interrupt on P5.7 // vm1010
            P5IE &= ~BIT6;      // Disable interrupt on P5.6
    
            switch(applicationMode)
            {
                case RECORD:
                {
                    volatile uint16_t j;
                    runRecord();
                    amplify_data();
                    fft_init();
                    while(window_number < 64)
                    {
                        fft_cal();
                    }
                    window_number=0;
                    for(j = 1; j < (VECTOR_SIZE / 2); j++)  // vm1010
                    {
                        // vm1010
                        real = fft_res[2 * j] << 2;
                        imag = fft_res[2 * j + 1] << 2;
                        if(real < 0)
                        {
                            real_abs = ~real + 1;
                        }
                        else
                        {
                            real_abs = real;
                        }
                        if(imag < 0)
                        {
                            imag_abs = ~imag + 1;
                        }
                        else
                        {
                            imag_abs = imag;
                        }
                        if(real_abs >= imag_abs)
                        {
                            max = real_abs;
                            min = imag_abs;
                        }
                        else
                        {
                            max = imag_abs;
                            min = real_abs;
                        }
                        mag = max + 3 * (min >> 3);
                        FFT_data[j] = mag << 1;
                    }
    
                    int16_t spectrum[SIGNAL_ROWS1][SIGNAL_COLS1];
                    signed int a,b;
                    for(a=0; a<1; a++)
                    {
                        for(b=256; b>=0; b--)
                        {
                            spectrum[a][b] = FFT_data[b];
                        }
                    }
    
                    matrix_multiply(1, 256, 256, 20, spectrum, weights1, pdt1);
                    matrix_add(1, 20, pdt1, bias1, layer1);
                    act_funct(1, 20, layer1, act1);
    
                    matrix_multiply(1, 20, 20, 10, act1, weights2, pdt2);
                    matrix_add(1, 10, pdt2, bias2, layer2);
                    act_funct(1, 10, layer2, act2);
    
                    matrix_multiply(1, 10, 10, 2, act2, weights3, pdt3);
                    matrix_add(1, 2, pdt3, bias3, layer3);
                    act_out(1, 2, layer3, pred);
    
                    TB0CCR0 = 2000-1;                         // PWM Period, 4kHz --> 250 us --> 2000 (0 to 1999) ticks at SMCLK = 8MHz
                    TB0CCTL6 = OUTMOD_7;                      // CCR6 reset/set
                    TB0CCR6 = 1000;                           // CCR6 PWM duty cycle, 50% duty cycle, 1000 ticks
                    TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR;  // SMCLK, up mode, clear TBR
                    P1OUT |= BIT0;
                    // TA1.1 ---- P1.2 ---- Timer for approx. 3 seconds for buzzer and LED
                    TA1CTL = TASSEL__SMCLK | MC__CONTINUOUS | TACLR | TAIE;        // SMCLK, Continuous mode, clear TAR
    
                    P1OUT &= ~BIT0;
                    TA1CTL &= ~MC;
                    TB0CTL &= ~MC;
                    memset(FFT_data, 0, sizeof(FFT_data));
                    break;
                default: break;
                }
            }
    
            // Toggle app mode
            applicationMode = DEFAULT;
    
            P6OUT &= ~BIT1;                 // vm1010
    
            // Set a Switch debounce to 500ms
            __delay_cycles(0.01 * __SYSTEM_FREQUENCY_MHZ__);
    
            P5IFG &= ~BIT6;                 // Clear interrupt on P5.6
            P5IE |= BIT6;                   // Enable interrupt on P5.6
            P5IFG &= ~BIT7;                 // Clear interrupt on P5.7 // vm1010
            P5IE |= BIT7;                   // Enable interrupt on P5.7 // vm1010
            P6OUT |= BIT1;  // vm1010
    
            __bis_SR_register(LPM4_bits+GIE);
    
        }
    }
    //******************************************************************************
    // Port 5 interrupt service routine
    //      This ISR handles the push button to switch the application
    //      mode.
    //******************************************************************************
    #pragma vector=PORT5_VECTOR
    __interrupt void port5IsrHandler(void)
    {
        switch (__even_in_range(P5IV, P5IV_P5IFG7))
        {
            case P5IV_NONE: break;
            case P5IV_P5IFG0: break;
            case P5IV_P5IFG1: break;
            case P5IV_P5IFG2: break;
            case P5IV_P5IFG3: break;
            case P5IV_P5IFG4: break;
            case P5IV_P5IFG5: break;
            case P5IV_P5IFG6:
                // Toggle record mode
                applicationMode = RECORD;
                //exit LPM mode on exit
                __bic_SR_register_on_exit(LPM4_bits+GIE);
                break;
            case P5IV_P5IFG7:
                //Toggle record mode
                applicationMode = RECORD;
                //exit LPM mode on exit
                __bic_SR_register_on_exit(LPM4_bits+GIE);
                break;
            default:
                break;
       }
    }
    

    runApplication() is the function I call in the main() function of the code. The operation proceeds through the switch case to the applicationMode=DEFAULT, here the microphone interfaced with the MSP430 will provide a signal on the P5.6. I want to use this as the wake up signal from the LPM4.0. Hence, I enter the LPM4.0 at the end of the code and the corresponding ISR denotes the transition for P5.6. I believe the code should run as follows: after disabling the interrupts at the top, the applicationMode=DEFAULT is set and the interrupts are programmed, after this the device would enter the LPM4.0, for wake-up signal I use the low to high transition obtained on the P5.6, subsequently the code goes to the top again and enters the case applicationMode=RECORD. Here, the entire operation is performed and the code eventually arrives at the line with applicationMode=DEFAULT.

    Based on your suggestions and everything I found online, I came up with the code above. A small additional question here is: will the MSP430 exit the LPM4.0 based on the wake-up signal without button press in the 'Debug' mode? Or is the interrupt wake-up routine of the debugger different from that of the normal application. 

    Please let me know if any other information is necessary. Thanks a lot for the suggestions mentioned previously.

    Regards,

    Siddhant

**Attention** This is a public forum