1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-13 02:22:55 +03:00

Implement esp_yield() as a replacement for delay(0)

esp_yield() now also calls esp_schedule(), original esp_yield() function renamed to esp_suspend().

Don't use delay(0) in the Core internals, libraries and examples. Use yield() when the code is
supposed to be called from CONT, use esp_yield() when the code can be called from either CONT or SYS.
Clean-up esp_yield() and esp_schedule() declarations across the code and use coredecls.h instead.

Implement helper functions for libraries that were previously using esp_yield(), esp_schedule() and
esp_delay() directly to wait for certain SYS context tasks to complete. Correctly use esp_delay()
for timeouts, make sure scheduled functions have a chance to run (e.g. LwIP_Ethernet uses recurrent)

Related issues:
- #6107 - discussion about the esp_yield() and esp_delay() usage in ClientContext
- #6212 - discussion about replacing delay() with a blocking loop
- #6680 - pull request introducing LwIP-based Ethernet
- #7146 - discussion that originated UART code changes
- #7969 - proposal to remove delay(0) from the example code
- #8291 - discussion related to the run_scheduled_recurrent_functions() usage in LwIP Ethernet
- #8317 - yieldUntil() implementation, similar to the esp_delay() overload with a timeout and a 0 interval
This commit is contained in:
Dirk O. Kaar
2021-10-16 23:19:01 +02:00
committed by GitHub
parent 40b26b769c
commit c312a2eaf1
32 changed files with 286 additions and 213 deletions

View File

@ -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 -----------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------
@ -438,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) {
@ -518,9 +513,9 @@ bool ESP8266WiFiGenericClass::forceSleepBegin(uint32 sleepUs) {
}
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
delay(0);
esp_yield();
wifi_fpm_open();
delay(0);
esp_yield();
auto ret = wifi_fpm_do_sleep(sleepUs);
if (ret != 0)
{
@ -621,22 +616,24 @@ 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
// 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;
}
}
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;
}
return (err == ERR_OK) ? 1 : 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
@ -671,8 +668,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()) {
@ -680,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;
}
return (err == ERR_OK) ? 1 : 0;
DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, (int)err);
return 0;
}
#endif
@ -705,7 +702,8 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca
if(ipaddr) {
(*reinterpret_cast<IPAddress*>(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)