1 /* 2 * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include "pico/async_context.h" 8 #include "pico/time.h" 9 #include "lwip/tcpip.h" 10 #include "lwip/timeouts.h" 11 12 #include "FreeRTOS.h" 13 #include "semphr.h" 14 15 #if NO_SYS 16 #error lwip_freertos_async_context_bindings requires NO_SYS=0 17 #endif 18 19 static async_context_t * volatile lwip_context; 20 // lwIP tcpip_task cannot be shutdown, so we block it when we are de-initialized. 21 static SemaphoreHandle_t tcpip_task_blocker; 22 tcpip_init_done(void * param)23static void tcpip_init_done(void *param) { 24 xSemaphoreGive((SemaphoreHandle_t)param); 25 } 26 lwip_freertos_init(async_context_t * context)27bool lwip_freertos_init(async_context_t *context) { 28 assert(!lwip_context); 29 lwip_context = context; 30 static bool done_lwip_init; 31 if (!done_lwip_init) { 32 done_lwip_init = true; 33 SemaphoreHandle_t init_sem = xSemaphoreCreateBinary(); 34 tcpip_task_blocker = xSemaphoreCreateBinary(); 35 tcpip_init(tcpip_init_done, init_sem); 36 xSemaphoreTake(init_sem, portMAX_DELAY); 37 vSemaphoreDelete(init_sem); 38 } else { 39 xSemaphoreGive(tcpip_task_blocker); 40 } 41 return true; 42 } 43 clear_lwip_context(__unused void * param)44static uint32_t clear_lwip_context(__unused void *param) { 45 lwip_context = NULL; 46 return 0; 47 } 48 lwip_freertos_deinit(__unused async_context_t * context)49void lwip_freertos_deinit(__unused async_context_t *context) { 50 // clear the lwip context under lock as lwIP may still be running in tcpip_task 51 async_context_execute_sync(context, clear_lwip_context, NULL); 52 } 53 pico_lwip_custom_lock_tcpip_core(void)54void pico_lwip_custom_lock_tcpip_core(void) { 55 while (!lwip_context) { 56 xSemaphoreTake(tcpip_task_blocker, portMAX_DELAY); 57 } 58 async_context_acquire_lock_blocking(lwip_context); 59 } 60 pico_lwip_custom_unlock_tcpip_core(void)61void pico_lwip_custom_unlock_tcpip_core(void) { 62 async_context_release_lock(lwip_context); 63 } 64