Skip to content

Commit ade00f7

Browse files
Only 1 outstanding sleep poll, remove async_ctx
Completely null out the async_context used by the CYW43 driver to ensure it will crash immediately instead of just doing nothing should there be some driver code which uses it. Replace the connect routines to use our custom methods directly. Limit the outstanding sleep poll messages in the LWIP queue to 1. This avoids the case where, due to some long running operation, the sleep alarm ends up being called multiple times before actually processing the callback (which would flood the LWIP work queue and crash the machine).
1 parent 9eae58c commit ade00f7

File tree

4 files changed

+79
-10
lines changed

4 files changed

+79
-10
lines changed

cores/rp2040/lwip_wrap.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,14 @@ extern "C" {
887887
void __wrap_cyw43_schedule_internal_poll_dispatch(void (*func)()) {
888888
__real_cyw43_schedule_internal_poll_dispatch(func);
889889
}
890+
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);
891+
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) {
892+
return __real_cyw43_arch_wifi_connect_bssid_timeout_ms(ssid, bssid, pw, auth, timeout_ms);
893+
}
894+
extern int __real_cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout_ms);
895+
extern "C" int __wrap_cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout_ms) {
896+
return __real_cyw43_arch_wifi_connect_timeout_ms(ssid, pw, auth, timeout_ms);
897+
}
890898

891899
#endif
892900

cores/rp2040/sdkoverride/cyw43_arch_freertos.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,17 @@ async_context_t *cyw43_arch_init_default_async_context(void) {
5050
}
5151

