1 /*
2  * Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #if PICO_CYW43_ARCH_FREERTOS
8 
9 #include "pico/cyw43_arch.h"
10 #include "pico/cyw43_driver.h"
11 #include "pico/async_context_freertos.h"
12 
13 #if CYW43_LWIP
14 #include "pico/lwip_freertos.h"
15 #include <lwip/tcpip.h>
16 #endif
17 
18 #if CYW43_ENABLE_BLUETOOTH
19 #include "pico/btstack_cyw43.h"
20 #endif
21 
22 #if NO_SYS
23 #error example_cyw43_arch_freetos_sys requires NO_SYS=0
24 #endif
25 
26 static async_context_freertos_t cyw43_async_context_freertos;
27 
cyw43_arch_init_default_async_context(void)28 async_context_t *cyw43_arch_init_default_async_context(void) {
29     async_context_freertos_config_t config = async_context_freertos_default_config();
30 #ifdef CYW43_TASK_PRIORITY
31     config.task_priority = CYW43_TASK_PRIORITY;
32 #endif
33 #ifdef CYW43_TASK_STACK_SIZE
34     config.task_stack_size = CYW43_TASK_STACK_SIZE;
35 #endif
36     if (async_context_freertos_init(&cyw43_async_context_freertos, &config))
37         return &cyw43_async_context_freertos.core;
38     return NULL;
39 }
40 
cyw43_arch_init(void)41 int cyw43_arch_init(void) {
42     async_context_t *context = cyw43_arch_async_context();
43     if (!context) {
44         context = cyw43_arch_init_default_async_context();
45         if (!context) return PICO_ERROR_GENERIC;
46         cyw43_arch_set_async_context(context);
47     }
48     bool ok = cyw43_driver_init(context);
49 #if CYW43_LWIP
50     ok &= lwip_freertos_init(context);
51 #endif
52 #if CYW43_ENABLE_BLUETOOTH
53     ok &= btstack_cyw43_init(context);
54 #endif
55     if (!ok) {
56         cyw43_arch_deinit();
57         return PICO_ERROR_GENERIC;
58     } else {
59         return 0;
60     }
61 }
62 
cyw43_arch_deinit(void)63 void cyw43_arch_deinit(void) {
64     async_context_t *context = cyw43_arch_async_context();
65 #if CYW43_ENABLE_BLUETOOTH
66     btstack_cyw43_deinit(context);
67 #endif
68     // there is a bit of a circular dependency here between lwIP and cyw43_driver. We
69     // shut down cyw43_driver first as it has IRQs calling back into lwIP. Also lwIP itself
70     // does not actually get shut down.
71     // todo add a "pause" method to async_context if we need to provide some atomicity (we
72     //      don't want to take the lock as these methods may invoke execute_sync()
73     cyw43_driver_deinit(context);
74 #if CYW43_LWIP
75     lwip_freertos_deinit(context);
76 #endif
77     // if it is our context, then we de-init it.
78     if (context == &cyw43_async_context_freertos.core) {
79         async_context_deinit(context);
80         cyw43_arch_set_async_context(NULL);
81     }
82 }
83 
84 #endif