Skip to content

Commit 0bb470c

Browse files
committed
Merge branch 'esp_yield_mt' into delay0isyield
1 parent 397408f commit 0bb470c

File tree

10 files changed

+130
-91
lines changed

10 files changed

+130
-91
lines changed

Diff for: cores/esp8266/core_esp8266_main.cpp

+37-2
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ const char* core_release =
8080
#else
8181
NULL;
8282
#endif
83+
84+
static os_timer_t delay_timer;
85+
#define ONCE 0
86+
#define REPEAT 1
8387
} // extern "C"
8488

8589
void initVariant() __attribute__((weak));
@@ -137,6 +141,38 @@ extern "C" void esp_yield() {
137141
esp_suspend();
138142
}
139143

144+
void delay_end(void* arg) {
145+
(void)arg;
146+
esp_schedule();
147+
}
148+
149+
extern "C" void __esp_delay(unsigned long ms) {
150+
if (ms) {
151+
os_timer_setfn(&delay_timer, (os_timer_func_t*)&delay_end, 0);
152+
os_timer_arm(&delay_timer, ms, ONCE);
153+
}
154+
else {
155+
esp_schedule();
156+
}
157+
esp_suspend();
158+
if (ms) {
159+
os_timer_disarm(&delay_timer);
160+
}
161+
}
162+
163+
extern "C" void esp_delay(unsigned long ms) __attribute__((weak, alias("__esp_delay")));
164+
165+
using IsBlockedCB = std::function<bool()>;
166+
167+
void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms) {
168+
const auto start = millis();
169+
decltype(millis()) expired;
170+
while ((expired = millis() - start) < timeout_ms && blocked()) {
171+
auto remaining = timeout_ms - expired;
172+
esp_delay(remaining <= intvl_ms ? remaining : intvl_ms);
173+
}
174+
}
175+
140176
extern "C" void __yield() {
141177
if (cont_can_suspend(g_pcont)) {
142178
esp_schedule();
@@ -224,8 +260,8 @@ static void loop_task(os_event_t *events) {
224260
panic();
225261
}
226262
}
227-
extern "C" {
228263

264+
extern "C" {
229265
struct object { long placeholder[ 10 ]; };
230266
void __register_frame_info (const void *begin, struct object *ob);
231267
extern char __eh_frame[];
@@ -262,7 +298,6 @@ static void __unhandled_exception_cpp()
262298
}
263299
#endif
264300
}
265-
266301
}
267302

