Matteo Bonaiuti

LPC4088 resets after wakeup from power down in some cases

Discussion created by Matteo Bonaiuti on Sep 27, 2017
Latest reply on Oct 6, 2017 by Matteo Bonaiuti

Hi everybody,

 

my project consists of an application and a secondary bootloader using a LPC4088FBD208.

At the POR, the device runs the bootloader, which checks for the availability of a valid application. If so, it relocates the vector table at the beginning of the application part and jumps there.

The application implements the "Power down" low power mode. Wake up occurs by means of a qualified GPIO interrupt (P2.1) , connected to a pushbutton line.

The bootloader is allocated starting from address 0x00000000 to 0x00004FFF, the application (reflashable by the bootloader using the IAP) starts from 0x00005000 onwards. In this case I experience no issue. Power down is entered correctly, wake up and operations are resumed correctly when I press the wake button, everything works perfectly.

 

Now I have to accommodate more functionalities in the bootloader so I have to yield more space to it, reducing the application room accordingly. 

I tried extending the bootloader space up to 0x00008FFF and placing the application start address at 0x00009000. The rest of the application is left untouched.

Everything works correctly until the devices enters power down. Power down continues to be correctly entered (I see the same consumption I read when there was no issue) but when I press the wake up button the device resets.

I tried  the following:

bootloader up to 0x00004FFF , app starting at 0x00005000 (original project) -> OK

bootloader up to 0x00005FFF , app starting at 0x00006000  -> OK

bootloader up to 0x00007FFF , app starting at 0x00008000  -> ISSUE

bootloader up to 0x00008FFF , app starting at 0x00009000  -> ISSUE

 

Sections location and sizes are modified accordingly in the linker script,  and the vector table is relocated accordingly.

Note that the application part uses around 270kbytes of flash so it is well accommodated in all the four cases, and that it makes extensive use of interrupts from the beginning of execution,  which all work correctly until the issue: this makes me think that I have relocated the vector table correctly in the bootloader just before jumping to the application.

 

Has anybody experienced such behavior?

 

This is the initialization part of the low-power management, which is called by the initialization routine of the application:

 

/* Default: no wakeup event happened */
    WakeupEvent = NO_WAKEUP_EVENT;

 

    /* Power down mode after the execution of a WFI or a WFE instruction */
    SCB->SCR = SCB->SCR | SCB_SCR_SLEEPDEEP_Msk;

 

    /* Configure the allowed low power mode (power-down mode is supported) */
    LPC_SC->PCON |= SC_PCON_PM_POWERDOWN;

 

    /* Disable all rising and falling edge interrupt sources (for every P0.x and P2.x) */
    LPC_GPIOINT->IO0IntEnR = 0;
    LPC_GPIOINT->IO0IntEnF = 0;
    LPC_GPIOINT->IO2IntEnR = 0;
    LPC_GPIOINT->IO2IntEnF = 0;

 

    /* Clear all GPIO port interrupts */
    LPC_GPIOINT->IO0IntClr = MAX_LONG;
    LPC_GPIOINT->IO2IntClr = MAX_LONG;

 

    /* Enable the GPIO interrupt in the NVIC interrupt controller and set the relevant priority (to 24) */
    NVIC_SetPriority(GPIO_IRQn, 24);
    NVIC_EnableIRQ(GPIO_IRQn);

 

then, in the main loop, after some time of keypad inactivity, the following code is executed to go and to resume from power down:

 

/* Enable falling edge interrupt for back pushbutton (P2.1) */
        LPC_GPIOINT->IO2IntClr |= BACK_BTN_MASK;
        LPC_GPIOINT->IO2IntEnF = BACK_BTN_MASK;


        /*----------------------------------------------------------------------*/
        /* Switch to power-down mode (and wait for subsequent wakeup event)     */
        /*----------------------------------------------------------------------*/

 

        /* Deinitialize and de-energize all the peripherals */
        ShutdownAllThePeripherals();

 

        /* Switch to internal RC oscillator */
        Chip_SetupIrcClocking();

 

        /* Update the clock frequency variables according to the currently set clock register values */
        //SystemCoreClockUpdate();

 

        /* Switch to power-down mode (and wait for subsequent wakeup) */

 

        Nop();
        Nop();
        Nop();
        { __asm(" WFI "); }
        Nop();
        Nop();
        Nop();

 

        /* Here begins the wakeup sequence from power down */

 

        /* Global interrupt disabled */
        DisableInterrupt();

 

        /* Clear any low power mode notification flag */
        ClearLowPowerFlags();

  
        /* Switch to the main oscillator */
        Chip_SetupMainClocking();


        /* Restore all the peripherals by powering and re-initializing them back */
        RestoreAllThePeripherals();


        /*----------------------------------------------------------------------*/
        /* Final restoring                                                      */
        /*----------------------------------------------------------------------*/

 

        /* Global interrupt enabled */
        EnableInterrupt();

 

 

the interrupt service routine associated to the wakeup event (falling edge of P2.1) is the following - note that the "voltage dip" interrupt is not enabled therefore it shouldn't cause troubles:

  

/*__interrupt*/ void GPIO_IRQHandler (void)
{

 

    /* If the interrupt occurred during power down then notify a wakeup event and disable further interrupts */
    if ((LPC_SC->PCON & (uint32)(SC_PCON_DPDFLAG | SC_PCON_PDFLAG | SC_PCON_DSFLAG | SC_PCON_SMFLAG)) != 0) {

 

        /* Disable all rising and falling edge interrupt sources (for every P0.x and P2.x) */
        LPC_GPIOINT->IO0IntEnR = 0;
        LPC_GPIOINT->IO0IntEnF = 0;
        LPC_GPIOINT->IO2IntEnR = 0;
        LPC_GPIOINT->IO2IntEnF = 0;

 

        /* Determine the wakeup source */
        if (((LPC_GPIOINT->IO2IntStatF) & VDIP_DETECT_MASK) != 0) {

 

            /* Notify that the wake up has been triggered by a voltage dip */
            WakeupEvent = WAKEUP_FROM_VOLTAGE_DIP;
        }


        /* Wakeup from back button depress */
        else {
            /* A wakeup after back pushbutton pressing has just happened */
            WakeupEvent = WAKEUP_FROM_PUSHBUTTON;
        }

 


    }

 

    /* The interrupt was triggered before actual  power-down */
    else {

 

        /* In the case the interrupt was triggered by a voltage dip recovery before completing the
         power-down leading sequence then signal it to skip the powerdown */

 

        if (((LPC_GPIOINT->IO2IntStatF) & VDIP_DETECT_MASK) != 0) {

 

            /* A voltage dip has been recovered before entering power down */
            DipRecovered = TRUE;

 

            /* Notify that the wake up has been triggered by a voltage dip */
            WakeupEvent = WAKEUP_FROM_VOLTAGE_DIP;

 

            /* Disable the dip recovered interrupt */
            LPC_GPIOINT->IO2IntEnF &= ~VDIP_DETECT_MASK;
        }
    }

 

    /* Clear all GPIO port interrupts */
    LPC_GPIOINT->IO0IntClr = MAX_LONG;
    LPC_GPIOINT->IO2IntClr = MAX_LONG;

 

} /** GPIO_IRQHandler */

 

The project uses the NXP libspifi and the emWin graphic library.

 

Thank you for your help and for any hint/ideas.

 

Sincerely,

Matteo

Outcomes