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