diff options
author | Angus Gratton <angus@redyak.com.au> | 2025-03-26 11:21:09 +1100 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2025-05-21 13:47:45 +1000 |
commit | 4545eb844df3acf342052bf80b35a8127cf7e194 (patch) | |
tree | b8b24def51979a50b96b05690aa4881354eb21c3 | |
parent | a1ee42cd3e6172cd57756e382a4702ae2a1d4a9e (diff) | |
download | micropython-4545eb844df3acf342052bf80b35a8127cf7e194.tar.gz micropython-4545eb844df3acf342052bf80b35a8127cf7e194.zip |
rp2: Disable the LWIP tick timer when not needed.
Prevents lightsleep being woken up every 64ms to service LWIP timers, when:
1. No netif is up, and
2. No TCP sockets are active
The TCP socket check may not be strictly necessary, but without ticking the
tcp timer they won't ever time out by themselves.
This work was funded through GitHub Sponsors.
Signed-off-by: Angus Gratton <angus@redyak.com.au>
-rw-r--r-- | ports/rp2/mpnetworkport.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/ports/rp2/mpnetworkport.c b/ports/rp2/mpnetworkport.c index e1e1567828..fed34be380 100644 --- a/ports/rp2/mpnetworkport.c +++ b/ports/rp2/mpnetworkport.c @@ -31,6 +31,7 @@ #if MICROPY_PY_LWIP #include "shared/runtime/softtimer.h" +#include "lwip/netif.h" #include "lwip/timeouts.h" // Poll lwIP every 64ms by default @@ -39,6 +40,9 @@ // Soft timer for running lwIP in the background. static soft_timer_entry_t mp_network_soft_timer; +// Callback for change of netif state +NETIF_DECLARE_EXT_CALLBACK(netif_callback) + #if MICROPY_PY_NETWORK_CYW43 #include "lib/cyw43-driver/src/cyw43.h" #include "lib/cyw43-driver/src/cyw43_stats.h" @@ -137,17 +141,48 @@ static void mp_network_soft_timer_callback(soft_timer_entry_t *self) { #if MICROPY_PY_NETWORK_WIZNET5K wiznet5k_poll(); #endif + + // Only keep the timer running if any TCP sockets are active, or any netif is up + struct netif *netif; + extern void *tcp_active_pcbs; + bool keep_running = (tcp_active_pcbs != NULL); + if (!keep_running) { + NETIF_FOREACH(netif) { + if (netif->flags & NETIF_FLAG_LINK_UP) { + keep_running = true; + break; + } + } + } + + // Periodic timer will re-queue as soon as this handler exits, + // one shot timer will not + mp_network_soft_timer.mode = keep_running ? SOFT_TIMER_MODE_PERIODIC : SOFT_TIMER_MODE_ONE_SHOT; } +static void mp_network_netif_status_cb(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args); + void mod_network_lwip_init(void) { soft_timer_static_init( &mp_network_soft_timer, - SOFT_TIMER_MODE_PERIODIC, + SOFT_TIMER_MODE_ONE_SHOT, LWIP_TICK_RATE_MS, mp_network_soft_timer_callback ); - soft_timer_reinsert(&mp_network_soft_timer, LWIP_TICK_RATE_MS); + if (netif_callback.callback_fn == NULL) { + netif_add_ext_callback(&netif_callback, mp_network_netif_status_cb); + } +} + +static void mp_network_netif_status_cb(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args) { + // Start the network soft timer any time an interface comes up, unless + // it's already running + if (reason == LWIP_NSC_LINK_CHANGED && args->link_changed.state + && mp_network_soft_timer.mode == SOFT_TIMER_MODE_ONE_SHOT) { + mp_network_soft_timer.mode = SOFT_TIMER_MODE_PERIODIC; + soft_timer_reinsert(&mp_network_soft_timer, LWIP_TICK_RATE_MS); + } } #endif // MICROPY_PY_LWIP |