tomjorquera / pico-micropython-lowpower-workaround

Workaround for low power support in micropython for the Raspberry pico
GNU Lesser General Public License v3.0
58 stars 12 forks source link

Only wakes for 1 pin when multiple pins are included in `dormant_until_pins` #9

Closed coplate closed 2 years ago

coplate commented 2 years ago

I was looking at this to use to wake my pico, and noticed that only the highest pin in the list will trigger the wake. i.e.: lowpower.dormant_until_pins([12, 13], high=False) only pin 13 wakes lowpower.dormant_until_pins([13, 12 ], high=False) pin 13 also wakes lowpower.dormant_until_pins([12 ], high=False) pin 12 wakes properly

For my use case it is fine, I will be feeding it with one pin from an RTC alarm, but I thought I would file the issue to let you know. I have not read deep into the documentation to really understand what is going on with the registers.

ToracX commented 2 years ago

Im having an hard time getting the script to work at all. Could you maybe send me your script and setup?

coplate commented 2 years ago

Here is my complete test case. I have wired 3 buttons to pins from 3V3_OUT to GP20, GP21, GP22. On test1 and test2, only pin GP20 will wake my device. ( using dormant_with_modes ). On test3 and test4, only GP21 will wake my device. ( using dormant_until_pins ). I am using a momentary button, so the button is reset during the flashing that occurs after waking, and my test is not misinterpreting the results be having the erroneous data go to the next call - but a more careful test could put a pause between them.

Edit: I added some log statement, to see what was being set in the registers, and I got this:


        registers_events[en_reg] = registers_events[en_reg] + pin_mode << 4 * (gpio_pin % 8)
+        print(hex(en_reg))
+        print(hex(registers_events[en_reg]))

0x40014168 0xc00000 0x40014168 0xc0000c000000 0x40014168 0xc0000c00000c0000

That final log entry is 64 bits long, instead of the 32 bits that should be written to the register - I will move the rest of these notes to a new comment

from machine import Pin
from time import sleep
import lowpower

DORMANT_PIN_A = 20
DORMANT_PIN_B = 21
DORMANT_PIN_C = 22
LED_PIN = 25
busy_led = Pin(LED_PIN, Pin.OUT)

def blink_led():
    for i in range(8):
            busy_led.value(1)
            sleep(0.03)
            busy_led.value(0)
            sleep(0.03)
#Test 1, only GP20 will wake the PI, which is the lowest, and the final in the list
def test1():
        lowpower.dormant_with_modes({
                DORMANT_PIN_C: (lowpower.EDGE_LOW | lowpower.EDGE_HIGH),
                DORMANT_PIN_B: (lowpower.EDGE_LOW | lowpower.EDGE_HIGH),
                DORMANT_PIN_A: (lowpower.EDGE_LOW | lowpower.EDGE_HIGH)
        })
        blink_led()
#Test 2, only GP20 will wake the PI, which is the lowest, and the first in the list
def test2():
        lowpower.dormant_with_modes({
                DORMANT_PIN_A: (lowpower.EDGE_LOW | lowpower.EDGE_HIGH),
                DORMANT_PIN_B: (lowpower.EDGE_LOW | lowpower.EDGE_HIGH),
                DORMANT_PIN_C: (lowpower.EDGE_LOW | lowpower.EDGE_HIGH)
        })
        blink_led()

#Test 3, onlt GP 21 will wake the Pi, which is the highest and the final in the list
def test3():
        lowpower.dormant_until_pins([DORMANT_PIN_A, DORMANT_PIN_B], high=False)
        blink_led()

#Test 3, onlt GP 21 will wake the Pi, which is the highest and the first in the list
def test4():
        lowpower.dormant_until_pins([DORMANT_PIN_B, DORMANT_PIN_A ], high=False)
        blink_led()

blink_led()
test1()
test2()
test3()
test4()
coplate commented 2 years ago

I added more logging and found the problem on this line: registers_events[en_reg] = registers_events[en_reg] + pin_mode << 4 * (gpio_pin % 8)

It appears to be doing a concatenation on the version of micropython I have "MicroPython v1.18 on 2022-01-17; Raspberry Pi Pico with RP2040", instead of integer addition.

I changed it to a bitwise or |, and got these results: Adding pin: 21 0x40014168 0xc00000 0b110000000000000000000000 Adding pin: 22 0x40014168 0xcc00000 0b1100110000000000000000000000 Adding pin: 20 0x40014168 0xccc0000 0b1100110011000000000000000000

Those are the correct bits.

I have created Pull request https://github.com/tomjorquera/pico-micropython-lowpower-workaround/pull/10 for this.

tomjorquera commented 2 years ago

Thanks for catching that @coplate! That was big one on my side.

Your PR is merged