9 years, 11 months ago.

How to use RTC alarm to wake up from Deepsleep or Power-Down modes ?

Hello,

I'm trying for several days to wake up my mbed from Deepsleep or Power-Down mode with the RTC alarm but it doesn't work. My code is inspired from :

If I try in sleep mode the interrupt works good (the led 4 turn on) but in other modes nothing works. The problem could perhaps be that :

  • the processor could still be in debug mode (how to know if it is still in debug mode ? the Mbed Interface is turned off)
  • the initialisation of the system at the wake-up is wrong. (I use SystemInit() fonction).
  • The RTC doesn't work in deep sleep and power-down modes. (Is there some differences between the LPC1768 original version, rev. A and rev. B ?)
  • ????

Could somebody help me, please.

Here is my code :

Wake-up from deep-sleep or power down mode with RTC

#include "mbed.h"
#include "PowerControl/PowerControl.h"
#include "PowerControl/EthernetPowerControl.h"

//need to install the new Beta library from http://mbed.org/handbook/Beta
//inspired from :
//- http://mbed.org/users/Sissors/code/RTC/ (Erik Olieman)
//- http://mbed.org/users/no2chem/notebook/mbed-power-controlconsumption (Michael Wei)
//- http://mbed.org/forum/bugs-suggestions/topic/434/?page=1#comment-14029 (Jim Hamblen)

//Sorry for the look and organisation of the code. I put ~all in one page for the question.

DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
DigitalOut myled3(LED3);
DigitalOut myled4(LED4);
extern "C" void RTC_IRQHandler(void) __irq;
tm Resettime( void );


//RTC Interrupt function
extern "C" void RTC_IRQHandler(void) __irq
{
    SystemInit();
    myled4=1;                       //Turn on LED 4 on RTC Interrupt
}

int main()
{
    myled1=0;
    myled2=0;
    myled3=0;
    myled4=0;
    int result;

    myled1=1;                       //Turn on LED 1 when program starts
    wait(2);

    result = LPC_SC->RSID;          // Read the source of reset

    if ((result & 0x03 )==0) {      // If reset <> de Power On or reset button => out of debug mode (if Mbed "magic" interface is off)

        myled3 = 1;                 //Turn on LED 3 during this part of program

        tm alarmTime = Resettime(); //reset of alarm time
        alarmTime.tm_sec = 00;      // 0-59   //configure alarm time; as the starting time is initialized at 11:35:50 (see below) the led must turn on after 10s
        alarmTime.tm_min = 36;      // 0-59

        NVIC_DisableIRQ(RTC_IRQn); //Disable IRQs during their configuration

        //Delete all RTC interrupt sources
        LPC_RTC->CIIR = 0;
        LPC_RTC->AMR = 255;
        LPC_RTC->ILR = 0x02;        //Set the RTC in RTCALF mode

        //Set the time of alarm in RTC register

        if ((alarmTime.tm_sec>=0) && (alarmTime.tm_sec<60)) {
            LPC_RTC->ALSEC = alarmTime.tm_sec;
            LPC_RTC->AMR &= ~1;
        } else
            LPC_RTC->AMR |= 1;

        if ((alarmTime.tm_min>=0) && (alarmTime.tm_min<60)) {
            LPC_RTC->ALMIN = alarmTime.tm_min;
            LPC_RTC->AMR &= ~2;
        } else
            LPC_RTC->AMR |= 2;

        if ((alarmTime.tm_hour>=0) && (alarmTime.tm_hour<24)) {
            LPC_RTC->ALHOUR = alarmTime.tm_hour;
            LPC_RTC->AMR &= ~4;
        } else
            LPC_RTC->AMR |= 4;

        if ((alarmTime.tm_mday>=1) && (alarmTime.tm_mday<32)) {
            LPC_RTC->ALDOM = alarmTime.tm_mday;
            LPC_RTC->AMR &= ~8;
        } else
            LPC_RTC->AMR |= 8;

        if ((alarmTime.tm_wday>=0) && (alarmTime.tm_wday<7)) {
            LPC_RTC->ALDOW = alarmTime.tm_wday;
            LPC_RTC->AMR &= ~16;
        } else
            LPC_RTC->AMR |= 16;

        if ((alarmTime.tm_yday>0) && (alarmTime.tm_yday<367)) {
            LPC_RTC->ALDOY = alarmTime.tm_yday;
            LPC_RTC->AMR &= ~32;
        } else
            LPC_RTC->AMR |= 32;

        if ((alarmTime.tm_mon>=0) && (alarmTime.tm_mon<12)) {
            LPC_RTC->ALMON = alarmTime.tm_mon + 1;   //Different definitions
            LPC_RTC->AMR &= ~64;
        } else
            LPC_RTC->AMR |= 64;

        if ((alarmTime.tm_year>=0) && (alarmTime.tm_year<1000)) {
            LPC_RTC->ALYEAR = alarmTime.tm_year + 1900;   //Different definitions
            LPC_RTC->AMR &= ~128;
        } else
            LPC_RTC->AMR |= 128;

        //DOY and DOW register normally not set
        time_t RtcTime = time(NULL);
        LPC_RTC->DOY = localtime(&RtcTime)->tm_yday+1;
        LPC_RTC->DOW = localtime(&RtcTime)->tm_wday;

        //Enable interrupts
        NVIC_EnableIRQ(RTC_IRQn);

        //turn of PLL before deep-sleep or Power-Down mode : see p.14 of http://www.nxp.com/documents/errata_sheet/ES_LPC176X.pdf
        //on my mbed version it seems to be the original version of LPC1768

        LPC_SC->PLL0CON &= ~(1<<1); /* Disconnect the main PLL (PLL0) */
        LPC_SC->PLL0FEED = 0xAA; /* Feed */
        LPC_SC->PLL0FEED = 0x55; /* Feed */
        while ((LPC_SC->PLL0STAT & (1<<25)) != 0x00); /* Wait for main PLL (PLL0) to disconnect */
        LPC_SC->PLL0CON &= ~(1<<0); /* Turn off the main PLL (PLL0) */
        LPC_SC->PLL0FEED = 0xAA; /* Feed */
        LPC_SC->PLL0FEED = 0x55; /* Feed */
        while ((LPC_SC->PLL0STAT & (1<<24)) != 0x00); /* Wait for main PLL (PLL0) to shut down */

        //Define sleep level
        //while(1) {}
        //sleep();
        //DeepSleep();
        //PowerDown();
        DeepPowerDown();

    } else {            // This codes only executes the first time after initial POR or button reset

        myled2=1;       //Turn on LED 2 during this part of program
        wait(2);
        LPC_SC->RSID = 0x0F;  // Clear reset source register bits for next reset// LED3 on to indicate initial reset at full power level
        set_time(1256729750); // Update of RTC time to Wed, 28 Oct 2009 11:35:50 - Also turn on RTC time counter.

        PHY_PowerDown();                        //Disaable mbed ethernet chip
        result = mbed_interface_powerdown();    //Disable of the mbed "magic" interface
        Peripheral_PowerDown(0xFFFF7DFF);       //Turn off all LPC1768 peripheral excepted GPIO and RTC
        NVIC_SystemReset();                     //Software reset to turn off the debug mode
    }
}

