From 4df7186945eee9236d59f4bc32e6053d4c686142 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Fri, 1 Jan 2021 18:51:38 +0100 Subject: [PATCH 01/21] delay0isyield squash commit. --- cores/esp8266/Esp.cpp | 2 -- cores/esp8266/PolledTimeout.h | 3 ++- cores/esp8266/core_esp8266_main.cpp | 9 +++++++++ cores/esp8266/core_esp8266_postmortem.cpp | 6 +++--- cores/esp8266/core_esp8266_waveform_phase.cpp | 2 +- cores/esp8266/core_esp8266_waveform_pwm.cpp | 6 +++--- cores/esp8266/core_esp8266_wiring.cpp | 5 +---- cores/esp8266/coredecls.h | 1 + cores/esp8266/uart.cpp | 15 ++++++++------- .../ESP8266HTTPClient/src/ESP8266HTTPClient.cpp | 6 ++++-- .../src/ESP8266HTTPUpdateServer-impl.h | 3 ++- .../ESP8266WiFi/examples/WiFiScan/WiFiScan.ino | 2 +- libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp | 8 ++------ libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 7 ++++--- libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp | 5 ++--- libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp | 7 +++---- .../ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp | 1 - libraries/ESP8266WiFi/src/include/ClientContext.h | 7 +++---- libraries/ESP8266WiFi/src/include/UdpContext.h | 2 +- .../examples/SerialStress/SerialStress.ino | 2 +- tests/host/common/Arduino.cpp | 7 +++++++ tests/host/common/include/ClientContext.h | 3 --- tests/host/common/user_interface.cpp | 4 ---- 23 files changed, 58 insertions(+), 55 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index 41d0592f31..dba0205164 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -115,8 +115,6 @@ void EspClass::wdtFeed(void) system_soft_wdt_feed(); } -extern "C" void esp_yield(); - void EspClass::deepSleep(uint64_t time_us, WakeMode mode) { system_deep_sleep_set_option(static_cast(mode)); diff --git a/cores/esp8266/PolledTimeout.h b/cores/esp8266/PolledTimeout.h index 7eec547e48..a8da626ad5 100644 --- a/cores/esp8266/PolledTimeout.h +++ b/cores/esp8266/PolledTimeout.h @@ -27,6 +27,7 @@ #include // std::numeric_limits #include // std::is_unsigned #include +#include namespace esp8266 { @@ -45,7 +46,7 @@ struct DoNothing struct YieldOrSkip { - static void execute() {delay(0);} + static void execute() {esp_break();} }; template diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index ff95d08cfb..92472f7997 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -128,6 +128,15 @@ extern "C" IRAM_ATTR void esp_schedule() { ets_post(LOOP_TASK_PRIORITY, 0, 0); } +// Replacement for delay(0). In CONT, same as yield(). Whereas yield() panics +// in SYS, esp_break() is safe to call and only schedules CONT. Use yield() +// whereever only called from CONT, use esp_break() if code is called from SYS +// or both CONT and SYS. +extern "C" void esp_break() { + esp_schedule(); + esp_yield(); +} + extern "C" void __yield() { if (can_yield()) { esp_schedule(); diff --git a/cores/esp8266/core_esp8266_postmortem.cpp b/cores/esp8266/core_esp8266_postmortem.cpp index 3e75342d05..17ac3d7edd 100644 --- a/cores/esp8266/core_esp8266_postmortem.cpp +++ b/cores/esp8266/core_esp8266_postmortem.cpp @@ -245,12 +245,12 @@ static void print_stack(uint32_t start, uint32_t end) { } } -static void uart_write_char_d(char c) { +static void ICACHE_RAM_ATTR uart_write_char_d(char c) { uart0_write_char_d(c); uart1_write_char_d(c); } -static void uart0_write_char_d(char c) { +static void ICACHE_RAM_ATTR uart0_write_char_d(char c) { while (((USS(0) >> USTXC) & 0xff)) { } if (c == '\n') { @@ -259,7 +259,7 @@ static void uart0_write_char_d(char c) { USF(0) = c; } -static void uart1_write_char_d(char c) { +static void ICACHE_RAM_ATTR uart1_write_char_d(char c) { while (((USS(1) >> USTXC) & 0xff) >= 0x7e) { } if (c == '\n') { diff --git a/cores/esp8266/core_esp8266_waveform_phase.cpp b/cores/esp8266/core_esp8266_waveform_phase.cpp index de2f914121..873dadede0 100644 --- a/cores/esp8266/core_esp8266_waveform_phase.cpp +++ b/cores/esp8266/core_esp8266_waveform_phase.cpp @@ -211,7 +211,7 @@ int startWaveformClockCycles_weak(uint8_t pin, uint32_t highCcys, uint32_t lowCc } std::atomic_thread_fence(std::memory_order_acq_rel); while (waveform.toSetBits) { - delay(0); // Wait for waveform to update + yield(); // Wait for waveform to update std::atomic_thread_fence(std::memory_order_acquire); } return true; diff --git a/cores/esp8266/core_esp8266_waveform_pwm.cpp b/cores/esp8266/core_esp8266_waveform_pwm.cpp index 916361e2ca..9ee80ffcc7 100644 --- a/cores/esp8266/core_esp8266_waveform_pwm.cpp +++ b/cores/esp8266/core_esp8266_waveform_pwm.cpp @@ -162,7 +162,7 @@ static IRAM_ATTR void _notifyPWM(PWMState *p, bool idle) { forceTimerInterrupt(); while (pwmState.pwmUpdate) { if (idle) { - delay(0); + yield(); } MEMBARRIER(); } @@ -372,7 +372,7 @@ int startWaveformClockCycles_weak(uint8_t pin, uint32_t timeHighCycles, uint32_t if (wvfState.waveformEnabled & mask) { // Make sure no waveform changes are waiting to be applied while (wvfState.waveformToChange) { - delay(0); // Wait for waveform to update + yield(); // Wait for waveform to update // No mem barrier here, the call to a global function implies global state updated } wvfState.waveformNewHigh = timeHighCycles; @@ -392,7 +392,7 @@ int startWaveformClockCycles_weak(uint8_t pin, uint32_t timeHighCycles, uint32_t initTimer(); forceTimerInterrupt(); while (wvfState.waveformToEnable) { - delay(0); // Wait for waveform to update + yield(); // Wait for waveform to update // No mem barrier here, the call to a global function implies global state updated } } diff --git a/cores/esp8266/core_esp8266_wiring.cpp b/cores/esp8266/core_esp8266_wiring.cpp index b956cebe43..b11d14a1d8 100644 --- a/cores/esp8266/core_esp8266_wiring.cpp +++ b/cores/esp8266/core_esp8266_wiring.cpp @@ -24,13 +24,10 @@ #include "osapi.h" #include "user_interface.h" #include "cont.h" +#include "coredecls.h" extern "C" { -extern void ets_delay_us(uint32_t us); -extern void esp_schedule(); -extern void esp_yield(); - static os_timer_t delay_timer; static os_timer_t micros_overflow_timer; static uint32_t micros_at_last_overflow_tick = 0; diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index b9c771df77..9f7fff2d07 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -15,6 +15,7 @@ extern "C" { bool can_yield(); void esp_yield(); void esp_schedule(); +void esp_break(); void tune_timeshift64 (uint64_t now_us); void disable_extra4k_at_link_time (void) __attribute__((noinline)); bool sntp_set_timezone_in_seconds(int32_t timezone); diff --git a/cores/esp8266/uart.cpp b/cores/esp8266/uart.cpp index de574d0bee..80e0cbffd0 100644 --- a/cores/esp8266/uart.cpp +++ b/cores/esp8266/uart.cpp @@ -41,6 +41,7 @@ * */ #include "Arduino.h" +#include "coredecls.h" #include #include "gdb_hooks.h" #include "uart.h" @@ -493,13 +494,13 @@ uart_stop_isr(uart_t* uart) -tools/sdk/uart_register.h -cores/esp8266/esp8266_peri.h */ -inline size_t +inline __attribute__((always_inline)) size_t uart_tx_fifo_available(const int uart_nr) { return (USS(uart_nr) >> USTXC) & 0xff; } -inline bool +inline __attribute__((always_inline)) bool uart_tx_fifo_full(const int uart_nr) { return uart_tx_fifo_available(uart_nr) >= 0x7f; @@ -566,7 +567,7 @@ uart_wait_tx_empty(uart_t* uart) return; while(uart_tx_fifo_available(uart->uart_nr) > 0) - delay(0); + esp_break(); } @@ -943,23 +944,23 @@ uart_ignore_char(char c) (void) c; } -inline void +inline __attribute__((always_inline)) void uart_write_char_delay(const int uart_nr, char c) { while(uart_tx_fifo_full(uart_nr)) - delay(0); + esp_break(); USF(uart_nr) = c; } -static void +static void ICACHE_RAM_ATTR uart0_write_char(char c) { uart_write_char_delay(0, c); } -static void +static void ICACHE_RAM_ATTR uart1_write_char(char c) { uart_write_char_delay(1, c); diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index b98edcccc0..7be96030da 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -22,6 +22,7 @@ * */ #include +#include #include "ESP8266HTTPClient.h" #include @@ -567,6 +568,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) if (transferred != size) { DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] short write, asked for %d but got %d failed.\n", size, transferred); + esp_break(); return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); } @@ -709,7 +711,7 @@ int HTTPClient::writeToPrint(Print * print) return returnError(HTTPC_ERROR_READ_TIMEOUT); } - delay(0); + esp_break(); } } else { return returnError(HTTPC_ERROR_ENCODING); @@ -1074,7 +1076,7 @@ int HTTPClient::handleHeaderResponse() if((millis() - lastDataTime) > _tcpTimeout) { return HTTPC_ERROR_READ_TIMEOUT; } - delay(0); + esp_break(); } } diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h index 3357f2ac63..303e5963d9 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -119,7 +120,7 @@ void ESP8266HTTPUpdateServerTemplate::setup(ESP8266WebServerTemplate Update.end(); if (_serial_output) Serial.println("Update was aborted"); } - delay(0); + esp_break(); }); } diff --git a/libraries/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino b/libraries/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino index 84a9befcf2..b546df4a7d 100644 --- a/libraries/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino +++ b/libraries/ESP8266WiFi/examples/WiFiScan/WiFiScan.ino @@ -49,7 +49,7 @@ void loop() { (encryptionType == ENC_TYPE_NONE) ? ' ' : '*', hidden ? 'H' : 'V', ssid.c_str()); - delay(0); + yield(); } } else { Serial.printf(PSTR("WiFi scan error %d"), scanResult); diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index 19da592c76..37f80e56b6 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -49,10 +49,6 @@ extern "C" { #include "debug.h" #include "include/WiFiState.h" -extern "C" void esp_schedule(); -extern "C" void esp_yield(); - - // ----------------------------------------------------------------------------------------------------------------------- // ------------------------------------------------- Generic WiFi function ----------------------------------------------- // ----------------------------------------------------------------------------------------------------------------------- @@ -518,9 +514,9 @@ bool ESP8266WiFiGenericClass::forceSleepBegin(uint32 sleepUs) { } wifi_fpm_set_sleep_type(MODEM_SLEEP_T); - delay(0); + esp_break(); wifi_fpm_open(); - delay(0); + esp_break(); auto ret = wifi_fpm_do_sleep(sleepUs); if (ret != 0) { diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 8d74f687cb..788c8eee1b 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -25,6 +25,7 @@ #include "PolledTimeout.h" #include "ESP8266WiFiMulti.h" +#include #include #include @@ -91,7 +92,7 @@ static wl_status_t waitWiFiConnect(uint32_t connectTimeoutMs) // Wait for WiFi status change or timeout do { // Refresh watchdog - delay(0); + esp_break(); // Get WiFi status status = WiFi.status(); @@ -249,7 +250,7 @@ int8_t ESP8266WiFiMulti::startScan() // Wait for WiFi scan change or timeout do { // Refresh watchdog - delay(0); + esp_break(); // Check scan timeout which may occur when scan does not report completion if (scanTimeout) { @@ -535,7 +536,7 @@ void ESP8266WiFiMulti::printWiFiScan() rssi, (encryptionType == ENC_TYPE_NONE) ? ' ' : '*', ssid.c_str()); - delay(0); + esp_break(); } #endif } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp index 618dbfcc86..c1c63996aa 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp @@ -28,6 +28,8 @@ #include "PolledTimeout.h" #include "LwipIntf.h" +#include + #include "c_types.h" #include "ets_sys.h" #include "os_type.h" @@ -44,9 +46,6 @@ extern "C" { #include "debug.h" -extern "C" void esp_schedule(); -extern "C" void esp_yield(); - // ----------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------- Private functions ------------------------------------------------ // ----------------------------------------------------------------------------------------------------------------------- diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp index 65878a3d5b..ae9b8e3c66 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp @@ -26,6 +26,8 @@ #include "ESP8266WiFiGeneric.h" #include "ESP8266WiFiScan.h" +#include + extern "C" { #include "c_types.h" #include "ets_sys.h" @@ -37,9 +39,6 @@ extern "C" { #include "debug.h" -extern "C" void esp_schedule(); -extern "C" void esp_yield(); - // ----------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------- Private functions ------------------------------------------------ // ----------------------------------------------------------------------------------------------------------------------- @@ -94,7 +93,7 @@ int8_t ESP8266WiFiScanClass::scanNetworks(bool async, bool show_hidden, uint8 ch ESP8266WiFiScanClass::_scanStarted = true; if(ESP8266WiFiScanClass::_scanAsync) { - delay(0); // time for the OS to trigger the scan + esp_break(); // time for the OS to trigger the scan return WIFI_SCAN_RUNNING; } diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index 6a82ff3b96..9ad357c33a 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -44,7 +44,6 @@ extern "C" { #include "lwip/netif.h" #include #include "c_types.h" -#include "coredecls.h" #include #include #include diff --git a/libraries/ESP8266WiFi/src/include/ClientContext.h b/libraries/ESP8266WiFi/src/include/ClientContext.h index a994b5cb1d..4fb557456f 100644 --- a/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -26,12 +26,11 @@ class WiFiClient; typedef void (*discard_cb_t)(void*, ClientContext*); -extern "C" void esp_yield(); -extern "C" void esp_schedule(); - #include #include +#include + bool getDefaultPrivateGlobalSyncValue (); class ClientContext @@ -352,7 +351,7 @@ class ClientContext last_sent = millis(); } - delay(0); // from sys or os context + esp_break(); // from sys or os context if ((state() != ESTABLISHED) || (sndbuf == TCP_SND_BUF)) { // peer has closed or all bytes are sent and acked diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index 1d3c6e418c..b444de3551 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -411,7 +411,7 @@ class UdpContext err_t err; esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs); while (((err = trySend(addr, port, /* keep buffer on error */true)) != ERR_OK) && !timeout) - delay(0); + esp_break(); if (err != ERR_OK) cancelBuffer(); // get rid of buffer kept on error after timeout return err == ERR_OK; diff --git a/libraries/esp8266/examples/SerialStress/SerialStress.ino b/libraries/esp8266/examples/SerialStress/SerialStress.ino index b06b38e307..a19eb9f270 100644 --- a/libraries/esp8266/examples/SerialStress/SerialStress.ino +++ b/libraries/esp8266/examples/SerialStress/SerialStress.ino @@ -122,7 +122,7 @@ void loop() { if ((out_idx += local_written_size) == BUFFER_SIZE) { out_idx = 0; } - delay(0); + yield(); DEBUG(logger->printf("----------\n")); diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index 780c4adc14..c80d9bb34b 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -57,6 +57,13 @@ extern "C" void esp_yield() { } +extern "C" void esp_schedule () +{ +} + +extern "C" void esp_break () +{ +} extern "C" void __panic_func(const char* file, int line, const char* func) { (void)file; diff --git a/tests/host/common/include/ClientContext.h b/tests/host/common/include/ClientContext.h index 744d7872d4..bd9c9b80a5 100644 --- a/tests/host/common/include/ClientContext.h +++ b/tests/host/common/include/ClientContext.h @@ -24,9 +24,6 @@ class ClientContext; class WiFiClient; -extern "C" void esp_yield(); -extern "C" void esp_schedule(); - #include bool getDefaultPrivateGlobalSyncValue (); diff --git a/tests/host/common/user_interface.cpp b/tests/host/common/user_interface.cpp index b3a302df18..4e03d77786 100644 --- a/tests/host/common/user_interface.cpp +++ b/tests/host/common/user_interface.cpp @@ -498,10 +498,6 @@ extern "C" (void)intr; } - void esp_schedule(void) - { - } - void dns_setserver(u8_t numdns, ip_addr_t *dnsserver) { (void)numdns; From b64622d303d10261c20fbb494cbcf095d2225946 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Sun, 10 Jan 2021 13:21:47 +0100 Subject: [PATCH 02/21] _notifyPWM may be called indirectly from ISR, cannot yield() from ISR, must not panic. --- cores/esp8266/core_esp8266_waveform_pwm.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cores/esp8266/core_esp8266_waveform_pwm.cpp b/cores/esp8266/core_esp8266_waveform_pwm.cpp index 9ee80ffcc7..0ba024e334 100644 --- a/cores/esp8266/core_esp8266_waveform_pwm.cpp +++ b/cores/esp8266/core_esp8266_waveform_pwm.cpp @@ -40,6 +40,7 @@ #include +#include #include "ets_sys.h" #include "core_esp8266_waveform.h" #include "user_interface.h" @@ -162,7 +163,7 @@ static IRAM_ATTR void _notifyPWM(PWMState *p, bool idle) { forceTimerInterrupt(); while (pwmState.pwmUpdate) { if (idle) { - yield(); + esp_break(); } MEMBARRIER(); } From 9bb489466e83c3b24fb219549379b4f704759622 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Mon, 15 Mar 2021 10:33:20 +0100 Subject: [PATCH 03/21] Fix for 656a33e6f8 --- cores/esp8266/core_esp8266_postmortem.cpp | 6 +++--- cores/esp8266/uart.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/core_esp8266_postmortem.cpp b/cores/esp8266/core_esp8266_postmortem.cpp index 17ac3d7edd..2279401b54 100644 --- a/cores/esp8266/core_esp8266_postmortem.cpp +++ b/cores/esp8266/core_esp8266_postmortem.cpp @@ -245,12 +245,12 @@ static void print_stack(uint32_t start, uint32_t end) { } } -static void ICACHE_RAM_ATTR uart_write_char_d(char c) { +static void IRAM_ATTR uart_write_char_d(char c) { uart0_write_char_d(c); uart1_write_char_d(c); } -static void ICACHE_RAM_ATTR uart0_write_char_d(char c) { +static void IRAM_ATTR uart0_write_char_d(char c) { while (((USS(0) >> USTXC) & 0xff)) { } if (c == '\n') { @@ -259,7 +259,7 @@ static void ICACHE_RAM_ATTR uart0_write_char_d(char c) { USF(0) = c; } -static void ICACHE_RAM_ATTR uart1_write_char_d(char c) { +static void IRAM_ATTR uart1_write_char_d(char c) { while (((USS(1) >> USTXC) & 0xff) >= 0x7e) { } if (c == '\n') { diff --git a/cores/esp8266/uart.cpp b/cores/esp8266/uart.cpp index 80e0cbffd0..2e7251c841 100644 --- a/cores/esp8266/uart.cpp +++ b/cores/esp8266/uart.cpp @@ -954,13 +954,13 @@ uart_write_char_delay(const int uart_nr, char c) } -static void ICACHE_RAM_ATTR +static void IRAM_ATTR uart0_write_char(char c) { uart_write_char_delay(0, c); } -static void ICACHE_RAM_ATTR +static void IRAM_ATTR uart1_write_char(char c) { uart_write_char_delay(1, c); From 97d59aea115410b4f23731fb88c1b2efbb3e5dd2 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Thu, 8 Apr 2021 12:14:20 +0200 Subject: [PATCH 04/21] Consolidate renaming of identifiers to clarify strict meaning of suspend vs. yield --- cores/esp8266/Esp.cpp | 6 ++-- cores/esp8266/PolledTimeout.h | 2 +- cores/esp8266/Schedule.cpp | 10 +++--- cores/esp8266/cont.S | 20 +++++------ cores/esp8266/cont.h | 12 +++---- cores/esp8266/cont_util.cpp | 4 +-- cores/esp8266/core_esp8266_main.cpp | 36 +++++++++---------- cores/esp8266/core_esp8266_waveform_pwm.cpp | 2 +- cores/esp8266/core_esp8266_wiring.cpp | 2 +- cores/esp8266/coredecls.h | 4 +-- cores/esp8266/hwdt_app_entry.cpp | 8 ++--- cores/esp8266/uart.cpp | 4 +-- .../src/ESP8266HTTPClient.cpp | 6 ++-- .../src/ESP8266HTTPUpdateServer-impl.h | 2 +- .../ESP8266WiFi/src/ESP8266WiFiGeneric.cpp | 4 +-- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 6 ++-- .../ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp | 2 +- libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp | 4 +-- .../ESP8266WiFi/src/include/ClientContext.h | 2 +- .../ESP8266WiFi/src/include/UdpContext.h | 6 ++-- libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp | 4 +-- tests/host/common/Arduino.cpp | 8 ++--- 22 files changed, 78 insertions(+), 76 deletions(-) diff --git a/cores/esp8266/Esp.cpp b/cores/esp8266/Esp.cpp index dba0205164..2ee4a65b5e 100644 --- a/cores/esp8266/Esp.cpp +++ b/cores/esp8266/Esp.cpp @@ -119,14 +119,14 @@ void EspClass::deepSleep(uint64_t time_us, WakeMode mode) { system_deep_sleep_set_option(static_cast(mode)); system_deep_sleep(time_us); - esp_yield(); + esp_suspend(); } void EspClass::deepSleepInstant(uint64_t time_us, WakeMode mode) { system_deep_sleep_set_option(static_cast(mode)); system_deep_sleep_instant(time_us); - esp_yield(); + esp_suspend(); } //this calculation was taken verbatim from the SDK api reference for SDK 2.1.0. @@ -198,7 +198,7 @@ void EspClass::reset(void) void EspClass::restart(void) { system_restart(); - esp_yield(); + esp_suspend(); } [[noreturn]] void EspClass::rebootIntoUartDownloadMode() diff --git a/cores/esp8266/PolledTimeout.h b/cores/esp8266/PolledTimeout.h index a8da626ad5..1252ce6c29 100644 --- a/cores/esp8266/PolledTimeout.h +++ b/cores/esp8266/PolledTimeout.h @@ -46,7 +46,7 @@ struct DoNothing struct YieldOrSkip { - static void execute() {esp_break();} + static void execute() {esp_yield();} }; template diff --git a/cores/esp8266/Schedule.cpp b/cores/esp8266/Schedule.cpp index b1230ed675..baef3e9601 100644 --- a/cores/esp8266/Schedule.cpp +++ b/cores/esp8266/Schedule.cpp @@ -164,9 +164,10 @@ void run_scheduled_functions() if (yieldNow) { // because scheduled functions might last too long for watchdog etc, - // this is yield() in cont stack: + // this is yield() in cont stack, but need to call cont_suspend directly + // to prevent recursion into run_scheduled_recurrent_functions() esp_schedule(); - cont_yield(g_pcont); + cont_suspend(g_pcont); } } } @@ -241,9 +242,10 @@ void run_scheduled_recurrent_functions() if (yieldNow) { // because scheduled functions might last too long for watchdog etc, - // this is yield() in cont stack: + // this is yield() in cont stack, but need to call cont_suspend directly + // to prevent recursion into run_scheduled_recurrent_functions() esp_schedule(); - cont_yield(g_pcont); + cont_suspend(g_pcont); } } while (current && !done); diff --git a/cores/esp8266/cont.S b/cores/esp8266/cont.S index 00ca017785..4832b39170 100644 --- a/cores/esp8266/cont.S +++ b/cores/esp8266/cont.S @@ -21,9 +21,9 @@ .section .irom0.text .align 4 .literal_position - .global cont_yield - .type cont_yield, @function -cont_yield: + .global cont_suspend + .type cont_suspend, @function +cont_suspend: /* a1: sp */ /* a2: void* cont_ctx */ /* adjust stack and save registers */ @@ -35,10 +35,10 @@ cont_yield: s32i a0, a1, 16 s32i a2, a1, 20 - /* &cont_continue -> cont_ctx.pc_yield */ + /* &cont_continue -> cont_ctx.pc_suspend */ movi a3, cont_continue s32i a3, a2, 8 - /* sp -> cont_ctx.sp_yield */ + /* sp -> cont_ctx.sp_suspend */ s32i a1, a2, 12 /* a0 <- cont_ctx.pc_ret */ @@ -56,7 +56,7 @@ cont_continue: l32i a2, a1, 20 addi a1, a1, 24 ret - .size cont_yield, . - cont_yield + .size cont_suspend, . - cont_suspend //////////////////////////////////////////////////// @@ -108,7 +108,7 @@ cont_run: /* sp -> cont_ctx.sp_ret */ s32i a1, a2, 4 - /* if cont_ctx.pc_yield != 0, goto cont_resume */ + /* if cont_ctx.pc_suspend != 0, goto cont_resume */ l32i a4, a2, 8 bnez a4, cont_resume /* else */ @@ -119,12 +119,12 @@ cont_run: jx a2 cont_resume: - /* a1 <- cont_ctx.sp_yield */ + /* a1 <- cont_ctx.sp_suspend */ l32i a1, a2, 12 - /* reset yield flag, 0 -> cont_ctx.pc_yield */ + /* reset yield flag, 0 -> cont_ctx.pc_suspend */ movi a3, 0 s32i a3, a2, 8 - /* jump to saved cont_ctx.pc_yield */ + /* jump to saved cont_ctx.pc_suspend */ movi a0, cont_ret jx a4 diff --git a/cores/esp8266/cont.h b/cores/esp8266/cont.h index 21ecad2806..6932416b68 100644 --- a/cores/esp8266/cont.h +++ b/cores/esp8266/cont.h @@ -35,8 +35,8 @@ typedef struct cont_ { void (*pc_ret)(void); unsigned* sp_ret; - void (*pc_yield)(void); - unsigned* sp_yield; + void (*pc_suspend)(void); + unsigned* sp_suspend; unsigned* stack_end; unsigned unused1; @@ -55,12 +55,12 @@ extern cont_t* g_pcont; void cont_init(cont_t*); // Run function pfn in a separate stack, or continue execution -// at the point where cont_yield was called +// at the point where cont_suspend was called void cont_run(cont_t*, void (*pfn)(void)); // Return to the point where cont_run was called, saving the // execution state (registers and stack) -void cont_yield(cont_t*); +void cont_suspend(cont_t*); // Check guard bytes around the stack. Return 0 in case everything is ok, // return 1 if guard bytes were overwritten. @@ -70,9 +70,9 @@ int cont_check(cont_t* cont); // and thus weren't used by the user code. i.e. that stack space is free. (high water mark) int cont_get_free_stack(cont_t* cont); -// Check if yield() may be called. Returns true if we are running inside +// Check if cont_suspend() may be called. Returns true if we are running inside // continuation stack -bool cont_can_yield(cont_t* cont); +bool cont_can_suspend(cont_t* cont); // Repaint the stack from the current SP to the end, to allow individual // routines' stack usages to be calculated by re-painting, checking current diff --git a/cores/esp8266/cont_util.cpp b/cores/esp8266/cont_util.cpp index 8fa4421802..fd72ee5d18 100644 --- a/cores/esp8266/cont_util.cpp +++ b/cores/esp8266/cont_util.cpp @@ -62,9 +62,9 @@ int cont_get_free_stack(cont_t* cont) { return freeWords * 4; } -bool IRAM_ATTR cont_can_yield(cont_t* cont) { +bool IRAM_ATTR cont_can_suspend(cont_t* cont) { return !ETS_INTR_WITHINISR() && - cont->pc_ret != 0 && cont->pc_yield == 0; + cont->pc_ret != 0 && cont->pc_suspend == 0; } // No need for this to be in IRAM, not expected to be IRQ called diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 92472f7997..5a471c79be 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -62,7 +62,7 @@ cont_t* g_pcont __attribute__((section(".noinit"))); static os_event_t s_loop_queue[LOOP_QUEUE_SIZE]; /* Used to implement optimistic_yield */ -static uint32_t s_cycles_at_yield_start; +static uint32_t s_cycles_at_resume; /* For ets_intr_lock_nest / ets_intr_unlock_nest * Max nesting seen by SDK so far is 2. @@ -106,41 +106,41 @@ extern "C" void __preloop_update_frequency() { extern "C" void preloop_update_frequency() __attribute__((weak, alias("__preloop_update_frequency"))); extern "C" bool can_yield() { - return cont_can_yield(g_pcont); + return cont_can_suspend(g_pcont); } -static inline void esp_yield_within_cont() __attribute__((always_inline)); -static void esp_yield_within_cont() { - cont_yield(g_pcont); - s_cycles_at_yield_start = ESP.getCycleCount(); +static inline void esp_suspend_within_cont() __attribute__((always_inline)); +static void esp_suspend_within_cont() { + cont_suspend(g_pcont); + s_cycles_at_resume = ESP.getCycleCount(); run_scheduled_recurrent_functions(); } -extern "C" void __esp_yield() { - if (can_yield()) { - esp_yield_within_cont(); +extern "C" void __esp_suspend() { + if (cont_can_suspend(g_pcont)) { + esp_suspend_within_cont(); } } -extern "C" void esp_yield() __attribute__ ((weak, alias("__esp_yield"))); +extern "C" void esp_suspend() __attribute__ ((weak, alias("__esp_suspend"))); extern "C" IRAM_ATTR void esp_schedule() { ets_post(LOOP_TASK_PRIORITY, 0, 0); } // Replacement for delay(0). In CONT, same as yield(). Whereas yield() panics -// in SYS, esp_break() is safe to call and only schedules CONT. Use yield() -// whereever only called from CONT, use esp_break() if code is called from SYS +// in SYS, esp_yield() is safe to call and only schedules CONT. Use yield() +// whereever only called from CONT, use esp_yield() if code is called from SYS // or both CONT and SYS. -extern "C" void esp_break() { +extern "C" void esp_yield() { esp_schedule(); - esp_yield(); + esp_suspend(); } extern "C" void __yield() { - if (can_yield()) { + if (cont_can_suspend(g_pcont)) { esp_schedule(); - esp_yield_within_cont(); + esp_suspend_within_cont(); } else { panic(); @@ -156,7 +156,7 @@ extern "C" void optimistic_yield(uint32_t interval_us) { #else ESP.getCpuFreqMHz(); #endif - if ((ESP.getCycleCount() - s_cycles_at_yield_start) > intvl_cycles && + if ((ESP.getCycleCount() - s_cycles_at_resume) > intvl_cycles && can_yield()) { yield(); @@ -216,7 +216,7 @@ static void loop_wrapper() { static void loop_task(os_event_t *events) { (void) events; - s_cycles_at_yield_start = ESP.getCycleCount(); + s_cycles_at_resume = ESP.getCycleCount(); ESP.resetHeap(); cont_run(g_pcont, &loop_wrapper); ESP.setDramHeap(); diff --git a/cores/esp8266/core_esp8266_waveform_pwm.cpp b/cores/esp8266/core_esp8266_waveform_pwm.cpp index 0ba024e334..65e75a0c71 100644 --- a/cores/esp8266/core_esp8266_waveform_pwm.cpp +++ b/cores/esp8266/core_esp8266_waveform_pwm.cpp @@ -163,7 +163,7 @@ static IRAM_ATTR void _notifyPWM(PWMState *p, bool idle) { forceTimerInterrupt(); while (pwmState.pwmUpdate) { if (idle) { - esp_break(); + esp_yield(); } MEMBARRIER(); } diff --git a/cores/esp8266/core_esp8266_wiring.cpp b/cores/esp8266/core_esp8266_wiring.cpp index b11d14a1d8..65a9a6aecc 100644 --- a/cores/esp8266/core_esp8266_wiring.cpp +++ b/cores/esp8266/core_esp8266_wiring.cpp @@ -47,7 +47,7 @@ void __delay(unsigned long ms) { } else { esp_schedule(); } - esp_yield(); + esp_suspend(); if(ms) { os_timer_disarm(&delay_timer); } diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index 9f7fff2d07..7268016a9f 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -13,9 +13,9 @@ extern "C" { #include // g_pcont declaration bool can_yield(); -void esp_yield(); +void esp_suspend(); void esp_schedule(); -void esp_break(); +void esp_yield(); void tune_timeshift64 (uint64_t now_us); void disable_extra4k_at_link_time (void) __attribute__((noinline)); bool sntp_set_timezone_in_seconds(int32_t timezone); diff --git a/cores/esp8266/hwdt_app_entry.cpp b/cores/esp8266/hwdt_app_entry.cpp index 3a657cfcd9..22a91a6bee 100644 --- a/cores/esp8266/hwdt_app_entry.cpp +++ b/cores/esp8266/hwdt_app_entry.cpp @@ -952,13 +952,13 @@ STATIC void IRAM_MAYBE handle_hwdt(void) { /* Print separate ctx: cont stack */ /* Check if cont stack is yielding to SYS */ - if (0 == hwdt_info.cont_integrity && 0 != g_pcont->pc_yield) { - ctx_cont_ptr = (const uint32_t *)((uintptr_t)g_pcont->sp_yield - 8u); + if (0 == hwdt_info.cont_integrity && 0 != g_pcont->pc_suspend) { + ctx_cont_ptr = (const uint32_t *)((uintptr_t)g_pcont->sp_suspend - 8u); } print_stack((uintptr_t)ctx_cont_ptr, (uintptr_t)g_pcont->stack_end, PRINT_STACK::CONT); } else { - if (0 == hwdt_info.cont_integrity && 0 != g_pcont->pc_yield) { - ETS_PRINTF("\nCont stack is yielding. Active stack starts at 0x%08X.\n", (uint32_t)g_pcont->sp_yield - 8u); + if (0 == hwdt_info.cont_integrity && 0 != g_pcont->pc_suspend) { + ETS_PRINTF("\nCont stack is yielding. Active stack starts at 0x%08X.\n", (uint32_t)g_pcont->sp_suspend - 8u); } } diff --git a/cores/esp8266/uart.cpp b/cores/esp8266/uart.cpp index 2e7251c841..1f657c9403 100644 --- a/cores/esp8266/uart.cpp +++ b/cores/esp8266/uart.cpp @@ -567,7 +567,7 @@ uart_wait_tx_empty(uart_t* uart) return; while(uart_tx_fifo_available(uart->uart_nr) > 0) - esp_break(); + esp_yield(); } @@ -948,7 +948,7 @@ inline __attribute__((always_inline)) void uart_write_char_delay(const int uart_nr, char c) { while(uart_tx_fifo_full(uart_nr)) - esp_break(); + esp_yield(); USF(uart_nr) = c; diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 7be96030da..195ade0274 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -568,7 +568,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) if (transferred != size) { DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] short write, asked for %d but got %d failed.\n", size, transferred); - esp_break(); + esp_yield(); return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED); } @@ -711,7 +711,7 @@ int HTTPClient::writeToPrint(Print * print) return returnError(HTTPC_ERROR_READ_TIMEOUT); } - esp_break(); + esp_yield(); } } else { return returnError(HTTPC_ERROR_ENCODING); @@ -1076,7 +1076,7 @@ int HTTPClient::handleHeaderResponse() if((millis() - lastDataTime) > _tcpTimeout) { return HTTPC_ERROR_READ_TIMEOUT; } - esp_break(); + esp_yield(); } } diff --git a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h index 303e5963d9..39608934cd 100644 --- a/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h +++ b/libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer-impl.h @@ -120,7 +120,7 @@ void ESP8266HTTPUpdateServerTemplate::setup(ESP8266WebServerTemplate Update.end(); if (_serial_output) Serial.println("Update was aborted"); } - esp_break(); + esp_yield(); }); } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index 37f80e56b6..5c1dba65db 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -514,9 +514,9 @@ bool ESP8266WiFiGenericClass::forceSleepBegin(uint32 sleepUs) { } wifi_fpm_set_sleep_type(MODEM_SLEEP_T); - esp_break(); + esp_yield(); wifi_fpm_open(); - esp_break(); + esp_yield(); auto ret = wifi_fpm_do_sleep(sleepUs); if (ret != 0) { diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 788c8eee1b..847a5ae969 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -92,7 +92,7 @@ static wl_status_t waitWiFiConnect(uint32_t connectTimeoutMs) // Wait for WiFi status change or timeout do { // Refresh watchdog - esp_break(); + esp_yield(); // Get WiFi status status = WiFi.status(); @@ -250,7 +250,7 @@ int8_t ESP8266WiFiMulti::startScan() // Wait for WiFi scan change or timeout do { // Refresh watchdog - esp_break(); + esp_yield(); // Check scan timeout which may occur when scan does not report completion if (scanTimeout) { @@ -536,7 +536,7 @@ void ESP8266WiFiMulti::printWiFiScan() rssi, (encryptionType == ENC_TYPE_NONE) ? ' ' : '*', ssid.c_str()); - esp_break(); + esp_yield(); } #endif } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp index 99d27ba7a3..f6c639fdb7 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp @@ -70,7 +70,7 @@ bool ESP8266WiFiSTAClass::beginWPSConfig(void) { return false; } - esp_yield(); + esp_suspend(); // will resume when wifi_wps_status_cb fires return true; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp index ae9b8e3c66..94bd12ee96 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp @@ -93,11 +93,11 @@ int8_t ESP8266WiFiScanClass::scanNetworks(bool async, bool show_hidden, uint8 ch ESP8266WiFiScanClass::_scanStarted = true; if(ESP8266WiFiScanClass::_scanAsync) { - esp_break(); // time for the OS to trigger the scan + esp_yield(); // time for the OS to trigger the scan return WIFI_SCAN_RUNNING; } - esp_yield(); // will resume when _scanDone fires + esp_suspend(); // will resume when _scanDone fires return ESP8266WiFiScanClass::_scanCount; } else { return WIFI_SCAN_FAILED; diff --git a/libraries/ESP8266WiFi/src/include/ClientContext.h b/libraries/ESP8266WiFi/src/include/ClientContext.h index 4fb557456f..416a666a60 100644 --- a/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -351,7 +351,7 @@ class ClientContext last_sent = millis(); } - esp_break(); // from sys or os context + esp_yield(); // from sys or os context if ((state() != ESTABLISHED) || (sndbuf == TCP_SND_BUF)) { // peer has closed or all bytes are sent and acked diff --git a/libraries/ESP8266WiFi/src/include/UdpContext.h b/libraries/ESP8266WiFi/src/include/UdpContext.h index b444de3551..1e7f639e34 100644 --- a/libraries/ESP8266WiFi/src/include/UdpContext.h +++ b/libraries/ESP8266WiFi/src/include/UdpContext.h @@ -24,7 +24,7 @@ class UdpContext; extern "C" { -void esp_yield(); +void esp_suspend(); void esp_schedule(); #include } @@ -177,7 +177,7 @@ class UdpContext } // warning: handler is called from tcp stack context - // esp_yield and non-reentrant functions which depend on it will fail + // esp_suspend and non-reentrant functions which depend on it will fail void onRx(rxhandler_t handler) { _on_rx = handler; } @@ -411,7 +411,7 @@ class UdpContext err_t err; esp8266::polledTimeout::oneShotFastMs timeout(timeoutMs); while (((err = trySend(addr, port, /* keep buffer on error */true)) != ERR_OK) && !timeout) - esp_break(); + esp_yield(); if (err != ERR_OK) cancelBuffer(); // get rid of buffer kept on error after timeout return err == ERR_OK; diff --git a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp index 6fc4e3cd01..bf1b1cde26 100644 --- a/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp +++ b/libraries/ESP8266mDNS/src/LEAmDNS_Control.cpp @@ -702,7 +702,7 @@ bool MDNSResponder::_parseResponse(const MDNSResponder::stcMDNS_MsgHeader& p_Msg for (uint16_t qd=0; ((bDumpResult) && (qdflush(); diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index c80d9bb34b..ff5c43835d 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -53,15 +53,15 @@ extern "C" void optimistic_yield (uint32_t interval_us) (void)interval_us; } -extern "C" void esp_yield() +extern "C" void esp_suspend() { } -extern "C" void esp_schedule () +extern "C" void esp_schedule() { } -extern "C" void esp_break () +extern "C" void esp_yield() { } @@ -84,6 +84,6 @@ extern "C" void delayMicroseconds(unsigned int us) #include "cont.h" cont_t* g_pcont = NULL; -extern "C" void cont_yield(cont_t*) +extern "C" void cont_suspend(cont_t*) { } From 08ed7d0b2828bab3e55ca8951c5cae1e2123f7cb Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Sat, 10 Apr 2021 10:05:24 +0200 Subject: [PATCH 05/21] Non-recurring scheduled functions may yield, therefore run_scheduled_functions can use optimistic_yield() --- cores/esp8266/Schedule.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/cores/esp8266/Schedule.cpp b/cores/esp8266/Schedule.cpp index baef3e9601..279e78ff6c 100644 --- a/cores/esp8266/Schedule.cpp +++ b/cores/esp8266/Schedule.cpp @@ -135,8 +135,6 @@ bool schedule_recurrent_function_us(const std::function& fn, void run_scheduled_functions() { - esp8266::polledTimeout::periodicFastMs yieldNow(100); // yield every 100ms - // prevent scheduling of new functions during this run auto stop = sLast; bool done = false; @@ -161,14 +159,10 @@ void run_scheduled_functions() recycle_fn_unsafe(to_recycle); } - if (yieldNow) - { - // because scheduled functions might last too long for watchdog etc, - // this is yield() in cont stack, but need to call cont_suspend directly - // to prevent recursion into run_scheduled_recurrent_functions() - esp_schedule(); - cont_suspend(g_pcont); - } + // scheduled functions might last too long for watchdog etc. + // yield() is allowed in scheduled functions, therefore + // recursion into run_scheduled_recurrent_functions() is permitted + optimistic_yield(100000); } } From 397408fc5a64eb4e1dde3626127a787a034c6e00 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Thu, 8 Apr 2021 12:42:38 +0200 Subject: [PATCH 06/21] Add HAVE_ESP_SUSPEND define to allow 3rd party libraries to detect API changes --- cores/esp8266/coredecls.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index 7268016a9f..474f77c5df 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -2,6 +2,8 @@ #ifndef __COREDECLS_H #define __COREDECLS_H +#define HAVE_ESP_SUSPEND 1 + #ifdef __cplusplus extern "C" { #endif From 0bb470cd588a1b4fa69b90f7b167de517d920683 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Fri, 9 Apr 2021 12:14:08 +0200 Subject: [PATCH 07/21] Merge branch 'esp_yield_mt' into delay0isyield --- cores/esp8266/core_esp8266_main.cpp | 39 ++++++++++- cores/esp8266/core_esp8266_wiring.cpp | 18 +---- cores/esp8266/coredecls.h | 16 +++++ cores/esp8266/time.cpp | 5 ++ .../ESP8266WiFi/src/ESP8266WiFiGeneric.cpp | 14 ++-- .../ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 69 +++++++------------ .../ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp | 8 ++- libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp | 9 +-- .../ESP8266WiFi/src/include/ClientContext.h | 26 ++++--- tests/host/common/Arduino.cpp | 17 ++++- 10 files changed, 130 insertions(+), 91 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 5a471c79be..e6b110783a 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -80,6 +80,10 @@ const char* core_release = #else NULL; #endif + +static os_timer_t delay_timer; +#define ONCE 0 +#define REPEAT 1 } // extern "C" void initVariant() __attribute__((weak)); @@ -137,6 +141,38 @@ extern "C" void esp_yield() { esp_suspend(); } +void delay_end(void* arg) { + (void)arg; + esp_schedule(); +} + +extern "C" void __esp_delay(unsigned long ms) { + if (ms) { + os_timer_setfn(&delay_timer, (os_timer_func_t*)&delay_end, 0); + os_timer_arm(&delay_timer, ms, ONCE); + } + else { + esp_schedule(); + } + esp_suspend(); + if (ms) { + os_timer_disarm(&delay_timer); + } +} + +extern "C" void esp_delay(unsigned long ms) __attribute__((weak, alias("__esp_delay"))); + +using IsBlockedCB = std::function; + +void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms) { + const auto start = millis(); + decltype(millis()) expired; + while ((expired = millis() - start) < timeout_ms && blocked()) { + auto remaining = timeout_ms - expired; + esp_delay(remaining <= intvl_ms ? remaining : intvl_ms); + } +} + extern "C" void __yield() { if (cont_can_suspend(g_pcont)) { esp_schedule(); @@ -224,8 +260,8 @@ static void loop_task(os_event_t *events) { panic(); } } -extern "C" { +extern "C" { struct object { long placeholder[ 10 ]; }; void __register_frame_info (const void *begin, struct object *ob); extern char __eh_frame[]; @@ -262,7 +298,6 @@ static void __unhandled_exception_cpp() } #endif } - } void init_done() { diff --git a/cores/esp8266/core_esp8266_wiring.cpp b/cores/esp8266/core_esp8266_wiring.cpp index 65a9a6aecc..40a996d560 100644 --- a/cores/esp8266/core_esp8266_wiring.cpp +++ b/cores/esp8266/core_esp8266_wiring.cpp @@ -23,34 +23,18 @@ #include "ets_sys.h" #include "osapi.h" #include "user_interface.h" -#include "cont.h" #include "coredecls.h" extern "C" { -static os_timer_t delay_timer; static os_timer_t micros_overflow_timer; static uint32_t micros_at_last_overflow_tick = 0; static uint32_t micros_overflow_count = 0; #define ONCE 0 #define REPEAT 1 -void delay_end(void* arg) { - (void) arg; - esp_schedule(); -} - void __delay(unsigned long ms) { - if(ms) { - os_timer_setfn(&delay_timer, (os_timer_func_t*) &delay_end, 0); - os_timer_arm(&delay_timer, ms, ONCE); - } else { - esp_schedule(); - } - esp_suspend(); - if(ms) { - os_timer_disarm(&delay_timer); - } + esp_delay(ms); } void delay(unsigned long ms) __attribute__ ((weak, alias("__delay"))); diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index 474f77c5df..e7baf26c62 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -16,6 +16,7 @@ extern "C" { bool can_yield(); void esp_suspend(); +void esp_delay(unsigned long ms); void esp_schedule(); void esp_yield(); void tune_timeshift64 (uint64_t now_us); @@ -35,9 +36,24 @@ uint32_t crc32 (const void* data, size_t length, uint32_t crc = 0xffffffff); using BoolCB = std::function; using TrivialCB = std::function; +void settimeofday_cb (BoolCB&& cb); void settimeofday_cb (const BoolCB& cb); void settimeofday_cb (const TrivialCB& cb); +using IsBlockedCB = std::function; + +inline void esp_suspend(const IsBlockedCB& blocked) { + do { + esp_suspend(); + } while (blocked()); +} + +void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms); + +inline void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked) { + esp_delay(timeout_ms, blocked, timeout_ms); +} + #endif // __cplusplus #endif // __COREDECLS_H diff --git a/cores/esp8266/time.cpp b/cores/esp8266/time.cpp index b9489c330f..8e997c72d5 100644 --- a/cores/esp8266/time.cpp +++ b/cores/esp8266/time.cpp @@ -214,6 +214,11 @@ void settimeofday_cb (const TrivialCB& cb) _settimeofday_cb = [cb](bool sntp) { (void)sntp; cb(); }; } +void settimeofday_cb (BoolCB&& cb) +{ + _settimeofday_cb = std::move(cb); +} + void settimeofday_cb (const BoolCB& cb) { _settimeofday_cb = cb; diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index 5c1dba65db..a7d323cd57 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -434,10 +434,9 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m) { //tasks to wait correctly. constexpr unsigned int timeoutValue = 1000; //1 second if(can_yield()) { - using oneShot = esp8266::polledTimeout::oneShotFastMs; - oneShot timeout(timeoutValue); - while(wifi_get_opmode() != (uint8) m && !timeout) - delay(5); + // The final argument, intvl_ms, to esp_delay influences how frequently + // the scheduled recurrent functions (Schedule.h) are probed. + esp_delay(timeoutValue, [m]() { return wifi_get_opmode() != m; }, 5); //if at this point mode still hasn't been reached, give up if(wifi_get_opmode() != (uint8) m) { @@ -617,7 +616,7 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul aResult = IPAddress(&addr); } else if(err == ERR_INPROGRESS) { _dns_lookup_pending = true; - delay(timeout_ms); + esp_delay(timeout_ms, []() { return _dns_lookup_pending; }); // will resume on timeout or when wifi_dns_found_callback fires _dns_lookup_pending = false; // will return here when dns_found_callback fires @@ -667,8 +666,8 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul aResult = IPAddress(&addr); } else if(err == ERR_INPROGRESS) { _dns_lookup_pending = true; - delay(timeout_ms); // will resume on timeout or when wifi_dns_found_callback fires + esp_delay(timeout_ms, []() { return _dns_lookup_pending; }); _dns_lookup_pending = false; // will return here when dns_found_callback fires if(aResult.isSet()) { @@ -701,7 +700,8 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca if(ipaddr) { (*reinterpret_cast(callback_arg)) = IPAddress(ipaddr); } - esp_schedule(); // break delay in hostByName + _dns_lookup_pending = false; // resume hostByName + esp_schedule(); } uint32_t ESP8266WiFiGenericClass::shutdownCRC (const WiFiState& state) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 847a5ae969..992beb23cb 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -84,36 +84,25 @@ static void printWiFiStatus(wl_status_t status) static wl_status_t waitWiFiConnect(uint32_t connectTimeoutMs) { wl_status_t status; + // The final argument, intvl_ms, to esp_delay influences how frequently + // the scheduled recurrent functions (Schedule.h) are probed. + esp_delay(connectTimeoutMs, + [&status]() { status = WiFi.status(); return status != WL_CONNECTED && status != WL_CONNECT_FAILED; }, 0); - // Set WiFi connect timeout - using esp8266::polledTimeout::oneShotMs; - oneShotMs connectTimeout(connectTimeoutMs); - - // Wait for WiFi status change or timeout - do { - // Refresh watchdog - esp_yield(); - - // Get WiFi status - status = WiFi.status(); - - // Check status - if (status == WL_CONNECTED) { - // Connected, print WiFi status - printWiFiStatus(status); - - // Return WiFi status - return status; - } else if (status == WL_CONNECT_FAILED) { - DEBUG_WIFI_MULTI("[WIFIM] Connect failed\n"); - - // Return WiFi connect failed - return WL_CONNECT_FAILED; - } - } while (!connectTimeout); + // Check status + if (status == WL_CONNECTED) { + // Connected, print WiFi status + printWiFiStatus(status); - DEBUG_WIFI_MULTI("[WIFIM] Connect timeout\n"); + // Return WiFi status + return status; + } else if (status == WL_CONNECT_FAILED) { + DEBUG_WIFI_MULTI("[WIFIM] Connect failed\n"); + } else { + DEBUG_WIFI_MULTI("[WIFIM] Connect timeout\n"); + } + // Return WiFi connect failed return WL_CONNECT_FAILED; } @@ -243,24 +232,16 @@ int8_t ESP8266WiFiMulti::startScan() // Start wifi scan in async mode WiFi.scanNetworks(true); - // Set WiFi scan timeout - using esp8266::polledTimeout::oneShotMs; - oneShotMs scanTimeout(WIFI_SCAN_TIMEOUT_MS); - // Wait for WiFi scan change or timeout - do { - // Refresh watchdog - esp_yield(); - - // Check scan timeout which may occur when scan does not report completion - if (scanTimeout) { - DEBUG_WIFI_MULTI("[WIFIM] Scan timeout\n"); - return WIFI_SCAN_FAILED; - } - - // Get scan result - scanResult = WiFi.scanComplete(); - } while (scanResult < 0); + // The final argument, intvl_ms, to esp_delay influences how frequently + // the scheduled recurrent functions (Schedule.h) are probed. + esp_delay(WIFI_SCAN_TIMEOUT_MS, + [&scanResult]() { scanResult = WiFi.scanComplete(); return scanResult < 0; }, 0); + // Check for scan timeout which may occur when scan does not report completion + if (scanResult < 0) { + DEBUG_WIFI_MULTI("[WIFIM] Scan timeout\n"); + return WIFI_SCAN_FAILED; + } // Print WiFi scan result printWiFiScan(); diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp index f6c639fdb7..b93c77da9c 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp @@ -30,6 +30,8 @@ static void wifi_wps_status_cb(wps_cb_status status); +static bool _wps_config_pending = false; + /** * WPS config * so far only WPS_TYPE_PBC is supported (SDK 1.2.0) @@ -70,8 +72,9 @@ bool ESP8266WiFiSTAClass::beginWPSConfig(void) { return false; } - esp_suspend(); + _wps_config_pending = true; // will resume when wifi_wps_status_cb fires + esp_suspend([]() { return _wps_config_pending; }); return true; } @@ -107,5 +110,6 @@ void wifi_wps_status_cb(wps_cb_status status) { } // TODO user function to get status - esp_schedule(); // resume beginWPSConfig + _wps_config_pending = false; // resume beginWPSConfig + esp_schedule(); } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp index 94bd12ee96..6aaf432e2d 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp @@ -26,8 +26,6 @@ #include "ESP8266WiFiGeneric.h" #include "ESP8266WiFiScan.h" -#include - extern "C" { #include "c_types.h" #include "ets_sys.h" @@ -38,6 +36,7 @@ extern "C" { } #include "debug.h" +#include // ----------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------- Private functions ------------------------------------------------ @@ -97,7 +96,9 @@ int8_t ESP8266WiFiScanClass::scanNetworks(bool async, bool show_hidden, uint8 ch return WIFI_SCAN_RUNNING; } - esp_suspend(); // will resume when _scanDone fires + // will resume when _scanDone fires + esp_suspend([]() { return !ESP8266WiFiScanClass::_scanComplete && ESP8266WiFiScanClass::_scanStarted; }); + return ESP8266WiFiScanClass::_scanCount; } else { return WIFI_SCAN_FAILED; @@ -321,7 +322,7 @@ void ESP8266WiFiScanClass::_scanDone(void* result, int status) { ESP8266WiFiScanClass::_scanStarted = false; ESP8266WiFiScanClass::_scanComplete = true; - if(!ESP8266WiFiScanClass::_scanAsync) { + if (!ESP8266WiFiScanClass::_scanAsync) { esp_schedule(); // resume scanNetworks } else if (ESP8266WiFiScanClass::_onComplete) { ESP8266WiFiScanClass::_onComplete(ESP8266WiFiScanClass::_scanCount); diff --git a/libraries/ESP8266WiFi/src/include/ClientContext.h b/libraries/ESP8266WiFi/src/include/ClientContext.h index 416a666a60..7fcad3678a 100644 --- a/libraries/ESP8266WiFi/src/include/ClientContext.h +++ b/libraries/ESP8266WiFi/src/include/ClientContext.h @@ -28,7 +28,6 @@ typedef void (*discard_cb_t)(void*, ClientContext*); #include #include - #include bool getDefaultPrivateGlobalSyncValue (); @@ -144,11 +143,9 @@ class ClientContext } _connect_pending = true; _op_start_time = millis(); - for (decltype(_timeout_ms) i = 0; _connect_pending && i < _timeout_ms; i++) { - // Give scheduled functions a chance to run (e.g. Ethernet uses recurrent) - delay(1); - // will resume on timeout or when _connected or _notify_error fires - } + // will resume on timeout or when _connected or _notify_error fires + // give scheduled functions a chance to run (e.g. Ethernet uses recurrent) + esp_delay(_timeout_ms, [this]() { return this->_connect_pending; }, 1); _connect_pending = false; if (!_pcb) { DEBUGV(":cabrt\r\n"); @@ -457,9 +454,10 @@ class ClientContext void _notify_error() { if (_connect_pending || _send_waiting) { + // resume connect or _write_from_source _send_waiting = false; _connect_pending = false; - esp_schedule(); // break delay in connect or _write_from_source + esp_schedule(); } } @@ -486,11 +484,9 @@ class ClientContext } _send_waiting = true; - for (decltype(_timeout_ms) i = 0; _send_waiting && i < _timeout_ms; i++) { - // Give scheduled functions a chance to run (e.g. Ethernet uses recurrent) - delay(1); - // will resume on timeout or when _write_some_from_cb or _notify_error fires - } + // will resume on timeout or when _write_some_from_cb or _notify_error fires + // give scheduled functions a chance to run (e.g. Ethernet uses recurrent) + esp_delay(_timeout_ms, [this]() { return this->_send_waiting; }, 1); _send_waiting = false; } while(true); @@ -560,8 +556,9 @@ class ClientContext void _write_some_from_cb() { if (_send_waiting) { + // resume _write_from_source _send_waiting = false; - esp_schedule(); // break delay in _write_from_source + esp_schedule(); } } @@ -648,8 +645,9 @@ class ClientContext (void) pcb; assert(pcb == _pcb); if (_connect_pending) { + // resume connect _connect_pending = false; - esp_schedule(); // break delay in connect + esp_schedule(); } return ERR_OK; } diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index ff5c43835d..eed0ebebdc 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -15,6 +15,7 @@ #include #include "Arduino.h" +#include #include @@ -65,6 +66,20 @@ extern "C" void esp_yield() { } +extern "C" void esp_delay (unsigned long ms) +{ + usleep(ms * 1000); +} + +using IsBlockedCB = std::function; + +void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms) +{ + (void)blocked; + (void)intvl_ms; + usleep(timeout_ms * 1000); +} + extern "C" void __panic_func(const char* file, int line, const char* func) { (void)file; (void)line; @@ -74,7 +89,7 @@ extern "C" void __panic_func(const char* file, int line, const char* func) { extern "C" void delay(unsigned long ms) { - usleep(ms * 1000); + esp_delay(ms); } extern "C" void delayMicroseconds(unsigned int us) From 971ad28dad73327ab2d8ac878e4f5bed09a1925d Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Mon, 19 Apr 2021 18:10:39 +0200 Subject: [PATCH 08/21] Make detectBaudrate safe from SYS context, for what it's worth. --- cores/esp8266/HardwareSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/HardwareSerial.cpp b/cores/esp8266/HardwareSerial.cpp index 88b47b33f3..4896e27758 100644 --- a/cores/esp8266/HardwareSerial.cpp +++ b/cores/esp8266/HardwareSerial.cpp @@ -143,7 +143,7 @@ unsigned long HardwareSerial::detectBaudrate(time_t timeoutMillis) if ((detectedBaudrate = testBaudrate())) { break; } - delay(100); + esp_delay(100); } return detectedBaudrate; } From 99ed6fcca3212752972144206d2b853146edca4f Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Mon, 19 Apr 2021 21:46:16 +0200 Subject: [PATCH 09/21] Add comment about how optimistic_yield() is safe for SYS, like in callbacks. --- cores/esp8266/core_esp8266_main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index e6b110783a..00e3cc9f19 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -185,6 +185,9 @@ extern "C" void __yield() { extern "C" void yield(void) __attribute__ ((weak, alias("__yield"))); +// In CONT, actually performs yield() only once the given time interval +// has elapsed since the last time yield() occured. Whereas yield() panics +// in SYS, optimistic_yield() additionally is safe to call and does nothing. extern "C" void optimistic_yield(uint32_t interval_us) { const uint32_t intvl_cycles = interval_us * #if defined(F_CPU) From cd8d2d311f3953a36467d4edb866b8e1e3189c5b Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Tue, 20 Jul 2021 18:39:25 +0200 Subject: [PATCH 10/21] Adapt logic to feed scheduled recurrent functions in hostByName from PR #6212 --- libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index a7d323cd57..bd784b48e7 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -616,10 +616,12 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul aResult = IPAddress(&addr); } else if(err == ERR_INPROGRESS) { _dns_lookup_pending = true; - esp_delay(timeout_ms, []() { return _dns_lookup_pending; }); - // will resume on timeout or when wifi_dns_found_callback fires + // Will resume on timeout or when wifi_dns_found_callback fires. + // The final argument, intvl_ms, to esp_delay influences how frequently + // the scheduled recurrent functions (Schedule.h) are probed; here, to allow + // the ethernet driver perform work. + esp_delay(timeout_ms, []() { return _dns_lookup_pending; }, 1); _dns_lookup_pending = false; - // will return here when dns_found_callback fires if(aResult.isSet()) { err = ERR_OK; } From 070eb482748386274cf63b21d8db613054959664 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Wed, 6 Oct 2021 23:09:18 +0200 Subject: [PATCH 11/21] Add clarifying comments to esp_suspend and esp_delay overloads. --- cores/esp8266/coredecls.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index e7baf26c62..7a7be8b31a 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -42,14 +42,23 @@ void settimeofday_cb (const TrivialCB& cb); using IsBlockedCB = std::function; +// This overload of esp_suspend() performs the blocked callback whenever it is resumed, +// and if that returns true, it immediately suspends again. inline void esp_suspend(const IsBlockedCB& blocked) { do { esp_suspend(); } while (blocked()); } +// This overload of esp_delay() delays for a duration of at most timeout_ms milliseconds. +// Whenever it is resumed, as well as every intvl_ms millisconds, it performs +// the blocked callback, and if that returns true, it keeps delaying for the remainder +// of the original timeout_ms period. void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms); +// This overload of esp_delay() delays for a duration of at most timeout_ms milliseconds. +// Whenever it is resumed, it performs the blocked callback, and if that returns true, +// it keeps delaying for the remainder of the original timeout_ms period. inline void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked) { esp_delay(timeout_ms, blocked, timeout_ms); } From d11be8b360914010a5b0c140d09cd930b2bfca57 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Wed, 6 Oct 2021 23:35:52 +0200 Subject: [PATCH 12/21] Refactoring as seen in PR #8317 --- .../ESP8266WiFi/src/ESP8266WiFiGeneric.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index bd784b48e7..c66f7ad48b 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -627,13 +627,13 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul } } - if(err != 0) { - DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err); - } else { + if(err == ERR_OK) { DEBUG_WIFI_GENERIC("[hostByName] Host: %s IP: %s\n", aHostname, aResult.toString().c_str()); + return 1; + } else { + DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err); + return 0; } - - return (err == ERR_OK) ? 1 : 0; } #if LWIP_IPV4 && LWIP_IPV6 @@ -677,13 +677,13 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul } } - if(err != 0) { - DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err); - } else { + if(err == ERR_OK) { DEBUG_WIFI_GENERIC("[hostByName] Host: %s IP: %s\n", aHostname, aResult.toString().c_str()); + return 1; + } else { + DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err); + return 0; } - - return (err == ERR_OK) ? 1 : 0; } #endif From 4b92d287c075dfc4062234b0816674aceffdde1c Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Thu, 7 Oct 2021 23:09:55 +0200 Subject: [PATCH 13/21] Removed redundant duplicate type definition. --- cores/esp8266/core_esp8266_main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 00e3cc9f19..5545a0e30f 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -162,8 +162,6 @@ extern "C" void __esp_delay(unsigned long ms) { extern "C" void esp_delay(unsigned long ms) __attribute__((weak, alias("__esp_delay"))); -using IsBlockedCB = std::function; - void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms) { const auto start = millis(); decltype(millis()) expired; From 208c4a3f41af444f448ec47dc5c0e9bccbcaac03 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Sat, 9 Oct 2021 02:33:19 +0200 Subject: [PATCH 14/21] Use function template syntax to save using std::function objects. --- cores/esp8266/core_esp8266_main.cpp | 12 +++++++----- cores/esp8266/coredecls.h | 21 +++++++++++++++------ tests/host/common/Arduino.cpp | 16 +++++++++------- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 5545a0e30f..a4be973191 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -162,13 +162,15 @@ extern "C" void __esp_delay(unsigned long ms) { extern "C" void esp_delay(unsigned long ms) __attribute__((weak, alias("__esp_delay"))); -void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms) { - const auto start = millis(); +bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) { decltype(millis()) expired; - while ((expired = millis() - start) < timeout_ms && blocked()) { - auto remaining = timeout_ms - expired; - esp_delay(remaining <= intvl_ms ? remaining : intvl_ms); + + if ((expired = millis() - start_ms) >= timeout_ms) { + return true; } + const auto remaining = timeout_ms - expired; + esp_delay(remaining <= intvl_ms ? remaining : intvl_ms); + return false; } extern "C" void __yield() { diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index 7a7be8b31a..d5da1cfade 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -4,6 +4,8 @@ #define HAVE_ESP_SUSPEND 1 +#include "core_esp8266_features.h" + #ifdef __cplusplus extern "C" { #endif @@ -40,27 +42,34 @@ void settimeofday_cb (BoolCB&& cb); void settimeofday_cb (const BoolCB& cb); void settimeofday_cb (const TrivialCB& cb); -using IsBlockedCB = std::function; - // This overload of esp_suspend() performs the blocked callback whenever it is resumed, // and if that returns true, it immediately suspends again. -inline void esp_suspend(const IsBlockedCB& blocked) { +template +inline void esp_suspend(T&& blocked) { do { esp_suspend(); } while (blocked()); } +bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms); + // This overload of esp_delay() delays for a duration of at most timeout_ms milliseconds. // Whenever it is resumed, as well as every intvl_ms millisconds, it performs // the blocked callback, and if that returns true, it keeps delaying for the remainder // of the original timeout_ms period. -void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms); +template +inline void esp_delay(const uint32_t timeout_ms, T&& blocked, const uint32_t intvl_ms) { + const auto start_ms = millis(); + while (!try_esp_delay(start_ms, timeout_ms, intvl_ms) && blocked()) { + } +} // This overload of esp_delay() delays for a duration of at most timeout_ms milliseconds. // Whenever it is resumed, it performs the blocked callback, and if that returns true, // it keeps delaying for the remainder of the original timeout_ms period. -inline void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked) { - esp_delay(timeout_ms, blocked, timeout_ms); +template +inline void esp_delay(const uint32_t timeout_ms, T&& blocked) { + esp_delay(timeout_ms, std::forward(blocked), timeout_ms); } #endif // __cplusplus diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index eed0ebebdc..e934f8acba 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -71,13 +71,15 @@ extern "C" void esp_delay (unsigned long ms) usleep(ms * 1000); } -using IsBlockedCB = std::function; - -void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms) -{ - (void)blocked; - (void)intvl_ms; - usleep(timeout_ms * 1000); +bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) { + decltype(millis()) expired; + + if ((expired = millis() - start_ms) >= timeout_ms) { + return true; + } + const auto remaining = timeout_ms - expired; + esp_delay(remaining <= intvl_ms ? remaining : intvl_ms); + return false; } extern "C" void __panic_func(const char* file, int line, const char* func) { From 3720ac0a86e09f638e46cc7a6f7275d0d8ab85b9 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Sat, 9 Oct 2021 02:59:51 +0200 Subject: [PATCH 15/21] Fix uninitialized status for immediately expired timeout. --- libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index 992beb23cb..a4d95383e5 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -83,7 +83,7 @@ static void printWiFiStatus(wl_status_t status) */ static wl_status_t waitWiFiConnect(uint32_t connectTimeoutMs) { - wl_status_t status; + wl_status_t status = WL_CONNECT_FAILED; // The final argument, intvl_ms, to esp_delay influences how frequently // the scheduled recurrent functions (Schedule.h) are probed. esp_delay(connectTimeoutMs, From 3be70a45ed7b73810170ec0e434a93b1cb396a1c Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Sat, 9 Oct 2021 09:53:31 +0200 Subject: [PATCH 16/21] Specification for try_esp_delay added as code comment. --- cores/esp8266/coredecls.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index d5da1cfade..e1edf8b927 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -51,6 +51,10 @@ inline void esp_suspend(T&& blocked) { } while (blocked()); } +// Try to delay for timeout_ms relative to start_ms. Returns false if the delayed task +// is asynchronously resumed before the timeout is reached. +// Also returns false if intvl_ms have expired during the active call. +// Otherwise return true to indicate the timeout_ms have completely expired. bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms); // This overload of esp_delay() delays for a duration of at most timeout_ms milliseconds. From 67ced120cf35d779e38b09fe2ceb0c5cbc9e8ced Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" <19971886+dok-net@users.noreply.github.com> Date: Wed, 13 Oct 2021 07:53:09 +0200 Subject: [PATCH 17/21] Apply suggestions from code review Co-authored-by: Max Prokhorov --- cores/esp8266/core_esp8266_main.cpp | 8 +++----- libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp | 12 ++++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index a4be973191..9cd262de26 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -163,13 +163,11 @@ extern "C" void __esp_delay(unsigned long ms) { extern "C" void esp_delay(unsigned long ms) __attribute__((weak, alias("__esp_delay"))); bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) { - decltype(millis()) expired; - - if ((expired = millis() - start_ms) >= timeout_ms) { + uint32_t expired = millis() - start_ms; + if (expired >= timeout_ms) { return true; } - const auto remaining = timeout_ms - expired; - esp_delay(remaining <= intvl_ms ? remaining : intvl_ms); + esp_delay(std::min((timeout_ms - expired), intvl_ms)); return false; } diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp index c66f7ad48b..822f861a91 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp @@ -630,10 +630,10 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul if(err == ERR_OK) { DEBUG_WIFI_GENERIC("[hostByName] Host: %s IP: %s\n", aHostname, aResult.toString().c_str()); return 1; - } else { - DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err); - return 0; } + + DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %s (%d)!\n", aHostname, lwip_strerr(err), (int)err); + return 0; } #if LWIP_IPV4 && LWIP_IPV6 @@ -680,10 +680,10 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul if(err == ERR_OK) { DEBUG_WIFI_GENERIC("[hostByName] Host: %s IP: %s\n", aHostname, aResult.toString().c_str()); return 1; - } else { - DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err); - return 0; } + + DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err); + return 0; } #endif From 62af9406a9030a0aa71754c46bc403a866053254 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Wed, 13 Oct 2021 08:01:30 +0200 Subject: [PATCH 18/21] By review feedback, maintain esp_ as prefix. --- cores/esp8266/core_esp8266_main.cpp | 2 +- cores/esp8266/coredecls.h | 4 ++-- tests/host/common/Arduino.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 9cd262de26..bd784bc7c8 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -162,7 +162,7 @@ extern "C" void __esp_delay(unsigned long ms) { extern "C" void esp_delay(unsigned long ms) __attribute__((weak, alias("__esp_delay"))); -bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) { +bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) { uint32_t expired = millis() - start_ms; if (expired >= timeout_ms) { return true; diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index e1edf8b927..8b176fa0b3 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -55,7 +55,7 @@ inline void esp_suspend(T&& blocked) { // is asynchronously resumed before the timeout is reached. // Also returns false if intvl_ms have expired during the active call. // Otherwise return true to indicate the timeout_ms have completely expired. -bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms); +bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms); // This overload of esp_delay() delays for a duration of at most timeout_ms milliseconds. // Whenever it is resumed, as well as every intvl_ms millisconds, it performs @@ -64,7 +64,7 @@ bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uin template inline void esp_delay(const uint32_t timeout_ms, T&& blocked, const uint32_t intvl_ms) { const auto start_ms = millis(); - while (!try_esp_delay(start_ms, timeout_ms, intvl_ms) && blocked()) { + while (!esp_try_delay(start_ms, timeout_ms, intvl_ms) && blocked()) { } } diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index e934f8acba..293b812bc9 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -71,7 +71,7 @@ extern "C" void esp_delay (unsigned long ms) usleep(ms * 1000); } -bool try_esp_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) { +bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) { decltype(millis()) expired; if ((expired = millis() - start_ms) >= timeout_ms) { From 863c4825e022be7bb76f9ae396b1ef71915f1d12 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Wed, 13 Oct 2021 08:10:32 +0200 Subject: [PATCH 19/21] Code cleanup as per review feedback. --- libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp index a4d95383e5..0f6cb72abe 100644 --- a/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp +++ b/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp @@ -87,7 +87,10 @@ static wl_status_t waitWiFiConnect(uint32_t connectTimeoutMs) // The final argument, intvl_ms, to esp_delay influences how frequently // the scheduled recurrent functions (Schedule.h) are probed. esp_delay(connectTimeoutMs, - [&status]() { status = WiFi.status(); return status != WL_CONNECTED && status != WL_CONNECT_FAILED; }, 0); + [&status]() { + status = WiFi.status(); + return status != WL_CONNECTED && status != WL_CONNECT_FAILED; + }, 0); // Check status if (status == WL_CONNECTED) { @@ -236,7 +239,10 @@ int8_t ESP8266WiFiMulti::startScan() // The final argument, intvl_ms, to esp_delay influences how frequently // the scheduled recurrent functions (Schedule.h) are probed. esp_delay(WIFI_SCAN_TIMEOUT_MS, - [&scanResult]() { scanResult = WiFi.scanComplete(); return scanResult < 0; }, 0); + [&scanResult]() { + scanResult = WiFi.scanComplete(); + return scanResult < 0; + }, 0); // Check for scan timeout which may occur when scan does not report completion if (scanResult < 0) { DEBUG_WIFI_MULTI("[WIFIM] Scan timeout\n"); From 679ecb16cb49a1e8831787db44e540e38cb2bb19 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Thu, 14 Oct 2021 08:12:28 +0200 Subject: [PATCH 20/21] Enable the startWaveform functions for calling from SYS context. Remove microoptimization that could break on inlining. --- cores/esp8266/core_esp8266_waveform_phase.cpp | 2 +- cores/esp8266/core_esp8266_waveform_pwm.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/core_esp8266_waveform_phase.cpp b/cores/esp8266/core_esp8266_waveform_phase.cpp index 873dadede0..4240ccb3c1 100644 --- a/cores/esp8266/core_esp8266_waveform_phase.cpp +++ b/cores/esp8266/core_esp8266_waveform_phase.cpp @@ -211,7 +211,7 @@ int startWaveformClockCycles_weak(uint8_t pin, uint32_t highCcys, uint32_t lowCc } std::atomic_thread_fence(std::memory_order_acq_rel); while (waveform.toSetBits) { - yield(); // Wait for waveform to update + esp_yield(); // Wait for waveform to update std::atomic_thread_fence(std::memory_order_acquire); } return true; diff --git a/cores/esp8266/core_esp8266_waveform_pwm.cpp b/cores/esp8266/core_esp8266_waveform_pwm.cpp index 65e75a0c71..f85ccb76aa 100644 --- a/cores/esp8266/core_esp8266_waveform_pwm.cpp +++ b/cores/esp8266/core_esp8266_waveform_pwm.cpp @@ -373,8 +373,8 @@ int startWaveformClockCycles_weak(uint8_t pin, uint32_t timeHighCycles, uint32_t if (wvfState.waveformEnabled & mask) { // Make sure no waveform changes are waiting to be applied while (wvfState.waveformToChange) { - yield(); // Wait for waveform to update - // No mem barrier here, the call to a global function implies global state updated + esp_yield(); // Wait for waveform to update + MEMBARRIER(); } wvfState.waveformNewHigh = timeHighCycles; wvfState.waveformNewLow = timeLowCycles; @@ -393,8 +393,8 @@ int startWaveformClockCycles_weak(uint8_t pin, uint32_t timeHighCycles, uint32_t initTimer(); forceTimerInterrupt(); while (wvfState.waveformToEnable) { - yield(); // Wait for waveform to update - // No mem barrier here, the call to a global function implies global state updated + esp_yield(); // Wait for waveform to update + MEMBARRIER(); } } From 6199eb922c5265666a6ab108fe0bffc47dece0a0 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Fri, 15 Oct 2021 01:46:37 +0200 Subject: [PATCH 21/21] Adopt same code for host-test version of `esp_try_delay`. Fix in-source specification for the main `esp_try_delay`. --- cores/esp8266/coredecls.h | 9 +++++---- tests/host/common/Arduino.cpp | 8 +++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/cores/esp8266/coredecls.h b/cores/esp8266/coredecls.h index 8b176fa0b3..e5573792bb 100644 --- a/cores/esp8266/coredecls.h +++ b/cores/esp8266/coredecls.h @@ -51,10 +51,11 @@ inline void esp_suspend(T&& blocked) { } while (blocked()); } -// Try to delay for timeout_ms relative to start_ms. Returns false if the delayed task -// is asynchronously resumed before the timeout is reached. -// Also returns false if intvl_ms have expired during the active call. -// Otherwise return true to indicate the timeout_ms have completely expired. +// Try to delay until timeout_ms has expired since start_ms. +// Returns true if timeout_ms has completely expired on entry. +// Otherwise returns false after delaying for the relative +// remainder of timeout_ms, or an absolute intvl_ms, whichever is shorter. +// The delay may be asynchronously cancelled, before that timeout is reached. bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms); // This overload of esp_delay() delays for a duration of at most timeout_ms milliseconds. diff --git a/tests/host/common/Arduino.cpp b/tests/host/common/Arduino.cpp index 293b812bc9..c2c1fa10a2 100644 --- a/tests/host/common/Arduino.cpp +++ b/tests/host/common/Arduino.cpp @@ -72,13 +72,11 @@ extern "C" void esp_delay (unsigned long ms) } bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) { - decltype(millis()) expired; - - if ((expired = millis() - start_ms) >= timeout_ms) { + uint32_t expired = millis() - start_ms; + if (expired >= timeout_ms) { return true; } - const auto remaining = timeout_ms - expired; - esp_delay(remaining <= intvl_ms ? remaining : intvl_ms); + esp_delay(std::min((timeout_ms - expired), intvl_ms)); return false; }