From 450901ad3d95fd7a26da9b001b3c32b3c34fd620 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 18 Dec 2024 14:25:21 +1100 Subject: [PATCH] WIP: rp2: Make GPIO wakeup from lightsleep consistent. Before this commit: - A Pin with an irq() trigger is a wakeup source only when machine.lightsleep(n) is used with a timeout, and only if an IRQ handler is set. After this commit: - A Pin with an irq() trigger is a wakeup source from both indefinite machine.lightsleep() and machine.lightsleep(n) with a timeout. - A Pin with an irq() trigger is a wakeup source even if no handler function is set. Issues at present: - Waking RP2040 repeatedly from machine.lightsleep() with no timeout and USB causes the USB connection to misbehave and eventually the CPU hangs. - This implementation doesn't match the machine.Pin docs re: irq(wake=) argument. However, I think only cc3200 port has actually implemented this argument as documented. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton --- ports/rp2/machine_pin.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 8ba0b44a684f7..a591b12aa8e29 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -134,6 +134,7 @@ void machine_pin_deinit(void) { continue; } gpio_set_irq_enabled(i, GPIO_IRQ_ALL, false); + gpio_set_dormant_irq_enabled(i, GPIO_IRQ_ALL, false); } irq_remove_handler(IO_IRQ_BANK0, gpio_irq); } @@ -445,6 +446,7 @@ void mp_hal_pin_interrupt(mp_hal_pin_obj_t pin, mp_obj_t handler, mp_uint_t trig // Disable all IRQs while data is updated. gpio_set_irq_enabled(pin, GPIO_IRQ_ALL, false); + gpio_set_dormant_irq_enabled(pin, GPIO_IRQ_ALL, false); // Update IRQ data. irq->base.handler = handler; @@ -452,9 +454,11 @@ void mp_hal_pin_interrupt(mp_hal_pin_obj_t pin, mp_obj_t handler, mp_uint_t trig irq->flags = 0; irq->trigger = trigger; - // Enable IRQ if a handler is given. - if (handler != mp_const_none && trigger != MP_HAL_PIN_TRIGGER_NONE) { + if (trigger != MP_HAL_PIN_TRIGGER_NONE) { + // Enable IRQ even if no handler is set, so pin can wake CPU from WFI/WFE gpio_set_irq_enabled(pin, trigger, true); + // Also have the IRQ wake us from indefinite lightsleep + gpio_set_dormant_irq_enabled(pin, trigger, true); } }