3131#include < pico/async_context_freertos.h>
3232#include " FreeRTOS.h"
3333#include " task.h"
34- // static async_context_freertos_t lwip_ethernet_async_context;
35- // static StackType_t lwip_ethernet_async_context_freertos_task_stack[CYW43_TASK_STACK_SIZE];
36-
37- // static async_context_t *lwip_ethernet_init_default_async_context(void) {
38- // async_context_freertos_config_t config = async_context_freertos_default_config();
39- // #if configSUPPORT_STATIC_ALLOCATION && !CYW43_NO_DEFAULT_TASK_STACK
40- // config.task_stack = lwip_ethernet_async_context_freertos_task_stack;
41- // #endif
42- // if (async_context_freertos_init(&lwip_ethernet_async_context, &config)) {
43- // return &lwip_ethernet_async_context.core;
44- // }
45- // return NULL;
46- // }
47-
34+ #include " semphr.h"
35+ static SemaphoreHandle_t _lwip_ethernet_mutex;
4836#else
4937#include < pico/async_context_threadsafe_background.h>
5038static async_context_threadsafe_background_t lwip_ethernet_async_context;
@@ -56,6 +44,10 @@ static async_context_t *lwip_ethernet_init_default_async_context(void) {
5644 }
5745 return NULL ;
5846}
47+ // Async context that pumps the ethernet controllers
48+ static async_when_pending_worker_t always_pending_update_timeout_worker;
49+ static async_at_time_worker_t ethernet_timeout_worker;
50+ static async_context_t *_context = nullptr ;
5951
6052#endif
6153
@@ -64,36 +56,37 @@ static async_context_t *lwip_ethernet_init_default_async_context(void) {
6456
6557bool __ethernetContextInitted = false ;
6658
67- // Async context that pumps the ethernet controllers
68- static async_when_pending_worker_t always_pending_update_timeout_worker;
69- static async_at_time_worker_t ethernet_timeout_worker;
70- static async_context_t *_context = nullptr ;
7159
7260// Theoretically support multiple interfaces
7361static std::map<int , std::function<void (void )>> _handlePacketList;
7462
7563void ethernet_arch_lwip_begin () {
64+ __startEthernetContext ();
7665#ifdef __FREERTOS
77- panic (" oops" );
66+ xSemaphoreTake (_lwip_ethernet_mutex, portMAX_DELAY);
67+ #else
68+ #if defined(PICO_CYW43_SUPPORTED)
69+ if (rp2040.isPicoW ()) {
70+ cyw43_arch_lwip_begin ();
71+ return ;
72+ }
73+ #endif
74+ async_context_acquire_lock_blocking (_context);
7875#endif
79- #if defined(PICO_CYW43_SUPPORTED)
80- if (rp2040.isPicoW ()) {
81- cyw43_arch_lwip_begin ();
82- return ;
83- }
84- #endif
85- __startEthernetContext ();
86- async_context_acquire_lock_blocking (_context);
8776}
8877
8978void ethernet_arch_lwip_end () {
90- #if defined(PICO_CYW43_SUPPORTED)
91- if (rp2040.isPicoW ()) {
92- cyw43_arch_lwip_end ();
93- return ;
94- }
95- #endif
96- async_context_release_lock (_context);
79+ #ifdef __FREERTOS
80+ xSemaphoreGive (_lwip_ethernet_mutex);
81+ #else
82+ #if defined(PICO_CYW43_SUPPORTED)
83+ if (rp2040.isPicoW ()) {
84+ cyw43_arch_lwip_end ();
85+ return ;
86+ }
87+ #endif
88+ async_context_release_lock (_context);
89+ #endif
9790}
9891
9992int __addEthernetPacketHandler (std::function<void (void )> _packetHandler) {
@@ -207,24 +200,6 @@ int hostByName(const char* aHostname, IPAddress& aResult, int timeout_ms) {
207200
208201uint32_t __ethernet_timeout_reached_calls = 0 ;
209202static uint32_t _pollingPeriod = 20 ;
210- // This will only be called under the protection of the async context mutex, so no re-entrancy checks needed
211- static void ethernet_timeout_reached (__unused async_context_t *context, __unused async_at_time_worker_t *worker) {
212- assert (worker == ðernet_timeout_worker);
213- __ethernet_timeout_reached_calls++;
214- ethernet_arch_lwip_gpio_mask (); // Ensure non-polled devices won't interrupt us
215- for (auto handlePacket : _handlePacketList) {
216- handlePacket.second ();
217- sys_check_timeouts ();
218- }
219- ethernet_arch_lwip_gpio_unmask ();
220- }
221-
222- static void update_next_timeout (async_context_t *context, async_when_pending_worker_t *worker) {
223- assert (worker == &always_pending_update_timeout_worker);
224- worker->work_pending = true ;
225- async_context_add_at_time_worker_in_ms (context, ðernet_timeout_worker, _pollingPeriod);
226- }
227-
228203
229204// We have a background pump which calls sys_check_timeouts on a periodic basis
230205// and polls all Ethernet interfaces
@@ -255,24 +230,44 @@ static void ethernetTask(void *param) {
255230 lwip_callback (stage2, nullptr );
256231 }
257232}
233+ #else
234+ // This will only be called under the protection of the async context mutex, so no re-entrancy checks needed
235+ static void ethernet_timeout_reached (__unused async_context_t *context, __unused async_at_time_worker_t *worker) {
236+ assert (worker == ðernet_timeout_worker);
237+ __ethernet_timeout_reached_calls++;
238+ ethernet_arch_lwip_gpio_mask (); // Ensure non-polled devices won't interrupt us
239+ for (auto handlePacket : _handlePacketList) {
240+ handlePacket.second ();
241+ sys_check_timeouts ();
242+ }
243+ ethernet_arch_lwip_gpio_unmask ();
244+ }
245+
246+ static void update_next_timeout (async_context_t *context, async_when_pending_worker_t *worker) {
247+ assert (worker == &always_pending_update_timeout_worker);
248+ worker->work_pending = true ;
249+ async_context_add_at_time_worker_in_ms (context, ðernet_timeout_worker, _pollingPeriod);
250+ }
258251#endif
259252
253+
260254void __startEthernetContext () {
261255 if (__ethernetContextInitted) {
262256 return ;
263257 }
264258#ifdef __FREERTOS
259+ _lwip_ethernet_mutex = xSemaphoreCreateMutex ();
265260 xTaskCreate (ethernetTask, " EthPoll" , 256 , nullptr , 1 , &_ethernetTask);
266261#else
267- #if defined(PICO_CYW43_SUPPORTED)
262+ #if defined(PICO_CYW43_SUPPORTED)
268263 if (rp2040.isPicoW ()) {
269264 _context = cyw43_arch_async_context ();
270265 } else {
271266 _context = lwip_ethernet_init_default_async_context ();
272267 }
273- #else
268+ #else
274269 _context = lwip_ethernet_init_default_async_context ();
275- #endif
270+ #endif
276271 ethernet_timeout_worker.do_work = ethernet_timeout_reached;
277272 always_pending_update_timeout_worker.work_pending = true ;
278273 always_pending_update_timeout_worker.do_work = update_next_timeout;
0 commit comments