| /* |
| * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include "pico/async_context.h" |
| #include "pico/time.h" |
| #include "lwip/tcpip.h" |
| #include "lwip/timeouts.h" |
| |
| #include "FreeRTOS.h" |
| #include "semphr.h" |
| |
| #if NO_SYS |
| #error lwip_freertos_async_context_bindings requires NO_SYS=0 |
| #endif |
| |
| static async_context_t * volatile lwip_context; |
| // lwIP tcpip_task cannot be shutdown, so we block it when we are de-initialized. |
| static SemaphoreHandle_t tcpip_task_blocker; |
| |
| static void tcpip_init_done(void *param) { |
| xSemaphoreGive((SemaphoreHandle_t)param); |
| } |
| |
| bool lwip_freertos_init(async_context_t *context) { |
| assert(!lwip_context); |
| lwip_context = context; |
| static bool done_lwip_init; |
| if (!done_lwip_init) { |
| done_lwip_init = true; |
| SemaphoreHandle_t init_sem = xSemaphoreCreateBinary(); |
| tcpip_task_blocker = xSemaphoreCreateBinary(); |
| tcpip_init(tcpip_init_done, init_sem); |
| xSemaphoreTake(init_sem, portMAX_DELAY); |
| vSemaphoreDelete(init_sem); |
| } else { |
| xSemaphoreGive(tcpip_task_blocker); |
| } |
| return true; |
| } |
| |
| static uint32_t clear_lwip_context(__unused void *param) { |
| lwip_context = NULL; |
| return 0; |
| } |
| |
| void lwip_freertos_deinit(__unused async_context_t *context) { |
| // clear the lwip context under lock as lwIP may still be running in tcpip_task |
| async_context_execute_sync(context, clear_lwip_context, NULL); |
| } |
| |
| void pico_lwip_custom_lock_tcpip_core(void) { |
| while (!lwip_context) { |
| xSemaphoreTake(tcpip_task_blocker, portMAX_DELAY); |
| } |
| async_context_acquire_lock_blocking(lwip_context); |
| } |
| |
| void pico_lwip_custom_unlock_tcpip_core(void) { |
| async_context_release_lock(lwip_context); |
| } |