Unverified Commit 01ee673d authored by Earle F. Philhower, III's avatar Earle F. Philhower, III Committed by GitHub

Protect the HW random generation from FreeRTOS (#1395)

Fixes #1394

The Pico_Rand SDK calls gather bits from the HW ROSC at precise intervals.
If there is jitter in the sleep_until() call then the ROSC bit collection
will always think it's failed to acquire the right bit and retry infintitely.

Avoid by wrapping the HW random number calls and the sleep_until() routine.
Only when in FreeRTOS set a flag to silently make sleep_until() into a
busy wait loop while in a random number generation step.  When not in the
random code, do the normal sleep_until call.
parent 5a949443
......@@ -21,6 +21,7 @@
#include "_freertos.h"
#include "pico/mutex.h"
#include <stdlib.h>
#include "Arduino.h"
typedef struct {
mutex_t *src;
......@@ -59,3 +60,45 @@ 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);
}
}
}
......@@ -207,3 +207,7 @@
-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
......@@ -10,7 +10,7 @@ for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S ./libraries/SingleF
./libraries/Updater ./libraries/HTTPClient ./libraries/HTTPUpdate \
./libraries/WebServer ./libraries/HTTPUpdateServer ./libraries/DNSServer \
./libraries/Joystick ./libraries/Keyboard ./libraries/Mouse \
./libraries/JoystickBT ./libraries/KeyboardBT ./variants ./libraries/BTstack \
./libraries/JoystickBT ./libraries/KeyboardBT ./variants ./libraries/BTstackLib \
./libraries/MouseBT ./libraries/SerialBT ./libraries/HID_Bluetooth \
./libraries/JoystickBLE ./libraries/KeyboardBLE ./libraries/MouseBLE ; do
find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" \) -a \! -path '*api*' -exec astyle --suffix=none --options=./tests/astyle_core.conf \{\} \;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment