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.

MSP432: Hard fault triggered when SCB_SCR_SLEEPONEXIT cleared



Hi

I have observed a strange behaviour on the MSP432. A hard fault is triggered (isr_fault) when the SCB_SCR_SLEEPONEXIT flag is cleared inside an ISR.

Example:

void main(void)
{
    // init code
    [...]

    // enter LPM4
    SYSCTL_SRAM_BANKRET |= SYSCTL_SRAM_BANKRET_BNK7_RET;
    MAP_PCM_gotoLPM3();

    while (1);
}


void isr_p1(void)
{
    uint32_t status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
    MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);

    if (status & GPIO_PIN1)   // switch S1 pressed
    {
        // toggle LED
        LED_TOGGLE(LED_0);

    } else if (status & GPIO_PIN4)  // switch S2 pressed
    {
        SCB_SCR &= ~SCB_SCR_SLEEPONEXIT;
// -> isr_fault() is called after this line } }

  • Hi keepcoding,

    I was able to generate an example from the code you provided that properly exits the LPM after the P1 ISR:

    #include "driverlib.h"
    
    void main(void)
    {
        /* Hold the watchdog */
        WDTCTL = WDTPW | WDTHOLD;
        /* Configuring P1.0 as output and P1.1 (switch) as input with pull-up resistor*/
        /* Rest of pins are configured as output low */
        /* Notice intentional '=' assignment since all P1 pins are being deliberately configured */
        P1DIR &= ~(BIT4);
        P1OUT = BIT4;
        P1REN = BIT4;                           // Enable pull-up resistor (P1.1 output high)
        P1SEL0 = 0;
        P1SEL1 = 0;
        P1IFG = 0;                              // Clear all P1 interrupt flags
        P1IE = BIT4;                            // Enable interrupt for P1.1
        P1IES = BIT4;                               // Interrupt on high-to-low transition
    
        // Enable Port 1 interrupt on the NVIC
        NVIC_ISER1 = 1 << ((INT_PORT1 - 16) & 31);
    
        // enter LPM4
        SYSCTL_SRAM_BANKRET |= SYSCTL_SRAM_BANKRET_BNK7_RET;
        MAP_PCM_gotoLPM3();
    
        while (1)
        	{__no_operation();}
    }
    
    
    void isr_p1(void)
    {
        uint32_t status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
        MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);
    
        if (status & GPIO_PIN4)   // switch S1 pressed
        {
        	SCB_SCR &= ~SCB_SCR_SLEEPONEXIT;        // -> isr_fault() is called after this line
        	P1IFG &= ~BIT4;
    
        }
    }

    Please ensure that you are using the latest TI compiler & version of driverlib.  Inside of msp432_startup_ccs.c also make sure that isr_p1 is externally defined (extern void isr_p1(void);) and that isr_p1 is placed inside of the PORT1 ISR spot of the interrupt vector table.

    Regards, Ryan

  • Hi Ryan

    Thanks for your reply. 

    However, your example suffers from the same issue that I described above. Note that it runs ok after it is programmed, but when the MCU is manually reset after programming, the fault ISR is called when I press the switch. 

    I am using the driver library 2_20_00_08 from Mai 2015. And yes, I have correctly linked p1 ISR in the startup script/vector table. 

    Best,

    keepcoding

  • Hello keepcoding,

    I have further debugged the code I posted and you are correct, the issue still persists.  I apologize for not providing a better code example.  Please use this one instead:

    #include "msp.h"
    int main(void)
    {
        /* Hold the watchdog */
        WDTCTL = WDTPW | WDTHOLD;
        /* Configuring P1.0 as output and P1.1 (switch) as input with pull-up resistor*/
        /* Rest of pins are configured as output low */
        /* Notice intentional '=' assignment since all P1 pins are being deliberately configured */
        P1DIR = ~(uint8_t) BIT4;
        P1OUT = BIT4;
        P1REN = BIT4;                           // Enable pull-up resistor (P1.1 output high)
        P1SEL0 = 0;
        P1SEL1 = 0;
        P1IFG = 0;                              // Clear all P1 interrupt flags
        P1IE = BIT4;                            // Enable interrupt for P1.1
        P1IES = BIT4;                               // Interrupt on high-to-low transition
    
        // Enable Port 1 interrupt on the NVIC
        NVIC_ISER1 = 1 << ((INT_PORT1 - 16) & 31);
    
        // Terminate all remaining pins on the device
        P2DIR |= 0xFF; P2OUT = 0;
        P3DIR |= 0xFF; P3OUT = 0;
        P4DIR |= 0xFF; P4OUT = 0;
        P5DIR |= 0xFF; P5OUT = 0;
        P6DIR |= 0xFF; P6OUT = 0;
        P7DIR |= 0xFF; P7OUT = 0;
        P8DIR |= 0xFF; P8OUT = 0;
        P9DIR |= 0xFF; P9OUT = 0;
        P10DIR |= 0xFF; P10OUT = 0;
    
        /* Configure Port J */
        PJDIR |= (BIT2 | BIT3); PJOUT &= ~(BIT2 | BIT3);
    
        /* PJ.0 & PJ.1 configured for XT1 */
        PJSEL0 |= BIT0 | BIT1;
        PJSEL1 &= ~(BIT0 | BIT1);
    
        /* Starting LFXT in non-bypass mode without a timeout. */
        CSKEY = CSKEY_VAL;
        CSCTL1 &= ~(SELA_M | SELB);
        CSCTL1 |= SELA__LFXTCLK;                // Source LFXTCLK to ACLK & BCLK
        CSCTL2 &= ~(LFXTDRIVE_M);               // Configure to lowest drive-strength    
        CSCTL2 |= LFXT_EN;
        while (CSIFG & LFXTIFG)
            CSCLRIFG |= LFXTIFG;
        CSKEY = 0;
        /* Turn off PSS high-side & low-side supervisors */
        PSSKEY = PSS_KEY_KEY_VAL;
        PSSCTL0 |= SVSMHOFF | SVSLOFF;
        PSSKEY = 0;
    
        /* Enable PCM rude mode, which allows to device to enter LPM3 without waiting for peripherals */
        PCMCTL1 = PCM_CTL_KEY_VAL | FORCE_LPM_ENTRY;
    
        /* Enable all SRAM bank retentions prior to going to LPM3  */
        SYSCTL_SRAM_BANKRET |= SYSCTL_SRAM_BANKRET_BNK7_RET;
        __enable_interrupt();
        SCB_SCR |= SCB_SCR_SLEEPONEXIT;        // Do not wake up on exit from ISR
    
    
        while(1)
        {
    		/* Setting the sleep deep bit */
    		SCB_SCR |= (SCB_SCR_SLEEPDEEP);
    		/* Go to LPM3 */
    		__sleep();
    		__no_operation();
        }
    
    }
    
    /* Port1 ISR */
    void isr_p1(void)
    {
        volatile uint32_t i, status;
        /* Toggling the output on the LED */
        if(P1IFG & BIT4)
            P1OUT ^= BIT0;
    
        /* Delay for switch debounce */
        for(i = 0; i < 10000; i++)
    
        P1IFG &= ~BIT4;
    
        SCB_SCR &= ~SCB_SCR_SLEEPONEXIT;        // -> isr_fault() is called after this line
    
    }
    

    Regards, Ryan

  • Hi Ryan

    Thanks a lot for your help! Your example works perfectly.

    I am still trying to figure out what was causing the problem in my code...

    [edit] Ok, found the problem:  MAP_PCM_gotoLPM3();  was causing the trouble, guess this function does not work properly. Same goes for PCM_gotoLPM3();

    Regards,

    keepcoding

**Attention** This is a public forum