diff --git a/cores/rp2040/LWIPMutex.h b/cores/rp2040/LWIPMutex.h deleted file mode 100644 index 02220a706..000000000 --- a/cores/rp2040/LWIPMutex.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - WiFiMutex.h - Ensure the timer-driven sys_check_timeouts doesn't - get executed while we're in the user-level TCP stack. - Copyright (c) 2022 Earle F. Philhower, III. All rights reserved. - - Implements the API defined by the Arduino WiFiNINA library, - copyright (c) 2018 Arduino SA. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#pragma once - -extern "C" volatile bool __inLWIP; - -class LWIPMutex { -public: - LWIPMutex() { - __inLWIP = true; - _ref++; - } - ~LWIPMutex() { - if (0 == --_ref) { - __inLWIP = false; - } - } -private: - static int _ref; -}; diff --git a/cores/rp2040/lwip_wrap.cpp b/cores/rp2040/lwip_wrap.cpp new file mode 100644 index 000000000..6de5a0ace --- /dev/null +++ b/cores/rp2040/lwip_wrap.cpp @@ -0,0 +1,326 @@ +/* + LWIP wrappers to protect against timer-based re-entrancy + + Copyright (c) 202s Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "pico/mutex.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "lwip/tcp.h" +#include "lwip/dns.h" +#include "lwip/raw.h" +#include "lwip/timeouts.h" + +// Global indicator that we're inside an LWIP block +extern "C" { + volatile bool __inLWIP = false; +} + +auto_init_recursive_mutex(__mtxLWIP); + +class LWIPMutex { +public: + LWIPMutex() { + noInterrupts(); + recursive_mutex_enter_blocking(&__mtxLWIP); + __inLWIP = true; + _ref++; + interrupts(); + } + + ~LWIPMutex() { + noInterrupts(); + if (0 == --_ref) { + __inLWIP = false; + } + recursive_mutex_exit(&__mtxLWIP); + interrupts(); + } + +private: + static int _ref; +}; +int LWIPMutex::_ref = 0; + + +extern "C" { + + extern u8_t __real_pbuf_header(struct pbuf *p, s16_t header_size); + u8_t __wrap_pbuf_header(struct pbuf *p, s16_t header_size) { + LWIPMutex m; + return __real_pbuf_header(p, header_size); + } + + extern u8_t __real_pbuf_free(struct pbuf *p); + u8_t __wrap_pbuf_free(struct pbuf *p) { + LWIPMutex m; + return __real_pbuf_free(p); + } + + extern struct pbuf *__real_pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type); + struct pbuf *__wrap_pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type) { + LWIPMutex m; + return __real_pbuf_alloc(l, length, type); + } + + extern err_t __real_pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len); + err_t __wrap_pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) { + LWIPMutex m; + return __real_pbuf_take(buf, dataptr, len); + } + + extern u16_t __real_pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset); + u16_t __wrap_pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset) { + LWIPMutex m; + return __real_pbuf_copy_partial(p, dataptr, len, offset); + } + + extern void __real_pbuf_ref(struct pbuf *p); + void __wrap_pbuf_ref(struct pbuf *p) { + LWIPMutex m; + __real_pbuf_ref(p); + } + + extern u8_t __real_pbuf_get_at(const struct pbuf* p, u16_t offset); + u8_t __wrap_pbuf_get_at(const struct pbuf* p, u16_t offset) { + LWIPMutex m; + return __real_pbuf_get_at(p, offset); + } + + extern void *__real_pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset); + void *__wrap_pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset) { + LWIPMutex m; + return __real_pbuf_get_contiguous(p, buffer, bufsize, len, offset); + } + + extern void __real_pbuf_cat(struct pbuf *head, struct pbuf *tail); + void __wrap_pbuf_cat(struct pbuf *head, struct pbuf *tail) { + LWIPMutex m; + __real_pbuf_cat(head, tail); + } + + extern void __real_tcp_arg(struct tcp_pcb *pcb, void *arg); + void __wrap_tcp_arg(struct tcp_pcb *pcb, void *arg) { + LWIPMutex m; + __real_tcp_arg(pcb, arg); + } + + extern struct tcp_pcb *__real_tcp_new(void); + struct tcp_pcb *__wrap_tcp_new(void) { + LWIPMutex m; + return __real_tcp_new(); + } + + extern err_t __real_tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port); + err_t __wrap_tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) { + LWIPMutex m; + return __real_tcp_bind(pcb, ipaddr, port); + } + + extern struct tcp_pcb *__real_tcp_listen(struct tcp_pcb *pcb); + struct tcp_pcb *__wrap_tcp_listen(struct tcp_pcb *pcb) { + LWIPMutex m; + return __real_tcp_listen(pcb); + } + + extern struct tcp_pcb *__real_tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog); + struct tcp_pcb *__wrap_tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) { + LWIPMutex m; + return __real_tcp_listen_with_backlog(pcb, backlog); + } + + extern void __real_tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)); + void __wrap_tcp_accept(struct tcp_pcb *pcb, err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)) { + LWIPMutex m; + __real_tcp_accept(pcb, accept); + } + + extern err_t __real_tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)); + err_t __wrap_tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err)) { + LWIPMutex m; + return __real_tcp_connect(pcb, ipaddr, port, connected); + } + + extern err_t __real_tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, u8_t apiflags); + err_t __wrap_tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len, u8_t apiflags) { + LWIPMutex m; + return __real_tcp_write(pcb, dataptr, len, apiflags); + } + + extern void __real_tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)); + void __wrap_tcp_sent(struct tcp_pcb *pcb, err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len)) { + LWIPMutex m; + __real_tcp_sent(pcb, sent); + } + + extern void __real_tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)); + void __wrap_tcp_recv(struct tcp_pcb *pcb, err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)) { + LWIPMutex m; + __real_tcp_recv(pcb, recv); + } + + extern void __real_tcp_recved(struct tcp_pcb *pcb, u16_t len); + void __wrap_tcp_recved(struct tcp_pcb *pcb, u16_t len) { + LWIPMutex m; + __real_tcp_recved(pcb, len); + } + + extern void __real_tcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval); + void __wrap_tcp_poll(struct tcp_pcb *pcb, err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval) { + LWIPMutex m; + __real_tcp_poll(pcb, poll, interval); + } + + extern err_t __real_tcp_close(struct tcp_pcb *pcb); + err_t __wrap_tcp_close(struct tcp_pcb *pcb) { + LWIPMutex m; + return __real_tcp_close(pcb); + } + + extern void __real_tcp_abort(struct tcp_pcb *pcb); + void __wrap_tcp_abort(struct tcp_pcb *pcb) { + LWIPMutex m; + __real_tcp_abort(pcb); + } + + extern void __real_tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, err_t err)); + void __wrap_tcp_err(struct tcp_pcb *pcb, void (* err)(void *arg, err_t err)) { + LWIPMutex m; + __real_tcp_err(pcb, err); + } + + extern err_t __real_tcp_output(struct tcp_pcb *pcb); + err_t __wrap_tcp_output(struct tcp_pcb *pcb) { + LWIPMutex m; + return __real_tcp_output(pcb); + } + + extern void __real_tcp_setprio(struct tcp_pcb *pcb, u8_t prio); + void __wrap_tcp_setprio(struct tcp_pcb *pcb, u8_t prio) { + LWIPMutex m; + return __real_tcp_setprio(pcb, prio); + } + + extern void __real_tcp_backlog_delayed(struct tcp_pcb* pcb); + void __wrap_tcp_backlog_delayed(struct tcp_pcb* pcb) { + LWIPMutex m; + return __real_tcp_backlog_delayed(pcb); + } + + extern void __real_tcp_backlog_accepted(struct tcp_pcb* pcb); + void __wrap_tcp_backlog_accepted(struct tcp_pcb* pcb) { + LWIPMutex m; + return __real_tcp_backlog_accepted(pcb); + } + extern struct udp_pcb *__real_udp_new(void); + struct udp_pcb *__wrap_udp_new(void) { + LWIPMutex m; + return __real_udp_new(); + } + + extern void __real_udp_remove(struct udp_pcb *pcb); + void __wrap_udp_remove(struct udp_pcb *pcb) { + LWIPMutex m; + __real_udp_remove(pcb); + } + + extern err_t __real_udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port); + err_t __wrap_udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) { + LWIPMutex m; + return __real_udp_bind(pcb, ipaddr, port); + } + + extern err_t __real_udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port); + err_t __wrap_udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) { + LWIPMutex m; + return __real_udp_connect(pcb, ipaddr, port); + } + + extern err_t __real_udp_disconnect(struct udp_pcb *pcb); + err_t __wrap_udp_disconnect(struct udp_pcb *pcb) { + LWIPMutex m; + return __real_udp_disconnect(pcb); + } + + extern err_t __real_udp_send(struct udp_pcb *pcb, struct pbuf *p); + err_t __wrap_udp_send(struct udp_pcb *pcb, struct pbuf *p) { + LWIPMutex m; + return __real_udp_send(pcb, p); + } + + extern void __real_udp_recv(struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port), void *recv_arg); + void __wrap_udp_recv(struct udp_pcb *pcb, void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port), void *recv_arg) { + LWIPMutex m; + __real_udp_recv(pcb, recv, recv_arg); + } + + extern err_t __real_udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif); + err_t __wrap_udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) { + LWIPMutex m; + return __real_udp_sendto_if(pcb, p, dst_ip, dst_port, netif); + } + + extern void __real_sys_check_timeouts(void); + void __wrap_sys_check_timeouts(void) { + LWIPMutex m; + __real_sys_check_timeouts(); + } + + extern err_t __real_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg); + err_t __wrap_dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg) { + LWIPMutex m; + return __real_dns_gethostbyname(hostname, addr, found, callback_arg); + } + + extern err_t __real_dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg, u8_t dns_addrtype); + err_t __wrap_dns_gethostbyname_addrtype(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *callback_arg, u8_t dns_addrtype) { + LWIPMutex m; + return __real_dns_gethostbyname_addrtype(hostname, addr, found, callback_arg, dns_addrtype); + } + + extern struct raw_pcb *__real_raw_new(u8_t proto); + struct raw_pcb *__wrap_raw_new(u8_t proto) { + LWIPMutex m; + return __real_raw_new(proto); + } + + extern void __real_raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); + void __wrap_raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) { + LWIPMutex m; + __real_raw_recv(pcb, recv, recv_arg); + } + + extern err_t __real_raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr); + err_t __wrap_raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr) { + LWIPMutex m; + return __real_raw_bind(pcb, ipaddr); + } + + extern err_t __real_raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr); + err_t __wrap_raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) { + LWIPMutex m; + return __real_raw_sendto(pcb, p, ipaddr); + } + + extern void __real_raw_remove(struct raw_pcb *pcb); + void __wrap_raw_remove(struct raw_pcb *pcb) { + LWIPMutex m; + __real_raw_remove(pcb); + } + +}; // extern "C" diff --git a/cores/rp2040/main.cpp b/cores/rp2040/main.cpp index 349e9b351..e630ea6c1 100644 --- a/cores/rp2040/main.cpp +++ b/cores/rp2040/main.cpp @@ -22,7 +22,6 @@ #include "RP2040USB.h" #include #include -#include "LWIPMutex.h" #include RP2040 rp2040; @@ -33,8 +32,6 @@ extern "C" { mutex_t _pioMutex; -int LWIPMutex::_ref = 0; - extern void setup(); extern void loop(); diff --git a/cores/rp2040/malloc-lock.cpp b/cores/rp2040/malloc-lock.cpp new file mode 100644 index 000000000..ec8a55f79 --- /dev/null +++ b/cores/rp2040/malloc-lock.cpp @@ -0,0 +1,53 @@ +/* + Malloc/etc. interrupt locking wrappers + + Copyright (c) 2022 Earle F. Philhower, III + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include + +extern "C" void *__real_malloc(size_t size); +extern "C" void *__real_calloc(size_t count, size_t size); +extern "C" void *__real_realloc(void *mem, size_t size); +extern "C" void __real_free(void *mem); + +extern "C" void *__wrap_malloc(size_t size) { + noInterrupts(); + void *rc = __real_malloc(size); + interrupts(); + return rc; +} + +extern "C" void *__wrap_calloc(size_t count, size_t size) { + noInterrupts(); + void *rc = __real_calloc(count, size); + interrupts(); + return rc; +} + +extern "C" void *__wrap_realloc(void *mem, size_t size) { + noInterrupts(); + void *rc = __real_realloc(mem, size); + interrupts(); + return rc; +} + +extern "C" void __wrap_free(void *mem) { + noInterrupts(); + __real_free(mem); + interrupts(); +} diff --git a/cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c b/cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c index bd3dd68fe..717ff2dca 100644 --- a/cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c +++ b/cores/rp2040/sdkoverride/cyw43_arch_threadsafe_background.c @@ -36,7 +36,7 @@ #define CYW43_WL_GPIO_LED_PIN 0 #endif -volatile bool __inLWIP = false; +extern volatile bool __inLWIP; // note same code #if PICO_CYW43_ARCH_THREADSAFE_BACKGROUND diff --git a/lib/libpico-ipv6.a b/lib/libpico-ipv6.a index d06eb19a7..913603f38 100644 Binary files a/lib/libpico-ipv6.a and b/lib/libpico-ipv6.a differ diff --git a/lib/libpico.a b/lib/libpico.a index fddb06dc5..547909708 100644 Binary files a/lib/libpico.a and b/lib/libpico.a differ diff --git a/lib/platform_wrap.txt b/lib/platform_wrap.txt index 29542dd96..06a0e75cf 100644 --- a/lib/platform_wrap.txt +++ b/lib/platform_wrap.txt @@ -144,4 +144,59 @@ -Wl,--wrap=tanhf -Wl,--wrap=trunc -Wl,--wrap=truncf + -Wl,--wrap=__getreent + +-Wl,--wrap=malloc +-Wl,--wrap=calloc +-Wl,--wrap=realloc +-Wl,--wrap=free + +-Wl,--wrap=pbuf_header +-Wl,--wrap=pbuf_free +-Wl,--wrap=pbuf_alloc +-Wl,--wrap=pbuf_take +-Wl,--wrap=pbuf_copy_partial +-Wl,--wrap=pbuf_ref +-Wl,--wrap=pbuf_get_at +-Wl,--wrap=pbuf_get_contiguous +-Wl,--wrap=pbuf_cat + +-Wl,--wrap=tcp_arg +-Wl,--wrap=tcp_new +-Wl,--wrap=tcp_listen +-Wl,--wrap=tcp_listen_with_backlog +-Wl,--wrap=tcp_accept +-Wl,--wrap=tcp_connect +-Wl,--wrap=tcp_write +-Wl,--wrap=tcp_sent +-Wl,--wrap=tcp_recv +-Wl,--wrap=tcp_recved +-Wl,--wrap=tcp_poll +-Wl,--wrap=tcp_close +-Wl,--wrap=tcp_abort +-Wl,--wrap=tcp_err +-Wl,--wrap=tcp_output +-Wl,--wrap=tcp_setprio +-Wl,--wrap=tcp_backlog_delayed +-Wl,--wrap=tcp_backlog_accepted + +-Wl,--wrap=udp_new +-Wl,--wrap=udp_remove +-Wl,--wrap=udp_bind +-Wl,--wrap=udp_connect +-Wl,--wrap=udp_disconnect +-Wl,--wrap=udp_send +-Wl,--wrap=udp_recv +-Wl,--wrap=udp_sendto_if + +-Wl,--wrap=sys_check_timeouts + +-Wl,--wrap=dns_gethostbyname +-Wl,--wrap=dns_gethostbyname_addrtype + +-Wl,--wrap=raw_new +-Wl,--wrap=raw_recv +-Wl,--wrap=raw_bind +-Wl,--wrap=raw_sendto +-Wl,--wrap=raw_remove diff --git a/libraries/LEAmDNS/src/LEAmDNS.cpp b/libraries/LEAmDNS/src/LEAmDNS.cpp index ef86b5605..c1b3e2eb3 100644 --- a/libraries/LEAmDNS/src/LEAmDNS.cpp +++ b/libraries/LEAmDNS/src/LEAmDNS.cpp @@ -28,7 +28,6 @@ #include "ESP8266mDNS.h" #include "LEAmDNS_Priv.h" #include // LwipIntf::stateUpCB() -#include // LwipIntf::stateUpCB() #include #include diff --git a/libraries/WiFi/src/WiFi.h b/libraries/WiFi/src/WiFi.h index 1c2650f7a..206bf0a2e 100644 --- a/libraries/WiFi/src/WiFi.h +++ b/libraries/WiFi/src/WiFi.h @@ -3,8 +3,6 @@ #include "wl_definitions.h" #include "wl_types.h" -#include "LWIPMutex.h" - #include "WiFiClass.h" #include "WiFiClient.h" #include "WiFiServer.h" diff --git a/libraries/WiFi/src/WiFiClient.cpp b/libraries/WiFi/src/WiFiClient.cpp index 19e7fab13..32df6b01d 100644 --- a/libraries/WiFi/src/WiFiClient.cpp +++ b/libraries/WiFi/src/WiFiClient.cpp @@ -130,8 +130,6 @@ int WiFiClient::connect(IPAddress ip, uint16_t port) { _client = nullptr; } - LWIPMutex m; // Block the timer sys_check_timeouts call - tcp_pcb* pcb = tcp_new(); if (!pcb) { return 0; diff --git a/libraries/WiFi/src/WiFiServer.cpp b/libraries/WiFi/src/WiFiServer.cpp index 364c11cda..305606658 100644 --- a/libraries/WiFi/src/WiFiServer.cpp +++ b/libraries/WiFi/src/WiFiServer.cpp @@ -56,8 +56,6 @@ void WiFiServer::begin(uint16_t port, uint8_t backlog) { } _port = port; - LWIPMutex m; // Block the timer sys_check_timeouts call - tcp_pcb* pcb = tcp_new(); if (!pcb) { return; @@ -134,7 +132,6 @@ WiFiClient WiFiServer::accept() { // pcb can be null when peer has already closed the connection if (_unclaimed->getPCB()) { - LWIPMutex m; // Block the timer sys_check_timeouts call // give permission to lwIP to accept one more peer tcp_backlog_accepted(_unclaimed->getPCB()); } @@ -162,7 +159,6 @@ void WiFiServer::close() { if (!_listen_pcb) { return; } - LWIPMutex m; // Block the timer sys_check_timeouts call tcp_close(_listen_pcb); _listen_pcb = nullptr; } @@ -197,7 +193,6 @@ err_t WiFiServer::_accept(tcp_pcb* apcb, err_t err) { // https://www.nongnu.org/lwip/2_1_x/group__tcp__raw.html#gaeff14f321d1eecd0431611f382fcd338 // increase lwIP's backlog - LWIPMutex m; // Block the timer sys_check_timeouts call tcp_backlog_delayed(apcb); _unclaimed = slist_append_tail(_unclaimed, client); diff --git a/libraries/WiFi/src/WiFiServer.h b/libraries/WiFi/src/WiFiServer.h index 04b90fe55..78b3c6da2 100644 --- a/libraries/WiFi/src/WiFiServer.h +++ b/libraries/WiFi/src/WiFiServer.h @@ -24,7 +24,6 @@ #include struct tcp_pcb; -#include #include #include #include diff --git a/libraries/WiFi/src/include/ClientContext.h b/libraries/WiFi/src/include/ClientContext.h index 5d40ba1dd..edb90e5ae 100644 --- a/libraries/WiFi/src/include/ClientContext.h +++ b/libraries/WiFi/src/include/ClientContext.h @@ -27,6 +27,8 @@ class WiFiClient; typedef void (*discard_cb_t)(void*, ClientContext*); #include +#include "lwip/timeouts.h" + //#include //#include @@ -36,6 +38,7 @@ template inline void esp_delay(const uint32_t timeout_ms, T&& blocked, const uint32_t intvl_ms) { const auto start_ms = millis(); while ((((uint32_t)millis() - start_ms) < timeout_ms) && blocked()) { + sys_check_timeouts(); delay(intvl_ms); } } @@ -68,7 +71,6 @@ class ClientContext { tcp_recv(_pcb, nullptr); tcp_err(_pcb, nullptr); tcp_poll(_pcb, nullptr, 0); - LWIPMutex m; // Block the timer sys_check_timeouts call tcp_abort(_pcb); _pcb = nullptr; } @@ -84,7 +86,6 @@ class ClientContext { tcp_recv(_pcb, nullptr); tcp_err(_pcb, nullptr); tcp_poll(_pcb, nullptr, 0); - LWIPMutex m; // Block the timer sys_check_timeouts call err = tcp_close(_pcb); if (err != ERR_OK) { DEBUGV(":tc err %d\r\n", (int) err); @@ -136,7 +137,6 @@ class ClientContext { ip6_addr_assign_zone(ip_2_ip6(addr), IP6_UNKNOWN, netif_default); } #endif - LWIPMutex m; // Block the timer sys_check_timeouts call err_t err = tcp_connect(_pcb, addr, port, &ClientContext::_s_connected); if (err != ERR_OK) { return 0; @@ -162,7 +162,6 @@ class ClientContext { } size_t availableForWrite() const { - LWIPMutex m; // Block the timer sys_check_timeouts call return _pcb ? tcp_sndbuf(_pcb) : 0; } @@ -170,7 +169,6 @@ class ClientContext { if (!_pcb) { return; } - LWIPMutex m; // Block the timer sys_check_timeouts call if (nodelay) { tcp_nagle_disable(_pcb); } else { @@ -182,7 +180,6 @@ class ClientContext { if (!_pcb) { return false; } - LWIPMutex m; // Block the timer sys_check_timeouts call return tcp_nagle_disabled(_pcb); } @@ -300,7 +297,6 @@ class ClientContext { if (!_rx_buf) { return; } - LWIPMutex m; // Block the timer sys_check_timeouts call if (_pcb) { tcp_recved(_pcb, (size_t) _rx_buf->tot_len); } @@ -332,7 +328,6 @@ class ClientContext { return false; } - LWIPMutex m; // Block the timer sys_check_timeouts call // force lwIP to send what can be sent tcp_output(_pcb); @@ -517,7 +512,6 @@ class ClientContext { const auto remaining = _datalen - _written; size_t next_chunk_size; { - LWIPMutex m; // Block the timer sys_check_timeouts call, just for this call next_chunk_size = std::min((size_t)tcp_sndbuf(_pcb), remaining); // Potentially reduce transmit size if we are tight on memory, but only if it doesn't return a 0 chunk size if (next_chunk_size > (size_t)(1 << scale)) { @@ -571,7 +565,6 @@ class ClientContext { // lwIP's tcp_output doc: "Find out what we can send and send it" // *with respect to Nagle* // more info: https://lists.gnu.org/archive/html/lwip-users/2017-11/msg00134.html - LWIPMutex m; // Block the timer sys_check_timeouts call tcp_output(_pcb); } @@ -596,7 +589,6 @@ class ClientContext { void _consume(size_t size) { ptrdiff_t left = _rx_buf->len - _rx_buf_offset - size; - LWIPMutex m; // Block the timer sys_check_timeouts call if (left > 0) { _rx_buf_offset += size; } else if (!_rx_buf->next) { @@ -638,7 +630,6 @@ class ClientContext { if (_rx_buf) { DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len); - LWIPMutex m; // Block the timer sys_check_timeouts call pbuf_cat(_rx_buf, pb); } else { DEBUGV(":rn %d\r\n", pb->tot_len); @@ -676,24 +667,44 @@ class ClientContext { return ERR_OK; } + // We may receive a nullptr as arg in the case when an IRQ happens during a shutdown sequence + // In that case, just ignore the CB static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err) { - return reinterpret_cast(arg)->_recv(tpcb, pb, err); + if (arg) { + return reinterpret_cast(arg)->_recv(tpcb, pb, err); + } else { + return ERR_OK; + } } static void _s_error(void *arg, err_t err) { - reinterpret_cast(arg)->_error(err); + if (arg) { + reinterpret_cast(arg)->_error(err); + } } static err_t _s_poll(void *arg, struct tcp_pcb *tpcb) { - return reinterpret_cast(arg)->_poll(tpcb); + if (arg) { + return reinterpret_cast(arg)->_poll(tpcb); + } else { + return ERR_OK; + } } static err_t _s_acked(void *arg, struct tcp_pcb *tpcb, uint16_t len) { - return reinterpret_cast(arg)->_acked(tpcb, len); + if (arg) { + return reinterpret_cast(arg)->_acked(tpcb, len); + } else { + return ERR_OK; + } } static err_t _s_connected(void* arg, struct tcp_pcb *pcb, err_t err) { - return reinterpret_cast(arg)->_connected(pcb, err); + if (arg) { + return reinterpret_cast(arg)->_connected(pcb, err); + } else { + return ERR_OK; + } } private: diff --git a/libraries/WiFi/src/include/UdpContext.h b/libraries/WiFi/src/include/UdpContext.h index bf4a6904f..5fa25c560 100644 --- a/libraries/WiFi/src/include/UdpContext.h +++ b/libraries/WiFi/src/include/UdpContext.h @@ -29,6 +29,8 @@ extern "C" { #include #include +#include "lwip/timeouts.h" + //#include #define PBUF_ALIGNER_ADJUST 4 @@ -383,6 +385,7 @@ class UdpContext { uint32_t start = millis(); while (((err = trySend(addr, port, /* keep buffer on error */true)) != ERR_OK) && (millis() - start < timeoutMs)) { delay(1); + sys_check_timeouts(); } if (err != ERR_OK) { cancelBuffer(); // get rid of buffer kept on error after timeout diff --git a/libraries/lwIP_CYW43/src/utility/CYW43shim.cpp b/libraries/lwIP_CYW43/src/utility/CYW43shim.cpp index 39a4a7780..ff9e88e42 100644 --- a/libraries/lwIP_CYW43/src/utility/CYW43shim.cpp +++ b/libraries/lwIP_CYW43/src/utility/CYW43shim.cpp @@ -39,6 +39,7 @@ extern "C" { netif *CYW43::_netif = nullptr; +extern "C" volatile bool __inLWIP; CYW43::CYW43(int8_t cs, arduino::SPIClass& spi, int8_t intrpin) { (void) cs; @@ -99,7 +100,20 @@ uint16_t CYW43::readFrame(uint8_t* buffer, uint16_t bufsize) { return 0; } -// CB from the cyg32_driver +//#define MAXWAIT 16 +//static struct pbuf *_pbufWaiting[MAXWAIT]; +//static bool _pbufHold(struct pbuf *p) { +// for (int i = 0; i < MAXWAIT; i++) { +// if (!_pbufWaiting[i]) { +// _pbufWaiting[i] = p; +// return true; +// } +// } +// return false; +//} + + +// CB from the cyw43 driver extern "C" void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) { //cyw43_t *self = (cyw43_t *)cb_data (void) cb_data; @@ -114,7 +128,7 @@ extern "C" void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, co struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); if (p != nullptr) { pbuf_take(p, buf, len); - if (netif->input(p, netif) != ERR_OK) { + if (__inLWIP || (netif->input(p, netif) != ERR_OK)) { pbuf_free(p); } CYW43_STAT_INC(PACKET_IN_COUNT); diff --git a/libraries/lwIP_Ethernet/src/LwipIntfDev.h b/libraries/lwIP_Ethernet/src/LwipIntfDev.h index 9afead04c..23c133b94 100644 --- a/libraries/lwIP_Ethernet/src/LwipIntfDev.h +++ b/libraries/lwIP_Ethernet/src/LwipIntfDev.h @@ -26,8 +26,6 @@ // TODO: // unchain pbufs -#include - #include #include #include @@ -176,7 +174,6 @@ int LwipIntfDev::hostByName(const char* aHostname, IPAddress& aResult, i return 1; } - LWIPMutex m; _dns_cb_t cb = { &aResult, this }; #if LWIP_IPV4 && LWIP_IPV6 err_t err = dns_gethostbyname_addrtype(aHostname, &addr, &_dns_found_callback, &cb, LWIP_DNS_ADDRTYPE_DEFAULT); @@ -230,8 +227,6 @@ int LwipIntfDev::ping(IPAddress host, uint8_t ttl, uint32_t _timeout) { auto ping_pcb = raw_new(IP_PROTO_ICMP); ping_pcb->ttl = ttl; - LWIPMutex m; - raw_recv(ping_pcb, _pingCB, this); raw_bind(ping_pcb, IP_ADDR_ANY); @@ -256,7 +251,7 @@ int LwipIntfDev::ping(IPAddress host, uint8_t ttl, uint32_t _timeout) { uint32_t now = millis(); while ((millis() - now < _timeout) && (_ping_ttl < 0)) { sys_check_timeouts(); - delay(10); + delay(1); } pbuf_free(p); raw_remove(ping_pcb); diff --git a/tools/libpico/CMakeLists.txt b/tools/libpico/CMakeLists.txt index 9b4f52511..375f0da4b 100644 --- a/tools/libpico/CMakeLists.txt +++ b/tools/libpico/CMakeLists.txt @@ -97,6 +97,6 @@ target_link_libraries(pico ) add_custom_command(TARGET pico POST_BUILD - COMMAND ar d libpico.a stdio.c.obj stdio_usb.c.obj stdio_usb_descriptors.c.obj cyw43_arch_threadsafe_background.c.obj + COMMAND ar d libpico.a stdio.c.obj stdio_usb.c.obj stdio_usb_descriptors.c.obj cyw43_arch_threadsafe_background.c.obj pico_malloc.c.obj COMMAND ar q libpico.a pico-sdk/src/rp2_common/cyw43_driver/cyw43_resource.o )