LPC4088 resets after wakeup from power down in some cases

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC4088 resets after wakeup from power down in some cases

1,574 Views
mettiu78
Contributor I

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

Labels (2)
Tags (2)
0 Kudos
4 Replies

988 Views
mettiu78
Contributor I

At the subsequent power up, bit 5 of the RSID (Reset Source Identification register) is set, that means LOCKUP. This, as I see from the Cortex M4 knowledge base is due to a fault during the execution of the NMI (not used) or Hardfault handler; the latter one being a simple while(1) loop as in cr_startup_lpc407x_8x..c.

According to the Cortex-M4 hardfault might be caused by a forced hard fault (an escalation of faults) or a bus fault on a vector table read during the processing of exception (infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/Cihdjcfc.html)

However I found a workaround by placing the code of the GPIO ISR (see my previous post above) in the boot area and temporarily redirect the respective vector to that. This way it works: the device glides into powerdown then when I push the P2.1 button it wakes up as expected. However, the mechanism that causes the issue is still unclear to me.

Any idea (possibly from the NXP support team) ?

Matteo

0 Kudos

988 Views
Carlos_Mendoza
NXP Employee
NXP Employee

Hi Matteo,

Have you confirmed that the relocated vector table is pointing to the correct address that corresponds to the GPIO ISR in your application? You can check the actual address of the GPIO IRS function in the *.map file. About your workaround, are you just changing the GPIO ISR address in the vector table to point to an address located in the bootloader section instead of an address in the application section?

Best Regards,
Carlos Mendoza
Technical Support Engineer

0 Kudos

988 Views
mettiu78
Contributor I

Hi Carlos,

first of all thank you for your reply.

Yes, I checked the actual address of the GPIO ISR. Here is what I get (project set with APP section starting at 0x00008000):

From my .MAP file I see:

 .text.GPIO_IRQHandler
                0x00021cc4       0x94 ./COMMON_LOC/APP_SRC/Application/lowpower_app.o
                0x00021cc4                GPIO_IRQHandler

and from the respective .LSS file, the g_pfnVectors section:

00008000 <g_pfnVectors>:
    8000:    c0 ff 00 10 95 81 00 00 29 82 00 00 31 82 00 00     ........)...1...
    8010:    39 82 00 00 41 82 00 00 49 82 00 00 00 00 00 00     9...A...I.......
    ...
    802c:    51 82 00 00 59 82 00 00 00 00 00 00 61 82 00 00     Q...Y.......a...
    803c:    61 5e 02 00 71 82 00 00 71 82 00 00 65 0b 02 00     a^..q...q...e...
    804c:    71 82 00 00 71 82 00 00 8d 31 02 00 71 82 00 00     q...q....1..q...
    805c:    71 82 00 00 71 82 00 00 71 82 00 00 71 82 00 00     q...q...q...q...
    806c:    b9 0d 02 00 71 82 00 00 71 82 00 00 71 82 00 00     ....q...q...q...
    807c:    71 82 00 00 71 82 00 00 71 82 00 00 71 82 00 00     q...q...q...q...
    808c:    71 82 00 00 71 82 00 00 71 82 00 00 71 82 00 00     q...q...q...q...
    809c:    71 82 00 00 71 82 00 00 71 82 00 00 71 82 00 00     q...q...q...q...
    80ac:    71 82 00 00 71 82 00 00 71 82 00 00 71 82 00 00     q...q...q...q...
    80bc:    71 82 00 00 71 82 00 00 71 82 00 00 71 82 00 00     q...q...q...q...
    80cc:    71 82 00 00 71 82 00 00 71 82 00 00 c5 1c 02 00     q...q...q.......
    80dc:    71 82 00 00 71 82 00 00                             q...q...

where the least-significant bit of the GPIO vector (whose offset is 0xD8) is 1 indicating that the exception handler is in Thumb code.. so I believe it is correct, yet it doesn't work.

About your workaround, are you just changing the GPIO ISR address in the vector table to point to an address located in the bootloader section instead of an address in the application section?

-> YES, I change the GPIO ISR address in the APP (= relocated at 0x00008000) vector table to an address in the bootloader section where I placed the ISR, so it is run from flash..

I also tried relocating the vector to RAM keeping the code in the flash APP area, and also I tried the __RAMFUNC to run the GPIO ISR from RAM (both RamPeriph32 and RamLoc64, with the vector table either kept in FLASH or in RAM)... None of these has worked. It seems to like the GPIO ISR to be located at low addresses (notice that both RAM banks are at even higher addresses), and not anywhere in its flash area even if I don't understand why. However, I don't like the workaround since I'd rather keep the two flash areas apart .

Best regards,

Matteo

0 Kudos

988 Views
andrew_glen
Contributor I

Hello Matteo,

Did you ever resolve this problem?

I have a project with an LPC4078 and am facing exactly the same problem.

My application starts at 0x8000 (with the bootloader using 0x0000-0x7FFF) and when I wake from sleep with a GPIO or RTC interrupt it immediately resets.

After reducing the Bootloader down in size and starting the application from 0x6000 the reset no longer occurs, the device wakes up fine

Regards,

Andrew.

0 Kudos