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.
|
||||
* 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.
|
||||
* [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.
|
||||
* [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.
|
||||
* [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.
|
||||
* 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
|
||||
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!
|
||||
}
|
||||
|
||||
|
||||
// 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/mutex.h>
|
||||
#include <sys/lock.h>
|
||||
#include "_xoshiro.h"
|
||||
|
||||
extern void ethernet_arch_lwip_begin() __attribute__((weak));
|
||||
extern void ethernet_arch_lwip_end() __attribute__((weak));
|
||||
|
|
@ -68,11 +69,25 @@ public:
|
|||
|
||||
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
|
||||
extern void __real_lwip_init();
|
||||
void __wrap_lwip_init() {
|
||||
static bool initted = false;
|
||||
if (!initted) {
|
||||
if (__isFreeRTOS) {
|
||||
_lwip_rng = new XoshiroCpp::Xoshiro256PlusPlus(rp2040.getCycleCount());
|
||||
}
|
||||
__real_lwip_init();
|
||||
initted = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ extern void interrupts();
|
|||
#define SYS_ARCH_PROTECT(lev) noInterrupts
|
||||
#define SYS_ARCH_UNPROTECT(lev) interrupts
|
||||
|
||||
extern unsigned long get_rand_32(void);
|
||||
#define LWIP_RAND() get_rand_32()
|
||||
extern unsigned long __lwip_rand(void);
|
||||
#define LWIP_RAND() __lwip_rand()
|
||||
|
||||
// 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)
|
||||
|
|
|
|||
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_cb_tcpip_init
|
||||
-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_UNPROTECT(lev) interrupts
|
||||
|
||||
extern unsigned long get_rand_32(void);
|
||||
#define LWIP_RAND() get_rand_32()
|
||||
extern unsigned long __lwip_rand(void);
|
||||
#define LWIP_RAND() __lwip_rand()
|
||||
|
||||
// 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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue