Avoid freezeing the core from LWIP under FreeRTOS (#1884)
Avoid issues with interrupts and priority inversions and other deadlocks and use a SW based random generator for LWIP when under FreeRTOS. This means removing any overrides for sleep_until and the two get_rand_xx calls from the SDK, making things much saner. Related to #1883, #1872, and other random FreeRTOS lockups.
This commit is contained in:
parent
81070a0b3f
commit
2bf249ffe1
12 changed files with 1500 additions and 53 deletions
|
|
@ -252,14 +252,14 @@ If you want to contribute or have bugfixes, drop me a note at <earlephilhower@ya
|
||||||
* [UF2CONV.PY](https://github.com/microsoft/uf2) is by Microsoft Corporation and licensed under the MIT license.
|
* [UF2CONV.PY](https://github.com/microsoft/uf2) is by Microsoft Corporation and licensed under the MIT license.
|
||||||
* Networking and filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
|
* Networking and filesystem code taken from the [ESP8266 Arduino Core](https://github.com/esp8266/Arduino) and licensed under the LGPL.
|
||||||
* DHCP server for AP host mode from the [Micropython Project](https://micropython.org), distributed under the MIT License.
|
* DHCP server for AP host mode from the [Micropython Project](https://micropython.org), distributed under the MIT License.
|
||||||
* [FreeRTOS](https://freertos.org) is Copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
|
* [FreeRTOS](https://freertos.org) is copyright Amazon.com, Inc. or its affiliates, and distributed under the MIT license.
|
||||||
* [lwIP](https://savannah.nongnu.org/projects/lwip/) is (c) the Swedish Institute of Computer Science and licenced under the BSD license.
|
* [lwIP](https://savannah.nongnu.org/projects/lwip/) is (c) the Swedish Institute of Computer Science and licenced under the BSD license.
|
||||||
* [BearSSL](https://bearssl.org) library written by Thomas Pornin, is distributed under the [MIT License](https://bearssl.org/#legal-details).
|
* [BearSSL](https://bearssl.org) library written by Thomas Pornin, is distributed under the [MIT License](https://bearssl.org/#legal-details).
|
||||||
* [UZLib](https://github.com/pfalcon/uzlib) is copyright (c) 2003 Joergen Ibsen and distributed under the zlib license.
|
* [UZLib](https://github.com/pfalcon/uzlib) is copyright (c) 2003 Joergen Ibsen and distributed under the zlib license.
|
||||||
* [LEAmDNS](https://github.com/LaborEtArs/ESP8266mDNS) is copyright multiple authors and distributed under the MIT license.
|
* [LEAmDNS](https://github.com/LaborEtArs/ESP8266mDNS) is copyright multiple authors and distributed under the MIT license.
|
||||||
* [http-parser](https://github.com/nodejs/http-parser) is copyright Joyent, Inc. and other Node contributors.
|
* [http-parser](https://github.com/nodejs/http-parser) is copyright Joyent, Inc. and other Node contributors.
|
||||||
* WebServer code modified from the [ESP32 WebServer](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer) and is copyright (c) 2015 Ivan Grokhotkov and others
|
* WebServer code modified from the [ESP32 WebServer](https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer) and is copyright (c) 2015 Ivan Grokhotkov and others.
|
||||||
|
* [Xoshiro-cpp](https://github.com/Reputeless/Xoshiro-cpp) is copyright (c) 2020 Ryo Suzuki and distributed under the MIT license.
|
||||||
|
|
||||||
-Earle F. Philhower, III
|
-Earle F. Philhower, III
|
||||||
earlephilhower@yahoo.com
|
earlephilhower@yahoo.com
|
||||||
|
|
|
||||||
|
|
@ -60,45 +60,3 @@ SemaphoreHandle_t __get_freertos_mutex_for_ptr(mutex_t *m, bool recursive) {
|
||||||
}
|
}
|
||||||
return nullptr; // Need to make space for more mutex maps!
|
return nullptr; // Need to make space for more mutex maps!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The HW Random code needs a precise sleep_until() in order to assure it
|
|
||||||
// grabs the ROSC bit when it wants. Unfortunately, under FreeRTOS the
|
|
||||||
// sleep_until() becomes imprecise and the "did I get the bit when I wanted"
|
|
||||||
// check in the pico_rand code always fails and you get an infinite loop.
|
|
||||||
|
|
||||||
// This block wraps the 2 get_rand calls to set a flag to convert
|
|
||||||
// sleep_until() (which can do a task swap and cause bad timing) into a
|
|
||||||
// busy wait.
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
static bool __inRand = false;
|
|
||||||
|
|
||||||
extern uint64_t __real_get_rand_64();
|
|
||||||
uint64_t __wrap_get_rand_64() {
|
|
||||||
if (__isFreeRTOS) {
|
|
||||||
rp2040.idleOtherCore();
|
|
||||||
__inRand = true;
|
|
||||||
auto r = __real_get_rand_64();
|
|
||||||
__inRand = false;
|
|
||||||
rp2040.resumeOtherCore();
|
|
||||||
return r;
|
|
||||||
} else {
|
|
||||||
return __real_get_rand_64();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t __wrap_get_rand_32() {
|
|
||||||
return (uint32_t) __wrap_get_rand_64();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void __real_sleep_until(absolute_time_t t);
|
|
||||||
void __wrap_sleep_until(absolute_time_t t) {
|
|
||||||
if (__inRand) {
|
|
||||||
busy_wait_until(t);
|
|
||||||
} else {
|
|
||||||
__real_sleep_until(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
||||||
1478
cores/rp2040/_xoshiro.h
Normal file
1478
cores/rp2040/_xoshiro.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -29,6 +29,7 @@
|
||||||
#include <pico/cyw43_arch.h>
|
#include <pico/cyw43_arch.h>
|
||||||
#include <pico/mutex.h>
|
#include <pico/mutex.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
|
#include "_xoshiro.h"
|
||||||
|
|
||||||
extern void ethernet_arch_lwip_begin() __attribute__((weak));
|
extern void ethernet_arch_lwip_begin() __attribute__((weak));
|
||||||
extern void ethernet_arch_lwip_end() __attribute__((weak));
|
extern void ethernet_arch_lwip_end() __attribute__((weak));
|
||||||
|
|
@ -68,11 +69,25 @@ public:
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
static XoshiroCpp::Xoshiro256PlusPlus *_lwip_rng = nullptr;
|
||||||
|
// Random number generator for LWIP. Bare metal, use the HW. FreeRTOS, use xoshiro generator to avoid needing to freeze the other core
|
||||||
|
unsigned long __lwip_rand() {
|
||||||
|
if (__isFreeRTOS) {
|
||||||
|
return (unsigned long)(*_lwip_rng)();
|
||||||
|
} else {
|
||||||
|
return get_rand_32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Avoid calling lwip_init multiple times
|
// Avoid calling lwip_init multiple times
|
||||||
extern void __real_lwip_init();
|
extern void __real_lwip_init();
|
||||||
void __wrap_lwip_init() {
|
void __wrap_lwip_init() {
|
||||||
static bool initted = false;
|
static bool initted = false;
|
||||||
if (!initted) {
|
if (!initted) {
|
||||||
|
if (__isFreeRTOS) {
|
||||||
|
_lwip_rng = new XoshiroCpp::Xoshiro256PlusPlus(rp2040.getCycleCount());
|
||||||
|
}
|
||||||
__real_lwip_init();
|
__real_lwip_init();
|
||||||
initted = true;
|
initted = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ extern void interrupts();
|
||||||
#define SYS_ARCH_PROTECT(lev) noInterrupts
|
#define SYS_ARCH_PROTECT(lev) noInterrupts
|
||||||
#define SYS_ARCH_UNPROTECT(lev) interrupts
|
#define SYS_ARCH_UNPROTECT(lev) interrupts
|
||||||
|
|
||||||
extern unsigned long get_rand_32(void);
|
extern unsigned long __lwip_rand(void);
|
||||||
#define LWIP_RAND() get_rand_32()
|
#define LWIP_RAND() __lwip_rand()
|
||||||
|
|
||||||
// Common settings used in most of the pico_w examples
|
// Common settings used in most of the pico_w examples
|
||||||
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
|
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
|
||||||
|
|
|
||||||
BIN
lib/libpico.a
BIN
lib/libpico.a
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -209,7 +209,3 @@
|
||||||
-Wl,--wrap=cyw43_tcpip_link_status
|
-Wl,--wrap=cyw43_tcpip_link_status
|
||||||
-Wl,--wrap=cyw43_cb_tcpip_init
|
-Wl,--wrap=cyw43_cb_tcpip_init
|
||||||
-Wl,--wrap=cyw43_cb_tcpip_deinit
|
-Wl,--wrap=cyw43_cb_tcpip_deinit
|
||||||
|
|
||||||
-Wl,--wrap=get_rand_64
|
|
||||||
-Wl,--wrap=get_rand_32
|
|
||||||
-Wl,--wrap=sleep_until
|
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ extern void interrupts();
|
||||||
#define SYS_ARCH_PROTECT(lev) noInterrupts
|
#define SYS_ARCH_PROTECT(lev) noInterrupts
|
||||||
#define SYS_ARCH_UNPROTECT(lev) interrupts
|
#define SYS_ARCH_UNPROTECT(lev) interrupts
|
||||||
|
|
||||||
extern unsigned long get_rand_32(void);
|
extern unsigned long __lwip_rand(void);
|
||||||
#define LWIP_RAND() get_rand_32()
|
#define LWIP_RAND() __lwip_rand()
|
||||||
|
|
||||||
// Common settings used in most of the pico_w examples
|
// Common settings used in most of the pico_w examples
|
||||||
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
|
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue