diff --git a/ports/rp2/cyw43_configport.h b/ports/rp2/cyw43_configport.h index 848fb9dbf7..b5a22e6354 100644 --- a/ports/rp2/cyw43_configport.h +++ b/ports/rp2/cyw43_configport.h @@ -49,12 +49,12 @@ #define CYW43_SDPCM_SEND_COMMON_WAIT \ if (get_core_num() == 0) { \ - __WFI(); \ + cyw43_yield(); \ } \ #define CYW43_DO_IOCTL_WAIT \ if (get_core_num() == 0) { \ - __WFI(); \ + cyw43_yield(); \ } \ #define CYW43_ARRAY_SIZE(a) MP_ARRAY_SIZE(a) @@ -88,6 +88,15 @@ #define cyw43_schedule_internal_poll_dispatch(func) pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, func) void cyw43_post_poll_hook(void); +extern volatile int cyw43_has_pending; + +static inline void cyw43_yield(void) { + uint32_t my_interrupts = save_and_disable_interrupts(); + if (!cyw43_has_pending) { + __WFI(); + } + restore_interrupts(my_interrupts); +} static inline void cyw43_delay_us(uint32_t us) { uint32_t start = mp_hal_ticks_us(); @@ -99,7 +108,7 @@ static inline void cyw43_delay_ms(uint32_t ms) { uint32_t us = ms * 1000; int32_t start = mp_hal_ticks_us(); while (mp_hal_ticks_us() - start < us) { - __WFI(); + cyw43_yield(); MICROPY_EVENT_POLL_HOOK_FAST; } } diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c index fc3f706a18..81154c94ce 100644 --- a/ports/rp2/modmachine.c +++ b/ports/rp2/modmachine.c @@ -48,6 +48,9 @@ #include "pico/bootrom.h" #include "pico/stdlib.h" #include "pico/unique_id.h" +#if MICROPY_PY_NETWORK_CYW43 +#include "lib/cyw43-driver/src/cyw43.h" +#endif #if MICROPY_PY_MACHINE @@ -141,6 +144,13 @@ STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { const uint32_t xosc_hz = XOSC_MHZ * 1000000; + uint32_t my_interrupts = save_and_disable_interrupts(); + #if MICROPY_PY_NETWORK_CYW43 + if (cyw43_has_pending) { + restore_interrupts(my_interrupts); + return mp_const_none; + } + #endif // Disable USB and ADC clocks. clock_stop(clk_usb); clock_stop(clk_adc); @@ -165,6 +175,9 @@ STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_DISABLE << ROSC_CTRL_ENABLE_LSB; if (n_args == 0) { + #if MICROPY_PY_NETWORK_CYW43 + gpio_set_dormant_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true); + #endif xosc_dormant(); } else { uint32_t sleep_en0 = clocks_hw->sleep_en0; @@ -190,6 +203,7 @@ STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { // Bring back all clocks. clocks_init(); + restore_interrupts(my_interrupts); return mp_const_none; } diff --git a/ports/rp2/mpnetworkport.c b/ports/rp2/mpnetworkport.c index 0cd6eb14ce..96cd16af0f 100644 --- a/ports/rp2/mpnetworkport.c +++ b/ports/rp2/mpnetworkport.c @@ -48,6 +48,7 @@ static alarm_id_t lwip_alarm_id = -1; #define CYW43_SHARED_IRQ_HANDLER_PRIORITY PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY uint32_t cyw43_country_code = CYW43_COUNTRY_WORLDWIDE; +volatile int cyw43_has_pending = 0; static void gpio_irq_handler(void) { uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE); @@ -56,6 +57,7 @@ static void gpio_irq_handler(void) { // So disable the interrupt until this is done. It's re-enabled again by // CYW43_POST_POLL_HOOK which is called at the end of cyw43_poll_func. gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, CYW43_IRQ_LEVEL, false); + cyw43_has_pending = 1; pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll); CYW43_STAT_INC(IRQ_COUNT); } @@ -68,6 +70,7 @@ void cyw43_irq_init(void) { } void cyw43_post_poll_hook(void) { + cyw43_has_pending = 0; gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, CYW43_IRQ_LEVEL, true); }