Mbed-os: Deep sleep mode on DISCO_L072CZ_LRWAN1

Created on 13 Aug 2020  路  16Comments  路  Source: ARMmbed/mbed-os

Description of defect


We are trying to test 'Deep sleep mode' on our target.
We think that target must entry to deep sleep mode after calling sleep() function.
But it printed a message "Toggle" every 2 seconds before button is pushed and released.
It looks like the target entry to deep sleep mode and directly wake up by something.

For NUCLEO_F429ZI, when we run same code, it works well as intended.

Target(s) affected by this defect ?

DISCO_L072CZ_LRWAN1

Toolchain(s) (name and version) displaying this defect ?

GCC_ARM

What version of Mbed-os are you using (tag or sha) ?


mbed-os-5.15.4

What version(s) of tools are you using. List all that apply (E.g. mbed-cli)

arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 9-2019-q4-major) 9.2.1 20191025 (release)
Python 2.7.17
mbed-cli 1.10.2

How is this defect reproduced ?

Just run main.cpp in my code

#include "mbed.h"

// Blinking rate in milliseconds
#define BLINKING_RATE_MS     2000

DigitalOut      led(LED1, 1);
InterruptIn     button(D0);

void test_interrupt(void)
{
    led = !led;
}

void test_ticker(void)
{
    led = !led;
}

int main()
{
    printf("\nStart Application\n");
    button.rise(&test_interrupt);

    DeepSleepLock lock;
    lock.unlock();
    sleep();

    while (true) {
        printf("Toggle\n");
        ThisThread::sleep_for(BLINKING_RATE_MS);
    }
}
CLOSED st bug

All 16 comments

@heejungPark thank you for raising this issue.Please take a look at the following comments:

We cannot automatically identify a release based on the version of Mbed OS that you have provided.
Please provide either a single valid sha of the form #abcde12 or #3b8265d70af32261311a06e423ca33434d8d80de
or a single valid release tag of the form mbed-os-x.y.z .
E.g. 'mbed-os-5.15.4)' has not been matched as a valid tag or sha.
NOTE: If there are fields which are not applicable then please just add 'n/a' or 'None'.This indicates to us that at least all the fields have been considered.
Please update the issue header with the missing information, the issue will not be mirroredto our internal defect tracking system or investigated until this has been fully resolved.

I updated the version of mbed-os.
What is the issue header?

@heejungPark for targets that support tickless operation, the application is not supposed to call sleep().
The mbed-os core will put the target to sleep or deep_sleep when the application calls for ThisThread::sleep_for(BLINKING_RATE_MS);
The target may wake-up for internal os / tickers operation but will go back to sleep / deep_sleep mode if there is nothing to do.

Thank you for raising this detailed GitHub issue. I am now notifying our internal issue triagers.
Internal Jira reference: https://jira.arm.com/browse/MBOTRIAGE-2786

The target supported MBED_TICKLESS cannot be wake-up by external interrupt like a button?
And if add "target.macro_remove" : ["MBED_TICKLESS"] in mbed_app.json, can the application be supported to call sleep() to entry sleep/deepsleep mode?

the target supported MBED_TICKLESS cannot be wake-up by external interrupt lik

yes it can. if you remove sleep() from your code, the target should anyway go to sleep modes, you don't need to call sleep().

And if add "target.macro_remove" : ["MBED_TICKLESS"] in mbed_app.json, can the application be supported to call sleep() to entry sleep/deepsleep mode?

No I don't think so. Without TICKLESS, the target will never enter deep_sleep. The mbed-os operating system will always schedule ticks and prevent deep_sleep.

you can have a look at : https://os.mbed.com/docs/mbed-os/v6.2/apis/power-management-sleep.html . At the end of this page, you can see the example main.cpp application. It never calls to sleep it will only call to sleep_manager_lock_deep_sleep(); or sleep_manager_unlock_deep_sleep(); to allow or disallow the system to enter deep_sleep or not.

Okay, I got it.
So, our main.cpp to entry into 'DeepSleep mode' and wake up is as below.

  1. Entry DeepSleep for 100 seconds
  2. Before 100 seconds, push and release a button to wake up the target.

In my case, when this code runs, 'led' is toggled whenever button is pushed but the target didn't wake up. The 'Toggle' message in while loop is always printed after 100 seconds.

Please check it.

#include "mbed.h"

// Blinking rate in milliseconds
#define BLINKING_RATE_MS     2000

DigitalOut      led(LED1, 1);
InterruptIn     button(D0);

void test_interrupt(void)
{
    led = !led;
}

int main()
{
    printf("\nStart Application\n");
    button.rise(&test_interrupt);

    printf("Deep sleep allowed: %i\r\n", sleep_manager_can_deep_sleep());
    sleep_manager_unlock_deep_sleep();
    ThisThread::sleep_for(100 * 1000);       // During 100 sec

    // I will push a Button to wake up the target before 100 seconds.

    while (true) {
        printf("Toggle\n");
        ThisThread::sleep_for(BLINKING_RATE_MS);
    }
}

Hmm not yet ... with the above code, the target will indeed exit deep sleep mode but the thread will continue to sleep.

You need a sync mecanism like shared variable or a semaphore.
The main thread will wait for it (and sleep during that time) and the test_interrupt will release it.

Something like (Note: I have not compiled, not tested ... )

#include "mbed.h"

// Blinking rate in milliseconds
#define BLINKING_RATE_MS     2000

