I have spent the last couple of evenings trying to get deepsleep() to work as I expect it to on my mbed-LPC11U24. I have hit a few issues that I thought I would report here since they might help others that are trying to do the same.
First I started with the example code that I found here but I modified it to blink LED1 instead of using the LCD.
#include "mbed.h"
InterruptIn wakeup(p14);
DigitalOut led(LED1);
int main ()
{
wakeup.rise(NULL); // Setup rising edge interrupt (no handler function needed)
led = 1;
while (1)
{
deepsleep(); // Deep sleep until external interrupt
led = !led;
}
}
I ran that code on the device when it was only powered on VB with a regulated 3.3V source and a switch connected to p14 with 1k pull-down resistor and when the button was pressed it would short to VB. When I ran the above code in that configuration, it just appeared to hang. At first I thought it was entering deep sleep and not waking up. After some research I figured out that the problem was that it was actually hanging in an exception handler because the mbed SDK deepsleep() function attempts to make a semihost call to the mbed interface chip to disable it. This isn't possible when the device is only powered from VB since the mbed interface chip isn't even powered up in the scenario. This means that the BKPT destined for the interface chip will cause a local exception to be thrown instead.
This new code contains my work around to that issue:
#include "mbed.h"
InterruptIn wakeup(p14);
DigitalOut led(LED1);
// Pulled from mbed SDK sources but removed mbed_interface_disconnect() call
// since that would cause halt when it tried to disable the interface chip
// which isn't powered up when I am powering the device from VB.
void deepsleep(void)
{
// PCON[PD] set to deepsleep
LPC_PMU->PCON = 0x1;
// SRC[SLEEPDEEP] set to 1 = deep sleep
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
// Power up everything after powerdown
LPC_SYSCON->PDAWAKECFG &= 0xFFFFF800;
// wait for interrupt
__WFI();
}
int main ()
{
wakeup.rise(NULL); // Setup rising edge interrupt (no handler function needed)
led = 1;
while (1)
{
deepsleep(); // Deep sleep until external interrupt
led = !led;
}
}
Running this code also leads to a hang where the device never appears to wakeup but I did notice that the device worked differently after running this code where it would take an extra press of the reset button when I plugged in the USB cable to get the interface chip to stop blinking its LED or to even just light it up. This made me think that the device was now entering deep sleep but just not waking up.
I banged my head against the wall with that issue for a few hours and then I became suspicious of this one line in the original sample:
wakeup.rise(NULL); // Setup rising edge interrupt (no handler function needed)
It turns out that calling rise() like this in the current SDK will actually disable the interrupt and not enable it without an interrupt handler. The final version of my code contains a dummy handler that fixes this issue in the sample code:
#include "mbed.h"
InterruptIn wakeup(p14);
DigitalOut led(LED1);
// Pulled from mbed SDK sources but removed mbed_interface_disconnect() call
// since that would cause halt when it tried to disable the interface chip
// which isn't powered up when I am powering the device from VB.
void deepsleep(void)
{
// PCON[PD] set to deepsleep
LPC_PMU->PCON = 0x1;
// SRC[SLEEPDEEP] set to 1 = deep sleep
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
// Power up everything after powerdown
LPC_SYSCON->PDAWAKECFG &= 0xFFFFF800;
// wait for interrupt
__WFI();
}
static void dummyHandler(void)
{
return;
}
int main ()
{
wakeup.rise(dummyHandler); // Setup rising edge interrupt
led = 1;
while (1)
{
deepsleep(); // Deep sleep until external interrupt
led = !led;
}
}
Now the code works as expected. I even measured the current when in deep sleep with this code and the current draw was down to 1.11mA. I suspect that the other people who complained that deep sleep was consuming >=14mA in their tests were actually hitting my first issue where the device wasn't even entering deep sleep.
One other thing I found as I was playing with deep sleep on the LPC11U24 version of the mbed is that it is best to upgrade to the latest mbed interface firmware. Without it I had difficulties getting new code programmed into the target device when it was in deep sleep.
I have spent the last couple of evenings trying to get deepsleep() to work as I expect it to on my mbed-LPC11U24. I have hit a few issues that I thought I would report here since they might help others that are trying to do the same.
First I started with the example code that I found here but I modified it to blink LED1 instead of using the LCD.
I ran that code on the device when it was only powered on VB with a regulated 3.3V source and a switch connected to p14 with 1k pull-down resistor and when the button was pressed it would short to VB. When I ran the above code in that configuration, it just appeared to hang. At first I thought it was entering deep sleep and not waking up. After some research I figured out that the problem was that it was actually hanging in an exception handler because the mbed SDK deepsleep() function attempts to make a semihost call to the mbed interface chip to disable it. This isn't possible when the device is only powered from VB since the mbed interface chip isn't even powered up in the scenario. This means that the BKPT destined for the interface chip will cause a local exception to be thrown instead.
This new code contains my work around to that issue:
Running this code also leads to a hang where the device never appears to wakeup but I did notice that the device worked differently after running this code where it would take an extra press of the reset button when I plugged in the USB cable to get the interface chip to stop blinking its LED or to even just light it up. This made me think that the device was now entering deep sleep but just not waking up.
I banged my head against the wall with that issue for a few hours and then I became suspicious of this one line in the original sample:
It turns out that calling rise() like this in the current SDK will actually disable the interrupt and not enable it without an interrupt handler. The final version of my code contains a dummy handler that fixes this issue in the sample code:
Now the code works as expected. I even measured the current when in deep sleep with this code and the current draw was down to 1.11mA. I suspect that the other people who complained that deep sleep was consuming >=14mA in their tests were actually hitting my first issue where the device wasn't even entering deep sleep.
One other thing I found as I was playing with deep sleep on the LPC11U24 version of the mbed is that it is best to upgrade to the latest mbed interface firmware. Without it I had difficulties getting new code programmed into the target device when it was in deep sleep.