From d6e603f397a17263c1b7a00568e4cf0af2dcf4b6 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Mon, 18 Nov 2019 22:39:51 +0100 Subject: [PATCH 1/8] Fix optimistic_yield to not yield on every call after a loop runs for x us, but yield only every x us between optimistic_yield calls. --- cores/esp8266/core_esp8266_main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 850d9b95a8..40bacd7600 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -58,7 +58,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_micros_at_task_start; +static uint32_t s_micros_since_yield_start; /* For ets_intr_lock_nest / ets_intr_unlock_nest * Max nesting seen by SDK so far is 2. @@ -116,6 +116,7 @@ extern "C" void __yield() { if (can_yield()) { esp_schedule(); esp_yield_within_cont(); + s_micros_since_yield_start = system_get_time(); } else { panic(); @@ -126,7 +127,7 @@ extern "C" void yield(void) __attribute__ ((weak, alias("__yield"))); extern "C" void optimistic_yield(uint32_t interval_us) { if (can_yield() && - (system_get_time() - s_micros_at_task_start) > interval_us) + (system_get_time() - s_micros_since_yield_start) > interval_us) { yield(); } @@ -183,7 +184,7 @@ static void loop_wrapper() { static void loop_task(os_event_t *events) { (void) events; - s_micros_at_task_start = system_get_time(); + s_micros_since_yield_start = system_get_time(); cont_run(g_pcont, &loop_wrapper); if (cont_check(g_pcont) != 0) { panic(); From 598361f3aa8b65283318fc41b85a748bf94705f0 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Tue, 19 Nov 2019 01:36:59 +0100 Subject: [PATCH 2/8] Substitute micros() by CPU cycles - faster, but large values for interval_us can overflow - 26s at 160MHz CPU clock. --- cores/esp8266/core_esp8266_main.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 40bacd7600..70f4215d7f 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -58,7 +58,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_micros_since_yield_start; +static uint32_t s_cycles_since_yield_start; /* For ets_intr_lock_nest / ets_intr_unlock_nest * Max nesting seen by SDK so far is 2. @@ -116,7 +116,7 @@ extern "C" void __yield() { if (can_yield()) { esp_schedule(); esp_yield_within_cont(); - s_micros_since_yield_start = system_get_time(); + s_cycles_since_yield_start = ESP.getCycleCount(); } else { panic(); @@ -126,8 +126,9 @@ extern "C" void __yield() { extern "C" void yield(void) __attribute__ ((weak, alias("__yield"))); extern "C" void optimistic_yield(uint32_t interval_us) { + const uint32_t interval_cycles = interval_us * ESP.getCpuFreqMHz(); if (can_yield() && - (system_get_time() - s_micros_since_yield_start) > interval_us) + (ESP.getCycleCount() - s_cycles_since_yield_start) > interval_cycles) { yield(); } @@ -184,7 +185,7 @@ static void loop_wrapper() { static void loop_task(os_event_t *events) { (void) events; - s_micros_since_yield_start = system_get_time(); + s_cycles_since_yield_start = ESP.getCycleCount(); cont_run(g_pcont, &loop_wrapper); if (cont_check(g_pcont) != 0) { panic(); @@ -212,7 +213,7 @@ extern void __unhandled_exception(const char *str); static void __unhandled_exception_cpp() { #ifndef __EXCEPTIONS - abort(); + abort(); #else static bool terminating; if (terminating) From 3d7423bddea68eb78d49edb2389d8cf1286d6dd5 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Tue, 19 Nov 2019 13:49:19 +0100 Subject: [PATCH 3/8] Move yield start time set to esp_yield_within_cont --- cores/esp8266/core_esp8266_main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 70f4215d7f..aca69a2169 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -97,6 +97,7 @@ extern "C" bool can_yield() { static inline void esp_yield_within_cont() __attribute__((always_inline)); static void esp_yield_within_cont() { cont_yield(g_pcont); + s_cycles_since_yield_start = ESP.getCycleCount(); run_scheduled_recurrent_functions(); } @@ -116,7 +117,6 @@ extern "C" void __yield() { if (can_yield()) { esp_schedule(); esp_yield_within_cont(); - s_cycles_since_yield_start = ESP.getCycleCount(); } else { panic(); @@ -134,7 +134,6 @@ extern "C" void optimistic_yield(uint32_t interval_us) { } } - // Replace ets_intr_(un)lock with nestable versions extern "C" void IRAM_ATTR ets_intr_lock() { if (ets_intr_lock_stack_ptr < ETS_INTR_LOCK_NEST_MAX) From 3767791fbc4ce348095ea9f305817f9f89c594ac Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Mon, 2 Dec 2019 11:05:21 +0100 Subject: [PATCH 4/8] Allow constexpr evalution to occur. optimistic_yield is always called with a literal parameter value. --- cores/esp8266/Arduino.h | 19 ++++++++++++++++++- cores/esp8266/core_esp8266_main.cpp | 9 ++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 54919ba100..a7e5ca23bf 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -204,7 +204,24 @@ void setup(void); void loop(void); void yield(void); -void optimistic_yield(uint32_t interval_us); + +#ifndef F_CPU +// single function needed from SDK user_interface.h +extern "C" uint8 system_get_cpu_freq(void); +#endif + +void __optimistic_yield(uint32_t intvl_cycles); + +void inline optimistic_yield(uint32_t interval_us) __attribute__((always_inline)); +void inline optimistic_yield(uint32_t interval_us) { + __optimistic_yield(interval_us * +#if defined(F_CPU) + clockCyclesPerMicrosecond() +#else + getCpuFreqMHz() +#endif + ); +} #define _PORT_GPIO16 1 #define digitalPinToPort(pin) (((pin)==16)?(_PORT_GPIO16):(0)) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index aca69a2169..48a20dd1f9 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -57,7 +57,7 @@ cont_t* g_pcont __attribute__((section(".noinit"))); /* Event queue used by the main (arduino) task */ static os_event_t s_loop_queue[LOOP_QUEUE_SIZE]; -/* Used to implement optimistic_yield */ +/* Used to implement __optimistic_yield */ static uint32_t s_cycles_since_yield_start; /* For ets_intr_lock_nest / ets_intr_unlock_nest @@ -125,10 +125,9 @@ extern "C" void __yield() { extern "C" void yield(void) __attribute__ ((weak, alias("__yield"))); -extern "C" void optimistic_yield(uint32_t interval_us) { - const uint32_t interval_cycles = interval_us * ESP.getCpuFreqMHz(); - if (can_yield() && - (ESP.getCycleCount() - s_cycles_since_yield_start) > interval_cycles) +extern "C" void __optimistic_yield(uint32_t intvl_cycles) { + if ((ESP.getCycleCount() - s_cycles_since_yield_start) > intvl_cycles && + can_yield()) { yield(); } From 554435780b3db892d0002cec5e707ea3ec984532 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Mon, 2 Dec 2019 11:58:45 +0100 Subject: [PATCH 5/8] Due to 3rd party use of symbol optimistic_yield without #include , have to resort to preprocessor definition for inlining. --- cores/esp8266/Arduino.h | 9 ++------- cores/esp8266/core_esp8266_main.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index a7e5ca23bf..dbde309fb6 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -212,16 +212,11 @@ extern "C" uint8 system_get_cpu_freq(void); void __optimistic_yield(uint32_t intvl_cycles); -void inline optimistic_yield(uint32_t interval_us) __attribute__((always_inline)); -void inline optimistic_yield(uint32_t interval_us) { - __optimistic_yield(interval_us * #if defined(F_CPU) - clockCyclesPerMicrosecond() +#define optimistic_yield(interval_us) (__optimistic_yield(interval_us * clockCyclesPerMicrosecond())) #else - getCpuFreqMHz() +#define optimistic_yield(interval_us) (__optimistic_yield(interval_us * getCpuFreqMHz())) #endif - ); -} #define _PORT_GPIO16 1 #define digitalPinToPort(pin) (((pin)==16)?(_PORT_GPIO16):(0)) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 48a20dd1f9..2037d2535f 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -133,6 +133,17 @@ extern "C" void __optimistic_yield(uint32_t intvl_cycles) { } } +#undef optimistic_yield +extern "C" void optimistic_yield(uint32_t interval_us) { + __optimistic_yield(interval_us * +#if defined(F_CPU) + clockCyclesPerMicrosecond() +#else + getCpuFreqMHz() +#endif + ); +} + // Replace ets_intr_(un)lock with nestable versions extern "C" void IRAM_ATTR ets_intr_lock() { if (ets_intr_lock_stack_ptr < ETS_INTR_LOCK_NEST_MAX) From 8d2eca56847a0344ea1b76ce62598bd4bcf2657b Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Wed, 18 Dec 2019 09:27:00 +0100 Subject: [PATCH 6/8] Remove long-since disused define. --- cores/esp8266/core_esp8266_main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 2037d2535f..c4be729fa3 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -37,7 +37,6 @@ extern "C" { #define LOOP_TASK_PRIORITY 1 #define LOOP_QUEUE_SIZE 1 -#define OPTIMISTIC_YIELD_TIME_US 16000 extern "C" void call_user_start(); extern void loop(); From 50fab5162fdc09430a73f581043b4b669837ccf1 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Tue, 24 Dec 2019 23:43:04 +0100 Subject: [PATCH 7/8] No need for preprocessor undefinition of optimistic_yield, after all. --- cores/esp8266/Arduino.h | 13 +------------ cores/esp8266/core_esp8266_main.cpp | 19 +++++++------------ 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index dbde309fb6..f82b3aea96 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -205,18 +205,7 @@ void loop(void); void yield(void); -#ifndef F_CPU -// single function needed from SDK user_interface.h -extern "C" uint8 system_get_cpu_freq(void); -#endif - -void __optimistic_yield(uint32_t intvl_cycles); - -#if defined(F_CPU) -#define optimistic_yield(interval_us) (__optimistic_yield(interval_us * clockCyclesPerMicrosecond())) -#else -#define optimistic_yield(interval_us) (__optimistic_yield(interval_us * getCpuFreqMHz())) -#endif +void optimistic_yield(uint32_t interval_us); #define _PORT_GPIO16 1 #define digitalPinToPort(pin) (((pin)==16)?(_PORT_GPIO16):(0)) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index c4be729fa3..bbcfd29efe 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -124,7 +124,13 @@ extern "C" void __yield() { extern "C" void yield(void) __attribute__ ((weak, alias("__yield"))); -extern "C" void __optimistic_yield(uint32_t intvl_cycles) { +extern "C" void optimistic_yield(uint32_t interval_us) { + const uint32_t intvl_cycles = interval_us * +#if defined(F_CPU) + clockCyclesPerMicrosecond(); +#else + getCpuFreqMHz(); +#endif if ((ESP.getCycleCount() - s_cycles_since_yield_start) > intvl_cycles && can_yield()) { @@ -132,17 +138,6 @@ extern "C" void __optimistic_yield(uint32_t intvl_cycles) { } } -#undef optimistic_yield -extern "C" void optimistic_yield(uint32_t interval_us) { - __optimistic_yield(interval_us * -#if defined(F_CPU) - clockCyclesPerMicrosecond() -#else - getCpuFreqMHz() -#endif - ); -} - // Replace ets_intr_(un)lock with nestable versions extern "C" void IRAM_ATTR ets_intr_lock() { if (ets_intr_lock_stack_ptr < ETS_INTR_LOCK_NEST_MAX) From afe40211ef2011e642fa8fd963389f7dadcf612c Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Thu, 20 Feb 2020 19:41:08 +0100 Subject: [PATCH 8/8] Corrections after review remarks; thanks @earlephilhower --- cores/esp8266/core_esp8266_main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index bbcfd29efe..a95c4b2c11 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -56,8 +56,8 @@ cont_t* g_pcont __attribute__((section(".noinit"))); /* Event queue used by the main (arduino) task */ static os_event_t s_loop_queue[LOOP_QUEUE_SIZE]; -/* Used to implement __optimistic_yield */ -static uint32_t s_cycles_since_yield_start; +/* Used to implement optimistic_yield */ +static uint32_t s_cycles_at_yield_start; /* For ets_intr_lock_nest / ets_intr_unlock_nest * Max nesting seen by SDK so far is 2. @@ -96,7 +96,7 @@ extern "C" bool can_yield() { static inline void esp_yield_within_cont() __attribute__((always_inline)); static void esp_yield_within_cont() { cont_yield(g_pcont); - s_cycles_since_yield_start = ESP.getCycleCount(); + s_cycles_at_yield_start = ESP.getCycleCount(); run_scheduled_recurrent_functions(); } @@ -129,9 +129,9 @@ extern "C" void optimistic_yield(uint32_t interval_us) { #if defined(F_CPU) clockCyclesPerMicrosecond(); #else - getCpuFreqMHz(); + ESP.getCpuFreqMHz(); #endif - if ((ESP.getCycleCount() - s_cycles_since_yield_start) > intvl_cycles && + if ((ESP.getCycleCount() - s_cycles_at_yield_start) > intvl_cycles && can_yield()) { yield(); @@ -188,7 +188,7 @@ static void loop_wrapper() { static void loop_task(os_event_t *events) { (void) events; - s_cycles_since_yield_start = ESP.getCycleCount(); + s_cycles_at_yield_start = ESP.getCycleCount(); cont_run(g_pcont, &loop_wrapper); if (cont_check(g_pcont) != 0) { panic();