DigitalOut      led(LED1, 1);
InterruptIn     button(D0);
Semaphore sleep_sem(0);

void test_interrupt(void)
{
    led = !led;
    sleep_sem.release();
}

int main()
{
    printf("\nStart Application\n");
    button.rise(&test_interrupt);

    printf("Deep sleep allowed: %i\r\n", sleep_manager_can_deep_sleep());

    /* wait for semaphore for 100s */
    sleep_sem.try_acquire_for(100 *1000);  // During 100 sec

    // I will push a Button to wake up the target before 100 seconds.

    while (true) {
        printf("Toggle\n");
        ThisThread::sleep_for(BLINKING_RATE_MS);
    }
}

It is same results...the led is toggled but 'Toggle' message is printed after 100 seconds.

hmm that's surprising ...
you don't need to call sleep_manager_unlock_deep_sleep(); as this is already enabled by default (I removed it from the above code). I quickly tested on a NUCLEO_L073RZ and mbed-os-6.1.0 and that worked ok (toggle is displayed as soon as I press the user button) ...

I tested on mbed-os-15.5.4 and this works as well with the code shared earlier.

Start Application
Deep sleep allowed: 0
Toggle

The log says deep sleep allowed : 0, but as printf is ongoing this is expected.
Then as soon as I pressed the button, Toggle is printed.

I removed sleep_manager_unlock_deep_sleep() and tested but there is no change.
Maybe, is there fixed pins used to external wake up?
(For example, the pin 'D0' I used cannot be used for wake up pin.)

Maybe, is there fixed pins used to external wake up?
(For example, the pin 'D0' I used cannot be used for wake up pin.)

Hmmm I don't think so. MBED deep sleep is mapped to STOP2 mode and any GPIO can wake-up from STOP mode.
I just tested with D10 on my board and this works ok.
You are connecting put 3V3 to this GPIO right ?
You may try with USER_BUTTON (blue button) instead.

InterruptIn     button(USER_BUTTON);

Can you copy / paste all your latest version of code again for a check ?

Yes, I used 'D0' instead of 'USER_BUTTON'.
When I tested again, it works well as intended. I don't know why it didn't work yesterday...
So, I wonder that the target surely entry into deepsleep mode by calling try_acquire_for().
Is any way to check it?

#include "mbed.h"

// Blinking rate in milliseconds
#define BLINKING_RATE_MS     2000

DigitalOut      led(LED1, 1);
InterruptIn     button(D0);
Semaphore       sleep_sem(0);

int park = 0;

int count1 = 0;

void test_interrupt(void)
{
    led = !led;
    sleep_sem.release();
}

int main()
{
    printf("\nStart Application\n");
    button.rise(&test_interrupt);

    sleep_manager_unlock_deep_sleep();
    printf("Deep sleep allowed: %i\r\n", sleep_manager_can_deep_sleep());
    // ThisThread::sleep_for(100 * 1000);       // During 100 sec
    sleep_sem.try_acquire_for(100 *1000);  // During 100 sec

    // I will push a Button to wake up the target before 100 seconds.

    while (true) {
        printf("Toggle\n");
        ThisThread::sleep_for(BLINKING_RATE_MS);
    }
}

Yes, I used 'D0' instead of 'USER_BUTTON'.
When I tested again, it works well as intended. I don't know why it didn't work yesterday...

Ok good.

So, I wonder that the target surely entry into deepsleep mode by calling try_acquire_for().
Is any way to check it?

You can measure power consumption or use mbed statistics. (https://os.mbed.com/docs/mbed-os/v6.2/apis/mbed-statistics.html)
I tested with mbed_app.json

        "NUCLEO_L073RZ": {
            "platform.all-stats-enabled" : true,
            "platform.cpu-stats-enabled": true
        },

and below updated main.cpp

#include "mbed.h"

// Blinking rate in milliseconds
#define BLINKING_RATE_MS     2000

DigitalOut      led(LED1, 1);
InterruptIn     button(USER_BUTTON);
Semaphore sleep_sem(0);

void test_interrupt(void)
{
    led = !led;
    sleep_sem.release();
}

int main()
{
    static mbed_stats_cpu_t stats;
    printf("\nStart Application\n");

    button.fall(&test_interrupt);

    printf("Deep sleep allowed: %i\r\n", sleep_manager_can_deep_sleep());

        /* wait for semaphore for 100s or button push */
    sleep_sem.try_acquire_for(100 *1000);  // During 100 sec
    // I will push a Button to wake up the target before 100 seconds.

    while (true) {
         mbed_stats_cpu_get(&stats);
         printf("uptime %d \%\n", (int) stats.uptime);
         printf("Sleep %d \%\n", (int) ((stats.sleep_time * 100) / stats.uptime));
         printf("DeepSleep %d \%\n", (int) ((stats.deep_sleep_time * 100) / stats.uptime));
        /* wait for semaphore for 100s or button push */
        sleep_sem.try_acquire_for(100 *1000);  // During 100 sec
    }
}

Result is:

Start Application
Deep sleep allowed: 0
uptime 3271301
Sleep 0
DeepSleep 98
uptime 5738067
Sleep 0
DeepSleep 98
uptime 7976593
Sleep 0
DeepSleep 98
uptime 66851196
Sleep 0
DeepSleep 99

Okay I'll try it.
Thank you so so much!

Was this page helpful?
0 / 5 - 0 ratings