Lightsleep with wake from interrupt - how?

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Does lightsleep even work?

Post by pythoncoder » Fri Mar 19, 2021 9:22 am

I now have another Pico to test.

Issuing machine.lightsleep() has no effect on the current consumption when connected by USB. It may be that you have to disable USB, power from another source and connect by UART to achieve a current drop. I will experiment.
Peter Hinch
Index to my micropython libraries.

John57
Posts: 10
Joined: Sat Mar 06, 2021 5:26 am

Re: Lightsleep with wake from interrupt - how?

Post by John57 » Tue Mar 30, 2021 12:23 am

Further thinking on this problem based on the current codebase.

lightsleep invokes __wfe(). I have been reading all I can, does or can the rp2 initiate an event when an interrupt occurs? Or do we need to setup a specific sleep call that uses the __wfi() call.

It also necessary to setup a wake on interrupt enable for the GPIO using the gpio_set_dormant_irq_enabled function which uses a different event than the pin interrupt call argument (see examples in rp2 datasheet). The datasheet is a bit confusing in its examples for entering sleep modes, with one section manually managing the clocks that are deactivated. Does the user actually control what clocks are deactivated in the sleep function? The overall description seems to suggest that dormant mode puts everything to sleep except memory (and the logic that monitors for wakeup).

Excerpt from rosc.h
// Register : ROSC_DORMANT
// Description : Ring Oscillator pause control
// This is used to save power by pausing the ROSC
// On power-up this field is initialised to WAKE
// An invalid write will also select WAKE
// Warning: setup the irq before selecting dormant mode
// 0x636f6d61 -> DORMANT
// 0x77616b65 -> WAKE
Maybe this is it, but means we must be running off the rosc.

So I havent yet tried activating with __wfi() yet, but have tried the using the gpio_set_dormant_irq_enabled function within the machine_pin_irq code without success.

I think there must be something else needed to activate dormant mode, but the option isnt in the current code, and still not sure what it is.

Found in pico_extras, activate dormant mode when operating rosc. It sets the above register. Will check this out shortly.

John

John57
Posts: 10
Joined: Sat Mar 06, 2021 5:26 am

Re: Lightsleep with wake from interrupt - how?

Post by John57 » Wed Mar 31, 2021 10:50 am

Success.

1) from pico-extras copy hardware_rosc to rp2_common and adjust cmake lists to match.
This provides the method rosc_set_dormant to place pico into dormant mode.

2) enable dormant irq for the required gpio. This is done in the machine_pin_irq method, when a non zero wake argument is passed.
This is similar to the published to description of that method.

Appears to be doing as expected - program halts until a button press/release occurs and on wake continues with the code immediately after the sleep call, and the main loop continues

Sample Program Output:
Running ...
Running ... <------- in main program loop
Running ...
Running ...
Running ...
Running ...
Sleeping <------- sleep activated after 5 loops
Woken <-------- print after the dormant call
this is delayed waiting for the button press-release
bpressed= 0 <------- count of button presses set in the interrupt call
Pressed Button-Pin(15, mode=IN, pull=PULL_UP)
Released Button-Pin(15, mode=IN, pull=PULL_UP) time 184
Running ...
Sleeping <-------- dormant sleep entered
Woken
bpressed= 1 <-------- dormant sleep entered
Pressed Button-Pin(15, mode=IN, pull=PULL_UP)
Released Button-Pin(15, mode=IN, pull=PULL_UP) time 237
Running ...
Sleeping
Woken
bpressed= 2
Pressed Button-Pin(15, mode=IN, pull=PULL_UP)
Released Button-Pin(15, mode=IN, pull=PULL_UP) time 159
Running ...


The required changes are in jf-wake branch of my cloned repository https://github.com/jmfloyd/jf-micropython-pico.

Work required
rosc_set_dormant should not be called without a dormant-irq enable. A global variable keeping count of active wake irq's is required to ensure dormant is not called unless set.

This is working for rosc based clocks. If xosc is required more work is required to disable/enable clocks on sleep and wake.

Might be useful to create a hardware_powersave module in pico-sdk to put both rosc and xosc required coding together. An example of required code is in the rp2040 datasheet pdf.

John

John57
Posts: 10
Joined: Sat Mar 06, 2021 5:26 am

Re: Lightsleep with wake from interrupt - how?

Post by John57 » Thu Apr 01, 2021 1:35 am

Have implemented safe activation of dormant_wake, needed a routine to check if any dormant_wake_irq's were enabled by checking the chips dormant INTE registers.

John

John57
Posts: 10
Joined: Sat Mar 06, 2021 5:26 am

Re: Lightsleep with wake from interrupt - Success

Post by John57 » Wed Apr 07, 2021 1:56 am

Description of my micropython additions/changes to get dormant wake working.

I added an extra method into hardware_pin (maybe not the place to do it) that sets the dormant_wake registers from python.

I previously had it incorporated into the general irq_enable method. Separation allows explicit fine control of the wake register. For example if you create a button that alternatively activates a button press and release irq, we only want a wake_on_interrupt to act on the press trigger that will allow the button press and release sequence to operate.

The extra code to micropython is minimal, providing python access to the enable dormant mode code from pico-extras code, some new code check if any dormant irqs are set, and uses the existing code to set the dormant_wake registers. This code only works when using the rosc clocks. Code to handle the xosc situation (mostly from pico-extras as well) needs to be done.

My simple python code showing dormant wake using a single button, is in the examples/rp2 folder of my cloned repository in jf-wakup branch.

John

Post Reply