summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2025-03-26 11:21:09 +1100
committerDamien George <damien@micropython.org>2025-05-21 13:47:45 +1000
commit4545eb844df3acf342052bf80b35a8127cf7e194 (patch)
treeb8b24def51979a50b96b05690aa4881354eb21c3
parenta1ee42cd3e6172cd57756e382a4702ae2a1d4a9e (diff)
downloadmicropython-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.c39
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