Skip to content

Commit ce2697c

Browse files
Rewrite CYW43 WiFi connection scheme
Fixes #3157 The SDK's CYW43 WiFi connection scheme combined both link layer (WiFi net connection) and IP (getting an IP address from DHCP) into a single step. We worked around it with a hack wrapped function, but it resulted in the WiFi.begin() timeout being 2x as long as specified. Remove the SDK's cyw43_arch_wifi_connect_timeout_ms and replace with our own custom CYW43::begin which will only look at the link layer. Note that the SDK docs are hokey and the cyw43_link_status is set to 1 *while network connection attempts are underway.* This means we can't actually just look at the link state, it will be in JOIN even if it's not really joined. So, we peek at the state internal CYW43 join FSM to see we're *really* connected. This exposed a corner case which @ledereyes seems to have run into in his own app where the LwipIntfDev could potentially try and register the same netif twice because the underlying lower-level CYW43 link had failed. Ensure we netif_remove() in that case to avoid this issue.
1 parent ded8a8a commit ce2697c

File tree

7 files changed

+63
-68
lines changed

7 files changed

+63
-68
lines changed

cores/rp2040/freertos/freertos-lwip.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,10 +381,14 @@ static void lwipThread(void *params) {
381381
}
382382
case __ethernet_input: {
383383
__ethernet_input_req *r = (__ethernet_input_req *)w.req;
384-
printf("__real_ethernet_input\n");
385384
*(r->ret) = __real_ethernet_input(r->p, r->netif);
386385
break;
387386
}
387+
case __cyw43_wifi_join: {
388+
__cyw43_wifi_join_req *r = (__cyw43_wifi_join_req *)w.req;
389+
*(r->ret) = __real_cyw43_wifi_join(r->self, r->ssid_len, r->ssid, r->key_len, r->key, r->auth_type, r->bssid, r->channel);
390+
break;
391+
}
388392
case __callback: {
389393
__callback_req *r = (__callback_req *)w.req;
390394
r->cb(r->cbData);

cores/rp2040/lwip_wrap.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,19 @@ extern "C" {
832832
return __real_ethernet_input(p, netif);
833833
}
834834

835+
int __real_cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel);
836+
int __wrap_cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel) {
837+
#ifdef __FREERTOS
838+
if (!__isLWIPThread()) {
839+
int ret;
840+
__cyw43_wifi_join_req req = { self, ssid_len, ssid, key_len, key, auth_type, bssid, channel, &ret };
841+
__lwip(__cyw43_wifi_join, &req);
842+
return ret;
843+
}
844+
#endif
845+
return __real_cyw43_wifi_join(self, ssid_len, ssid, key_len, key, auth_type, bssid, channel);
846+
}
847+
835848
void lwip_callback(void (*cb)(void *), void *cbData, __callback_req *buffer) {
836849
#ifdef __FREERTOS
837850
if (buffer) {
@@ -895,14 +908,6 @@ extern "C" {
895908
void __wrap_cyw43_schedule_internal_poll_dispatch(void (*func)()) {
896909
__real_cyw43_schedule_internal_poll_dispatch(func);
897910
}
898-
extern int __real_cyw43_arch_wifi_connect_bssid_timeout_ms(const char *ssid, const uint8_t *bssid, const char *pw, uint32_t auth, uint32_t timeout_ms);
899-
int __wrap_cyw43_arch_wifi_connect_bssid_timeout_ms(const char *ssid, const uint8_t *bssid, const char *pw, uint32_t auth, uint32_t timeout_ms) {
900-
return __real_cyw43_arch_wifi_connect_bssid_timeout_ms(ssid, bssid, pw, auth, timeout_ms);
901-
}
902-
extern int __real_cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout_ms);
903-
int __wrap_cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout_ms) {
904-
return __real_cyw43_arch_wifi_connect_timeout_ms(ssid, pw, auth, timeout_ms);
905-
}
906911
extern void __real_cyw43_arch_gpio_put(uint wl_gpio, bool value);
907912
void __wrap_cyw43_arch_gpio_put(uint wl_gpio, bool value) {
908913
__real_cyw43_arch_gpio_put(wl_gpio, value);

cores/rp2040/lwip_wrap.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ typedef enum {
167167

168168
__ethernet_input = 9000,
169169

170+
__cyw43_wifi_join = 9500,
171+
170172
__callback = 10000,
171173
} __lwip_op;
172174

@@ -230,6 +232,7 @@ extern void __real_raw_remove(struct raw_pcb *pcb);
230232
extern struct netif *__real_netif_add(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input);
231233
extern void __real_netif_remove(struct netif *netif);
232234
extern err_t __real_ethernet_input(struct pbuf *p, struct netif *netif);
235+
extern int __real_cyw43_wifi_join(cyw43_t * self, size_t ssid_len, const uint8_t * ssid, size_t key_len, const uint8_t * key, uint32_t auth_type, const uint8_t * bssid, uint32_t channel);
233236

234237

235238
typedef struct {
@@ -568,6 +571,18 @@ typedef struct {
568571
err_t *ret;
569572
} __ethernet_input_req;
570573

574+
typedef struct {
575+
cyw43_t * self;
576+
size_t ssid_len;
577+
const uint8_t *ssid;
578+
size_t key_len;
579+
const uint8_t *key;
580+
uint32_t auth_type;
581+
const uint8_t *bssid;
582+
uint32_t channel;
583+
int *ret;
584+
} __cyw43_wifi_join_req;
585+
571586
// Run a callback in the LWIP thread (i.e. for Ethernet device polling and packet reception)
572587
// When in an interrupt, need to pass in a heap-allocated buffer
573588
typedef struct {

cores/rp2040/sdkoverride/cyw43_driver_freertos.cpp

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -178,54 +178,6 @@ extern "C" void __wrap_cyw43_delay_us(uint32_t us) {
178178
delayMicroseconds(us);
179179
}
180180

181-
182-
183-
static int this_cyw43_arch_wifi_connect_bssid_until(const char *ssid, const uint8_t *bssid, const char *pw, uint32_t auth, uint32_t timeout_ms) {
184-
uint32_t start = millis();
185-
int err = cyw43_arch_wifi_connect_bssid_async(ssid, bssid, pw, auth);
186-
if (err) {
187-
return err;
188-
}
189-
int status = CYW43_LINK_UP + 1;
190-
while (status >= 0 && status != CYW43_LINK_UP) {
191-
int new_status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA);
192-
// If there was no network, keep trying
193-
if (new_status == CYW43_LINK_NONET) {
194-
new_status = CYW43_LINK_JOIN;
195-
err = cyw43_arch_wifi_connect_bssid_async(ssid, bssid, pw, auth);
196-
if (err) {
197-
return err;
198-
}
199-
}
200-
if (new_status != status) {
201-
status = new_status;
202-
}
203-
uint32_t delta = millis() - start;
204-
if (delta > timeout_ms) {
205-
return PICO_ERROR_TIMEOUT;
206-
}
207-
// Do polling
208-
//cyw43_arch_poll();
209-
__wrap_cyw43_await_background_or_timeout_us((timeout_ms - delta) * 1000); //cyw43_arch_wait_for_work_until(until);
210-
}
211-
// Turn status into a pico_error_codes, CYW43_LINK_NONET shouldn't happen as we fail with PICO_ERROR_TIMEOUT instead
212-
assert(status == CYW43_LINK_UP || status == CYW43_LINK_BADAUTH || status == CYW43_LINK_FAIL);
213-
if (status == CYW43_LINK_UP) {
214-
return PICO_OK; // success
215-
} else if (status == CYW43_LINK_BADAUTH) {
216-
return PICO_ERROR_BADAUTH;
217-
} else {
218-
return PICO_ERROR_CONNECT_FAILED;
219-
}
220-
}
221-
extern "C" int __wrap_cyw43_arch_wifi_connect_bssid_timeout_ms(const char *ssid, const uint8_t *bssid, const char *pw, uint32_t auth, uint32_t timeout_ms) {
222-
return this_cyw43_arch_wifi_connect_bssid_until(ssid, bssid, pw, auth, timeout_ms); //make_timeout_time_ms(timeout_ms));
223-
}
224-
225-
extern "C" int __wrap_cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout_ms) {
226-
return __wrap_cyw43_arch_wifi_connect_bssid_timeout_ms(ssid, nullptr, pw, auth, timeout_ms);
227-
}
228-
229181
extern "C" void __real_cyw43_arch_gpio_put(uint wl_gpio, bool value);
230182
void do_cyw43_arch_gpio_put(void *data) {
231183
uint32_t d = (uint32_t)data;

lib/core_wrap.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
-Wl,--wrap=cyw43_cb_process_ethernet
7575
-Wl,--wrap=cyw43_cb_tcpip_set_link_up
7676
-Wl,--wrap=cyw43_cb_tcpip_set_link_down
77-
-Wl,--wrap=cyw43_tcpip_link_status
7877
-Wl,--wrap=cyw43_cb_tcpip_init
7978
-Wl,--wrap=cyw43_cb_tcpip_deinit
8079

@@ -90,7 +89,6 @@
9089
-Wl,--wrap=cyw43_delay_us
9190
-Wl,--wrap=cyw43_post_poll_hook
9291
-Wl,--wrap=cyw43_schedule_internal_poll_dispatch
93-
-Wl,--wrap=cyw43_arch_wifi_connect_bssid_timeout_ms
94-
-Wl,--wrap=cyw43_arch_wifi_connect_timeout_ms
92+
-Wl,--wrap=cyw43_wifi_join
9593
-Wl,--wrap=cyw43_arch_gpio_put
9694
-Wl,--wrap=btstack_run_loop_async_context_get_instance

libraries/lwIP_CYW43/src/utility/CYW43shim.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,38 @@ bool CYW43::begin(const uint8_t* address, netif* netif) {
7979
cyw43_wifi_update_multicast_filter(&cyw43_state, mdnsV6, true);
8080
#endif
8181

82-
if (_bssid[0] | _bssid[1] | _bssid[2] | _bssid[3] | _bssid[4] | _bssid[5]) {
83-
if (cyw43_arch_wifi_connect_bssid_timeout_ms(_ssid, _bssid, _password, authmode, _timeout)) {
84-
return false;
85-
} else {
82+
cyw43_wifi_join(&cyw43_state, strlen(_ssid), (const uint8_t *)_ssid, strlen(_password), (const uint8_t *)_password, authmode, (_bssid[0] | _bssid[1] | _bssid[2] | _bssid[3] | _bssid[4] | _bssid[5]) ? _bssid : nullptr, CYW43_CHANNEL_NONE);
83+
uint32_t start = millis();
84+
while (millis() - start < _timeout) {
85+
auto link = cyw43_wifi_link_status(&cyw43_state, 0);
86+
if (link != 1) {
87+
// Some error, we can retry
88+
cyw43_wifi_join(&cyw43_state, strlen(_ssid), (const uint8_t *)_ssid, strlen(_password), (const uint8_t *)_password, authmode, (_bssid[0] | _bssid[1] | _bssid[2] | _bssid[3] | _bssid[4] | _bssid[5]) ? _bssid : nullptr, CYW43_CHANNEL_NONE);
89+
} else if (cyw43_state.wifi_join_state == 1) {
90+
// Link state can == 1 even if the negotiation is ongoing. Check the internal negotiaion state. When it hits 1 we are actually connected
8691
return true;
92+
} else {
93+
delay(50);
8794
}
88-
} else {
89-
if (cyw43_arch_wifi_connect_timeout_ms(_ssid, _password, authmode, _timeout)) {
90-
return false;
95+
}
96+
if (cyw43_wifi_link_status(&cyw43_state, 0) == 1) {
97+
// Now we may have just started a retry and the work is still in progress, or we're connected
98+
if (cyw43_state.wifi_join_state == 1) {
99+
return true; // We succeeded
91100
} else {
92-
return true;
101+
// We're still trying on our last try. Wait for things to change
102+
while (true) {
103+
if (cyw43_wifi_link_status(&cyw43_state, 0) != 1) {
104+
return false;
105+
} else if (cyw43_state.wifi_join_state == 1) {
106+
return true;
107+
} else {
108+
delay(50);
109+
}
110+
}
93111
}
94112
}
113+
return false; // We ended above with a failure
95114
} else {
96115
_itf = 1;
97116
cyw43_arch_enable_ap_mode(_ssid, _password, _password ? CYW43_AUTH_WPA2_AES_PSK : CYW43_AUTH_OPEN);

libraries/lwIP_Ethernet/src/LwipIntfDev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ bool LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu) {
402402
}
403403

404404
if (!RawDev::begin(_macAddress, &_netif)) {
405+
netif_remove(&_netif);
405406
return false;
406407
}
407408

@@ -420,6 +421,7 @@ bool LwipIntfDev<RawDev>::begin(const uint8_t* macAddress, const uint16_t mtu) {
420421
break;
421422

422423
case ERR_IF:
424+
netif_remove(&_netif);
423425
return false;
424426

425427
default:

0 commit comments

Comments
 (0)