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.

MSP430F5335: Problem with nested interrupts and LPM

Part Number: MSP430F5335


I am observing an issue with nested interrupts. I know I should avoid using nested interrupts but believe me, in this case there was no other choice.

This is the scenario:

- MSP is in Low Power Mode 3 (LPM3).

- RTC interrupt occurs.

- Inside the RTC's ISR, I set GIE to enable nesting.

- TA0 (or others) interrupts before returning from RTC's ISR (nesting).

- Inside the TA0 I change the Status Register (SR) bits to exit LPM (using __bic_SR_register_on_exit).

- The MSP does not respond anymore.

Note: If I don't try exiting LPM from the nested interrupt, the MSP behaves as expected.

In the following thread, Jens-Michael Gross, mentioned that "the nested interrupt cannot exit LPM".

https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/349661?Nested-interrupts-and-jump-table 

I understand the SR and PC are saved in the stack twice. Then, at the end of the nested interrupt ISR, the latest SR saved in the stack is modified (to exit LPM) and retrieved, then the PC will retrieved an instruction from the RTC's ISR and will continue executing the RTC's ISR. Then, at the end of the RTC's ISR, the SR will be retrieved again form the stack with the values saved before entering the RTC's ISR. For that reason, the MSP will not go out form LPM in that moment.

But, what I don't understand is why the MSP doesn't wake up at all, later when another interrupt occurs and there is no nesting enabled.

I would really appreciate any inputs on this matter.

Thanks in advance.

  • I don't have an F5335. When I run this program on an F5529 (Launchpad), it functions as expected.

    I'm not sure what you and I are doing differently.

    ///
    //  nest-5529
    //  If nesting works, LED1 blinks 2Hz, LED2 0.5Hz
    //
    #include <msp430.h> 
    #define HZ  1000000UL           // 1MHz from reset
    int
    main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	P4OUT &= ~BIT7;             // Launchpad LED2
    	P4DIR |=  BIT7;
    	P1OUT &= ~BIT0;             // Launchpad LED1
    	P1DIR |=  BIT0;
    	//  Blink at 2Hz from 4 interrupts/sec
    	TA0CCR0 = HZ/4/4;           // HZ/4 with ID=2
    	TA0CCTL0 = CCIE;
    	TA0CTL = TASSEL_2 | ID_2 | MC_1 | TACLR; // SMCLK/4, Up [,Clear]
    	//  RTC in counter mode, interrupt via PS1 1/sec
    	RTCPS0CTL = RT0PSDIV_7|(0*RT0PSHOLD);   // ACLK/256
    	RTCPS1CTL = RT1SSEL_3|RT1PSDIV_6|(0*RT1PSHOLD)|RT1IP_6|RT1PSIE; // PS0/128, count+interrupt
        RTCCTL0 = 0;
        RTCCTL1 = (0*RTCHOLD); // Run
    	__enable_interrupt();
    	while (1)
    	{
    	    LPM3;
    	}
    	/*NOTREACHED*/
    	return 0;
    }
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void
    TA0_0_ISR(void)
    {
        P1OUT ^= BIT0;                  // LED1
        __bic_SR_register_on_exit(LPM3_bits);  // Wake up half the time
        return;
    }
    #pragma vector=RTC_VECTOR
    __interrupt void
    RTC_ISR(void)
    {
        (void)RTCIV;                    // We know it's PS1
        P4OUT ^= BIT7;                  // LED2
        __bis_SR_register(GIE);         // Allow nesting
        __delay_cycles(3*HZ/4);         // 3/4-second visibly blocks TA0 without GIE
        return;
    }
    

  • Hi John,

    Can you please post the part of the code where you go into LPM?

    To clear the SR inside the TimerA ISR has only an effect if the interrupt of your TimerA appeared while you were in LPM. If it would be executed as a nested interrupt your device will anyway return into AcitveMode because it came from RTC right?

    So either you cause some kind of stack overflow or you might return into AM within your main loop and do not catch the CPU in a loop. These are my initial ideas if you say it does not respond anymore.

**Attention** This is a public forum