268303
void init_done() {

Diff for: cores/esp8266/core_esp8266_wiring.cpp

+1-17
Original file line numberDiff line numberDiff line change
@@ -23,34 +23,18 @@
2323
#include "ets_sys.h"
2424
#include "osapi.h"
2525
#include "user_interface.h"
26-
#include "cont.h"
2726
#include "coredecls.h"
2827

2928
extern "C" {
3029

31-
static os_timer_t delay_timer;
3230
static os_timer_t micros_overflow_timer;
3331
static uint32_t micros_at_last_overflow_tick = 0;
3432
static uint32_t micros_overflow_count = 0;
3533
#define ONCE 0
3634
#define REPEAT 1
3735

38-
void delay_end(void* arg) {
39-
(void) arg;
40-
esp_schedule();
41-
}
42-
4336
void __delay(unsigned long ms) {
44-
if(ms) {
45-
os_timer_setfn(&delay_timer, (os_timer_func_t*) &delay_end, 0);
46-
os_timer_arm(&delay_timer, ms, ONCE);
47-
} else {
48-
esp_schedule();
49-
}
50-
esp_suspend();
51-
if(ms) {
52-
os_timer_disarm(&delay_timer);
53-
}
37+
esp_delay(ms);
5438
}
5539

5640
void delay(unsigned long ms) __attribute__ ((weak, alias("__delay")));

Diff for: cores/esp8266/coredecls.h

+16
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extern "C" {
1616

1717
bool can_yield();
1818
void esp_suspend();
19+
void esp_delay(unsigned long ms);
1920
void esp_schedule();
2021
void esp_yield();
2122
void tune_timeshift64 (uint64_t now_us);
@@ -35,9 +36,24 @@ uint32_t crc32 (const void* data, size_t length, uint32_t crc = 0xffffffff);
3536
using BoolCB = std::function<void(bool)>;
3637
using TrivialCB = std::function<void()>;
3738

39+
void settimeofday_cb (BoolCB&& cb);
3840
void settimeofday_cb (const BoolCB& cb);
3941
void settimeofday_cb (const TrivialCB& cb);
4042

43+
using IsBlockedCB = std::function<bool()>;
44+
45+
inline void esp_suspend(const IsBlockedCB& blocked) {
46+
do {
47+
esp_suspend();
48+
} while (blocked());
49+
}
50+
51+
void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked, const uint32_t intvl_ms);
52+
53+
inline void esp_delay(const uint32_t timeout_ms, const IsBlockedCB& blocked) {
54+
esp_delay(timeout_ms, blocked, timeout_ms);
55+
}
56+
4157
#endif // __cplusplus
4258

4359
#endif // __COREDECLS_H

Diff for: cores/esp8266/time.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ void settimeofday_cb (const TrivialCB& cb)
214214
_settimeofday_cb = [cb](bool sntp) { (void)sntp; cb(); };
215215
}
216216

217+
void settimeofday_cb (BoolCB&& cb)
218+
{
219+
_settimeofday_cb = std::move(cb);
220+
}
221+
217222
void settimeofday_cb (const BoolCB& cb)
218223
{
219224
_settimeofday_cb = cb;

Diff for: libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -434,10 +434,9 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m) {
434434
//tasks to wait correctly.
435435
constexpr unsigned int timeoutValue = 1000; //1 second
436436
if(can_yield()) {
437-
using oneShot = esp8266::polledTimeout::oneShotFastMs;
438-
oneShot timeout(timeoutValue);
439-
while(wifi_get_opmode() != (uint8) m && !timeout)
440-
delay(5);
437+
// The final argument, intvl_ms, to esp_delay influences how frequently
438+
// the scheduled recurrent functions (Schedule.h) are probed.
439+
esp_delay(timeoutValue, [m]() { return wifi_get_opmode() != m; }, 5);
441440

442441
//if at this point mode still hasn't been reached, give up
443442
if(wifi_get_opmode() != (uint8) m) {
@@ -617,7 +616,7 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul
617616
aResult = IPAddress(&addr);
618617
} else if(err == ERR_INPROGRESS) {
619618
_dns_lookup_pending = true;
620-
delay(timeout_ms);
619+
esp_delay(timeout_ms, []() { return _dns_lookup_pending; });
621620
// will resume on timeout or when wifi_dns_found_callback fires
622621
_dns_lookup_pending = false;
623622
// will return here when dns_found_callback fires
@@ -667,8 +666,8 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul
667666
aResult = IPAddress(&addr);
668667
} else if(err == ERR_INPROGRESS) {
669668
_dns_lookup_pending = true;
670-
delay(timeout_ms);
671669
// will resume on timeout or when wifi_dns_found_callback fires
670+
esp_delay(timeout_ms, []() { return _dns_lookup_pending; });
672671
_dns_lookup_pending = false;
673672
// will return here when dns_found_callback fires
674673
if(aResult.isSet()) {
@@ -701,7 +700,8 @@ void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *ca
701700
if(ipaddr) {
702701
(*reinterpret_cast<IPAddress*>(callback_arg)) = IPAddress(ipaddr);
703702
}
704-
esp_schedule(); // break delay in hostByName
703+
_dns_lookup_pending = false; // resume hostByName
704+
esp_schedule();
705705
}
706706

707707
uint32_t ESP8266WiFiGenericClass::shutdownCRC (const WiFiState& state)

Diff for: libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp

+25-44
Original file line numberDiff line numberDiff line change
@@ -84,36 +84,25 @@ static void printWiFiStatus(wl_status_t status)
8484
static wl_status_t waitWiFiConnect(uint32_t connectTimeoutMs)
8585
{
8686
wl_status_t status;
87+
// The final argument, intvl_ms, to esp_delay influences how frequently
88+
// the scheduled recurrent functions (Schedule.h) are probed.
89+
esp_delay(connectTimeoutMs,
90+
[&status]() { status = WiFi.status(); return status != WL_CONNECTED && status != WL_CONNECT_FAILED; }, 0);
8791

88-
// Set WiFi connect timeout
89-
using esp8266::polledTimeout::oneShotMs;
90-
oneShotMs connectTimeout(connectTimeoutMs);
91-
92-
// Wait for WiFi status change or timeout
93-
do {
94-
// Refresh watchdog
95-
esp_yield();
96-
97-
// Get WiFi status
98-
status = WiFi.status();
99-
100-
// Check status
101-
if (status == WL_CONNECTED) {
102-
// Connected, print WiFi status
103-
printWiFiStatus(status);
104-
105-
// Return WiFi status
106-
return status;
107-
} else if (status == WL_CONNECT_FAILED) {
108-
DEBUG_WIFI_MULTI("[WIFIM] Connect failed\n");
109-
110-
// Return WiFi connect failed
111-
return WL_CONNECT_FAILED;
112-
}
113-
} while (!connectTimeout);
92+
// Check status
93+
if (status == WL_CONNECTED) {
94+
// Connected, print WiFi status
95+
printWiFiStatus(status);
11496

115-
DEBUG_WIFI_MULTI("[WIFIM] Connect timeout\n");
97+
// Return WiFi status
98+
return status;
99+
} else if (status == WL_CONNECT_FAILED) {
100+
DEBUG_WIFI_MULTI("[WIFIM] Connect failed\n");
101+
} else {
102+
DEBUG_WIFI_MULTI("[WIFIM] Connect timeout\n");
103+
}
116104

105+
// Return WiFi connect failed
117106
return WL_CONNECT_FAILED;
118107
}
119108

@@ -243,24 +232,16 @@ int8_t ESP8266WiFiMulti::startScan()
243232
// Start wifi scan in async mode
244233
WiFi.scanNetworks(true);
245234

246-
// Set WiFi scan timeout
247-
using esp8266::polledTimeout::oneShotMs;
248-
oneShotMs scanTimeout(WIFI_SCAN_TIMEOUT_MS);
249-
250235
// Wait for WiFi scan change or timeout
251-
do {
252-
// Refresh watchdog
253-
esp_yield();
254-
255-
// Check scan timeout which may occur when scan does not report completion
256-
if (scanTimeout) {
257-
DEBUG_WIFI_MULTI("[WIFIM] Scan timeout\n");
258-
return WIFI_SCAN_FAILED;
259-
}
260-
261-
// Get scan result
262-
scanResult = WiFi.scanComplete();
263-
} while (scanResult < 0);
236+
// The final argument, intvl_ms, to esp_delay influences how frequently
237+
// the scheduled recurrent functions (Schedule.h) are probed.
238+
esp_delay(WIFI_SCAN_TIMEOUT_MS,
239+
[&scanResult]() { scanResult = WiFi.scanComplete(); return scanResult < 0; }, 0);
240+
// Check for scan timeout which may occur when scan does not report completion
241+
if (scanResult < 0) {
242+
DEBUG_WIFI_MULTI("[WIFIM] Scan timeout\n");
243+
return WIFI_SCAN_FAILED;
244+
}
264245

265246
// Print WiFi scan result
266247
printWiFiScan();

Diff for: libraries/ESP8266WiFi/src/ESP8266WiFiSTA-WPS.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
static void wifi_wps_status_cb(wps_cb_status status);
3232

33+
static bool _wps_config_pending = false;
34+
3335
/**
3436
* WPS config
3537
* so far only WPS_TYPE_PBC is supported (SDK 1.2.0)
@@ -70,8 +72,9 @@ bool ESP8266WiFiSTAClass::beginWPSConfig(void) {
7072
return false;
7173
}
7274

73-
esp_suspend();
75+
_wps_config_pending = true;
7476
// will resume when wifi_wps_status_cb fires
77+
esp_suspend([]() { return _wps_config_pending; });
7578

7679
return true;
7780
}
@@ -107,5 +110,6 @@ void wifi_wps_status_cb(wps_cb_status status) {
107110
}
108111
// TODO user function to get status
109112

110-
esp_schedule(); // resume beginWPSConfig
113+
_wps_config_pending = false; // resume beginWPSConfig
114+
esp_schedule();
111115
}

Diff for: libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
#include "ESP8266WiFiGeneric.h"
2727
#include "ESP8266WiFiScan.h"
2828

29-
#include <coredecls.h>
30-
3129
extern "C" {
3230
#include "c_types.h"
3331
#include "ets_sys.h"
@@ -38,6 +36,7 @@ extern "C" {
3836
}
3937

4038
#include "debug.h"
39+
#include <coredecls.h>
4140

4241
// -----------------------------------------------------------------------------------------------------------------------
4342
// ---------------------------------------------------- Private functions ------------------------------------------------
@@ -97,7 +96,9 @@ int8_t ESP8266WiFiScanClass::scanNetworks(bool async, bool show_hidden, uint8 ch
9796
return WIFI_SCAN_RUNNING;
9897
}
9998

100-
esp_suspend(); // will resume when _scanDone fires
99+
// will resume when _scanDone fires
100+
esp_suspend([]() { return !ESP8266WiFiScanClass::_scanComplete && ESP8266WiFiScanClass::_scanStarted; });
101+
101102
return ESP8266WiFiScanClass::_scanCount;
102103
} else {
103104
return WIFI_SCAN_FAILED;
@@ -321,7 +322,7 @@ void ESP8266WiFiScanClass::_scanDone(void* result, int status) {
321322
ESP8266WiFiScanClass::_scanStarted = false;
322323
ESP8266WiFiScanClass::_scanComplete = true;
323324

324-
if(!ESP8266WiFiScanClass::_scanAsync) {
325+
if (!ESP8266WiFiScanClass::_scanAsync) {
325326
esp_schedule(); // resume scanNetworks
326327
} else if (ESP8266WiFiScanClass::_onComplete) {
327328
ESP8266WiFiScanClass::_onComplete(ESP8266WiFiScanClass::_scanCount);

0 commit comments

Comments
 (0)