//Reset of time variable
tm Resettime( void )  //
{
    struct tm t;
    t.tm_sec = -1;
    t.tm_min = -1;
    t.tm_hour = -1;
    t.tm_mday = -1;
    t.tm_wday = -1;
    t.tm_yday = -1;
    t.tm_mon = -1;
    t.tm_year = -1;

    return t;
}

2 Answers

9 years, 11 months ago.

Depending on your application, I found the LPC1768 was not the best option for low power scenarios, although a great target. I would suggest looking at a different Mbed target if you want sleepy battery/solar powered projects. Erik's deep sleep and wake up for the Freescale platform does perform very well for sub 100uA sleep applications. But you may need to re-configure the clock set up's to use different crystal options for the RTC to work reliably.

Accepted Answer

Thanks Paul for your answer. Bad news for me because my board design is almost finished with the LPC1768 (but at least it doesn't include the mbed "magic" interface that seems to be the main problem to work in power down mode). Based on the datasheet, the LPC1768 seems to be good for low-power application (600nA in Deep Power Down) . I will receive my board in 2-3 weeks and I will give some news on the forum.

posted by Martin Bochud 21 May 2014
9 years, 11 months ago.

This seems like fairly extensive code to get it to work. Granted it was on M0s, maybe M3s are different, but despite NXPs warnings I never had issues with getting them out of powerdown while in debug mode. I for sure can't see a better method to make it happen anyway than your code.

Possibly check current consumption, my own experience (although it will largely depend on the target), is that sleep power consumption is at least as low as deepsleep/powerdown power consumption when in debug mode. So by checking sleep consumption and powerdown you can compare it. Similar you can also check if something changes in power consumption when the interrupt is called. Possibly set the LED before SystemInit is called, then you know if it hangs on that one.

If you try it with sleep, you have exactly the same code only uncommented sleep? Have you tried it with an interruptin, that should also get it out of deepsleep/powerdown (deep powerdown is more limitted).

thanks for your answer Erik. Did you test the wake-up from Deep Power Down or Deep Sleep modes on the LPC1768 without the mbed platform? I'm building my own board without the Mbed "magic" interface but before I wanted to confirm that the RTC wake-up works fine.

posted by Martin Bochud 21 May 2014

I never tested it without the mbed platform, I do have another LPC1768 board laying around, but programming it is always a pita.

Deep powerdown the LPC1768 can have a quite low powerconsumption indeed, but is it also low in deepsleep/powerdown? In general those are alot easier to use, since your program can resume, while deep powerdown requires a reset. It could be tbh, I don't know the number. K20 core M4F I got here barely uses more in powerdown than his M0 brothers and sisters.

posted by Erik - 21 May 2014