5252
int cyw43_arch_init(void) {
53-
async_context_t *context = cyw43_arch_async_context();
54-
if (!context) {
55-
context = cyw43_arch_init_default_async_context();
56-
if (!context) {
57-
return PICO_ERROR_GENERIC;
58-
}
59-
cyw43_arch_set_async_context(context);
60-
}
53+
// async_context_t *context = cyw43_arch_async_context();
54+
// if (!context) {
55+
// context = cyw43_arch_init_default_async_context();
56+
// if (!context) {
57+
// return PICO_ERROR_GENERIC;
58+
// }
59+
// cyw43_arch_set_async_context(context);
60+
// }
61+
async_context_t *context = NULL;
62+
cyw43_arch_set_async_context(context);
63+
6164
bool ok = cyw43_driver_init(context);
6265
#if CYW43_LWIP
6366
ok &= lwip_freertos_init(context);

lib/core_wrap.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,5 @@
9090
-Wl,--wrap=cyw43_delay_us
9191
-Wl,--wrap=cyw43_post_poll_hook
9292
-Wl,--wrap=cyw43_schedule_internal_poll_dispatch
93-
93+
-Wl,--wrap=cyw43_arch_wifi_connect_bssid_timeout_ms
94+
-Wl,--wrap=cyw43_arch_wifi_connect_timeout_ms

libraries/lwIP_CYW43/src/cyw43_driver_freertos.cpp

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C" {
3939

4040
static SemaphoreHandle_t _cyw43_arch_mutex;
4141
static SemaphoreHandle_t _cyw43_irq_called_binary;
42+
static SemaphoreHandle_t _cyw43_sleep_poll_binary;
4243

4344
static void cb_cyw43_do_poll(void *context);
4445
static __callback_req _irqBuffer;
@@ -86,12 +87,17 @@ extern "C" void __wrap_cyw43_schedule_internal_poll_dispatch(__unused void (*fun
8687
lwip_callback(cb_cyw43_do_poll, nullptr);
8788
}
8889

90+
91+
8992
static int64_t cb_cyw43_sleep_timeout_reached(alarm_id_t id, void *ptr) {
9093
(void) id;
9194
(void) ptr;
9295
static __callback_req _sleepIRQBuffer;
9396
// This will be in IRQ context, so do a lwip callback. Only one at a time can be outstanding so this single struct is good enough
94-
lwip_callback(cb_cyw43_do_poll, nullptr, &_sleepIRQBuffer);
97+
BaseType_t pxHigherPriorityTaskWoken;
98+
if (xSemaphoreTakeFromISR(_cyw43_sleep_poll_binary, &pxHigherPriorityTaskWoken)) {
99+
lwip_callback(cb_cyw43_do_poll, nullptr, &_sleepIRQBuffer);
100+
}
95101
return 0; // Don't reschedule
96102
}
97103

@@ -100,6 +106,7 @@ static void cb_cyw43_do_poll(void *context) { //, __unused async_when_pending_wo
100106
#ifndef NDEBUG
101107
assert(get_core_num() == 0);
102108
#endif
109+
cyw43_thread_enter();
103110
if (cyw43_poll) {
104111
if (cyw43_sleep > 0) {
105112
cyw43_sleep--;
@@ -111,12 +118,17 @@ static void cb_cyw43_do_poll(void *context) { //, __unused async_when_pending_wo
111118
// Nothing to do. We have 1-shot alarms
112119
}
113120
}
121+
cyw43_thread_exit();
122+
xSemaphoreGive(_cyw43_irq_called_binary);
123+
xSemaphoreGive(_cyw43_sleep_poll_binary);
114124
}
115125

116126
extern "C" bool __wrap_cyw43_driver_init(async_context_t *context) {
117127
assert(get_core_num() == 0);
118128
_cyw43_arch_mutex = xSemaphoreCreateRecursiveMutex();
119129
_cyw43_irq_called_binary = xSemaphoreCreateBinary();
130+
_cyw43_sleep_poll_binary = xSemaphoreCreateBinary();
131+
xSemaphoreGive(_cyw43_sleep_poll_binary);
120132
cyw43_init(&cyw43_state);
121133
cyw43_irq_init(nullptr);
122134
return true;
@@ -144,6 +156,7 @@ extern "C" void __wrap_cyw43_thread_lock_check() {
144156
#endif
145157

146158
extern "C" void __wrap_cyw43_await_background_or_timeout_us(uint32_t timeout_us) {
159+
// cyw43_set_irq_enabled(true);
147160
if (__get_current_exception() > 0) {
148161
vTaskDelay((timeout_us / 1000) / portTICK_PERIOD_MS);
149162
return;
@@ -165,4 +178,48 @@ extern "C" void __wrap_cyw43_delay_us(uint32_t us) {
165178
delayMicroseconds(us);
166179
}
167180

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) return err;
187+
int status = CYW43_LINK_UP + 1;
188+
while(status >= 0 && status != CYW43_LINK_UP) {
189+
int new_status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA);
190+
// If there was no network, keep trying
191+
if (new_status == CYW43_LINK_NONET) {
192+
new_status = CYW43_LINK_JOIN;
193+
err = cyw43_arch_wifi_connect_bssid_async(ssid, bssid, pw, auth);
194+
if (err) return err;
195+
}
196+
if (new_status != status) {
197+
status = new_status;
198+
}
199+
uint32_t delta = millis() - start;
200+
if (delta > timeout_ms) {
201+
return PICO_ERROR_TIMEOUT;
202+
}
203+
// Do polling
204+
//cyw43_arch_poll();
205+
__wrap_cyw43_await_background_or_timeout_us((timeout_ms - delta) * 1000); //cyw43_arch_wait_for_work_until(until);
206+
}
207+
// Turn status into a pico_error_codes, CYW43_LINK_NONET shouldn't happen as we fail with PICO_ERROR_TIMEOUT instead
208+
assert(status == CYW43_LINK_UP || status == CYW43_LINK_BADAUTH || status == CYW43_LINK_FAIL);
209+
if (status == CYW43_LINK_UP) {
210+
return PICO_OK; // success
211+
} else if (status == CYW43_LINK_BADAUTH) {
212+
return PICO_ERROR_BADAUTH;
213+
} else {
214+
return PICO_ERROR_CONNECT_FAILED;
215+
}
216+
}
217+
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) {
218+
return this_cyw43_arch_wifi_connect_bssid_until(ssid, bssid, pw, auth, timeout_ms); //make_timeout_time_ms(timeout_ms));
219+
}
220+
221+
extern "C" int __wrap_cyw43_arch_wifi_connect_timeout_ms(const char *ssid, const char *pw, uint32_t auth, uint32_t timeout_ms) {
222+
return __wrap_cyw43_arch_wifi_connect_bssid_timeout_ms(ssid, nullptr, pw, auth, timeout_ms);
223+
}
224+
168225
#endif

0 commit comments

Comments
 (0)