Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit39080e3

Browse files
authored
delay / esp_delay: transparently manage recurrent scheduled functions (#8802)
Recurrent scheduled functions will always be running in background.esp_delay()'s interval (intvl_ms) is internally kept to its highest value allowing to honor recurrent scheduled functions requirements.It transparently allows to keep with the arduino and nonos-sdk trivial programming way and still use background services or drivers running regularly.
1 parente1c4a6c commit39080e3

File tree

8 files changed

+74
-30
lines changed

8 files changed

+74
-30
lines changed

‎cores/esp8266/Schedule.cpp‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
#include<assert.h>
20+
#include<numeric>
2021

2122
#include"Schedule.h"
2223
#include"PolledTimeout.h"
@@ -34,6 +35,7 @@ static scheduled_fn_t* sFirst = nullptr;
3435
staticscheduled_fn_t*sLast =nullptr;
3536
staticscheduled_fn_t*sUnused =nullptr;
3637
staticintsCount =0;
38+
staticuint32_t recurrent_max_grain_mS =0;
3739

3840
typedef std::function<bool(void)>mRecFuncT;
3941
structrecurrent_fn_t
@@ -130,9 +132,39 @@ bool schedule_recurrent_function_us(const std::function<bool(void)>& fn,
130132
}
131133
rLast = item;
132134

135+
// grain needs to be recomputed
136+
recurrent_max_grain_mS =0;
137+
133138
returntrue;
134139
}
135140

141+
uint32_tcompute_scheduled_recurrent_grain ()
142+
{
143+
if (recurrent_max_grain_mS ==0)
144+
{
145+
if (rFirst)
146+
{
147+
uint32_t recurrent_max_grain_uS = rFirst->callNow.getTimeout();
148+
for (auto it = rFirst->mNext; it; it = it->mNext)
149+
recurrent_max_grain_uS =std::gcd(recurrent_max_grain_uS, it->callNow.getTimeout());
150+
if (recurrent_max_grain_uS)
151+
// round to the upper millis
152+
recurrent_max_grain_mS = recurrent_max_grain_uS <=1000?1: (recurrent_max_grain_uS +999) /1000;
153+
}
154+
155+
#ifdef DEBUG_ESP_CORE
156+
staticuint32_t last_grain =0;
157+
if (recurrent_max_grain_mS != last_grain)
158+
{
159+
::printf(":rsf %u->%u\n", last_grain, recurrent_max_grain_mS);
160+
last_grain = recurrent_max_grain_mS;
161+
}
162+
#endif
163+
}
164+
165+
return recurrent_max_grain_mS;
166+
}
167+
136168
voidrun_scheduled_functions()
137169
{
138170
// prevent scheduling of new functions during this run
@@ -226,6 +258,9 @@ void run_scheduled_recurrent_functions()
226258
}
227259

228260
delete(to_ditch);
261+
262+
// grain needs to be recomputed
263+
recurrent_max_grain_mS =0;
229264
}
230265
else
231266
{

‎cores/esp8266/Schedule.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
// scheduled function happen more often: every yield() (vs every loop()),
4040
// and time resolution is microsecond (vs millisecond). Details are below.
4141

42+
// compute_scheduled_recurrent_grain() is used by delay() to give a chance to
43+
// all recurrent functions to run per their timing requirement.
44+
45+
uint32_tcompute_scheduled_recurrent_grain ();
46+
4247
// scheduled functions called once:
4348
//
4449
// * internal queue is FIFO.

‎cores/esp8266/core_esp8266_main.cpp‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
//This may be used to change user task stack size:
2424
//#define CONT_STACKSIZE 4096
25+
26+
#include<numeric>
27+
2528
#include<Arduino.h>
2629
#include"Schedule.h"
2730
extern"C" {
@@ -165,10 +168,18 @@ extern "C" void esp_delay(unsigned long ms) __attribute__((weak, alias("__esp_de
165168
boolesp_try_delay(constuint32_t start_ms,constuint32_t timeout_ms,constuint32_t intvl_ms) {
166169
uint32_t expired =millis() - start_ms;
167170
if (expired >= timeout_ms) {
168-
returntrue;
171+
returntrue;// expired
169172
}
170-
esp_delay(std::min((timeout_ms - expired), intvl_ms));
171-
returnfalse;
173+
174+
// compute greatest chunked delay with respect to scheduled recurrent functions
175+
uint32_t grain_ms =std::gcd(intvl_ms,compute_scheduled_recurrent_grain());
176+
177+
// recurrent scheduled functions will be called from esp_delay()->esp_suspend()
178+
esp_delay(grain_ms >0 ?
179+
std::min((timeout_ms - expired), grain_ms):
180+
(timeout_ms - expired));
181+
182+
returnfalse;// expiration must be checked again
172183
}
173184

174185
extern"C"void__yield() {

‎cores/esp8266/core_esp8266_wiring.cpp‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ static uint32_t micros_overflow_count = 0;
3434
#defineREPEAT1
3535

3636
void__delay(unsignedlong ms) {
37-
esp_delay(ms);
37+
// Use API letting recurrent scheduled functions run in background
38+
// but stay blocked in delay until ms is expired.
39+
esp_delay(ms, [](){returntrue; });
3840
}
3941

4042
voiddelay(unsignedlong ms) __attribute__ ((weak, alias("__delay")));

‎cores/esp8266/coredecls.h‎

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11

2-
#ifndef __COREDECLS_H
3-
#define__COREDECLS_H
2+
#pragma once
43

54
#include"core_esp8266_features.h"
65

@@ -55,14 +54,15 @@ inline void esp_suspend(T&& blocked) {
5554
// Try to delay until timeout_ms has expired since start_ms.
5655
// Returns true if timeout_ms has completely expired on entry.
5756
// Otherwise returns false after delaying for the relative
58-
// remainder of timeout_ms, or an absolute intvl_ms, whichever is shorter.
57+
// remainder of timeout_ms, or an absolute intvl_ms, whichever is shorter
58+
// and possibly amended by recurrent scheduled functions timing grain.
5959
// The delay may be asynchronously cancelled, before that timeout is reached.
6060
boolesp_try_delay(constuint32_t start_ms,constuint32_t timeout_ms,constuint32_t intvl_ms);
6161

6262
// This overload of esp_delay() delays for a duration of at most timeout_ms milliseconds.
63-
// Whenever it is resumed, as well as every intvl_ms millisconds, it performs
64-
// the blocked callback, and if that returns true, it keeps delaying for the remainder
65-
// of the original timeout_ms period.
63+
// Whenever it is resumed, as well asat mostevery intvl_ms millisconds and depending on
64+
//recurrent scheduled functions, it performsthe blocked callback, and if that returns true,
65+
//it keeps delaying for the remainderof the original timeout_ms period.
6666
template<typename T>
6767
inlinevoidesp_delay(constuint32_t timeout_ms, T&& blocked,constuint32_t intvl_ms) {
6868
constauto start_ms =millis();
@@ -79,5 +79,3 @@ inline void esp_delay(const uint32_t timeout_ms, T&& blocked) {
7979
}
8080

8181
#endif// __cplusplus
82-
83-
#endif// __COREDECLS_H

‎libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -451,9 +451,8 @@ bool ESP8266WiFiGenericClass::mode(WiFiMode_t m) {
451451
//tasks to wait correctly.
452452
constexprunsignedint timeoutValue =1000;//1 second
453453
if(can_yield()) {
454-
// The final argument, intvl_ms, to esp_delay influences how frequently
455-
// the scheduled recurrent functions (Schedule.h) are probed.
456-
esp_delay(timeoutValue, [m]() {returnwifi_get_opmode() != m; },5);
454+
// check opmode every 100ms or give up after timeout
455+
esp_delay(timeoutValue, [m]() {returnwifi_get_opmode() != m; },100);
457456

458457
//if at this point mode still hasn't been reached, give up
459458
if(wifi_get_opmode() != (uint8) m) {
@@ -642,11 +641,8 @@ static int hostByNameImpl(const char* aHostname, IPAddress& aResult, uint32_t ti
642641
// We need to wait for c/b to fire *or* we exit on our own timeout
643642
// (which also requires us to notify the c/b that it is supposed to delete the pending obj)
644643
case ERR_INPROGRESS:
645-
// Re-check every 10ms, we expect this to happen fast
646-
esp_delay(timeout_ms,
647-
[&]() {
648-
return !pending->done;
649-
},10);
644+
// sleep until dns_found_callback is called or timeout is reached
645+
esp_delay(timeout_ms, [&]() {return !pending->done; });
650646

651647
if (pending->done) {
652648
if ((pending->addr).isSet()) {

‎libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,13 @@ static void printWiFiStatus(wl_status_t status)
8484
staticwl_status_twaitWiFiConnect(uint32_t connectTimeoutMs)
8585
{
8686
wl_status_t status = WL_CONNECT_FAILED;
87-
//The final argument, intvl_ms,toesp_delay influences how frequently
88-
//the scheduled recurrent functions (Schedule.h) are probed.
87+
//Wait for WiFitoconnect
88+
//stop waiting upon status checked every 100ms or when timeout is reached
8989
esp_delay(connectTimeoutMs,
9090
[&status]() {
9191
status = WiFi.status();
9292
return status != WL_CONNECTED && status != WL_CONNECT_FAILED;
93-
},0);
93+
},100);
9494

9595
// Check status
9696
if (status == WL_CONNECTED) {
@@ -236,13 +236,12 @@ int8_t ESP8266WiFiMulti::startScan()
236236
WiFi.scanNetworks(true);
237237

238238
// Wait for WiFi scan change or timeout
239-
// The final argument, intvl_ms, to esp_delay influences how frequently
240-
// the scheduled recurrent functions (Schedule.h) are probed.
239+
// stop waiting upon status checked every 100ms or when timeout is reached
241240
esp_delay(WIFI_SCAN_TIMEOUT_MS,
242241
[&scanResult]() {
243242
scanResult = WiFi.scanComplete();
244243
return scanResult <0;
245-
},0);
244+
},100);
246245
// Check for scan timeout which may occur when scan does not report completion
247246
if (scanResult <0) {
248247
DEBUG_WIFI_MULTI("[WIFIM] Scan timeout\n");

‎libraries/ESP8266WiFi/src/include/ClientContext.h‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ class ClientContext
144144
_connect_pending =true;
145145
_op_start_time =millis();
146146
// will resume on timeout or when _connected or _notify_error fires
147-
// give scheduled functions a chance to run (e.g. Ethernet uses recurrent)
148-
esp_delay(_timeout_ms, [this]() {returnthis->_connect_pending; },1);
147+
esp_delay(_timeout_ms, [this]() {returnthis->_connect_pending; });
149148
_connect_pending =false;
150149
if (!_pcb) {
151150
DEBUGV(":cabrt\r\n");
@@ -485,8 +484,7 @@ class ClientContext
485484

486485
_send_waiting =true;
487486
// will resume on timeout or when _write_some_from_cb or _notify_error fires
488-
// give scheduled functions a chance to run (e.g. Ethernet uses recurrent)
489-
esp_delay(_timeout_ms, [this]() {returnthis->_send_waiting; },1);
487+
esp_delay(_timeout_ms, [this]() {returnthis->_send_waiting; });
490488
_send_waiting =false;
491489
}while(true);
492490

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp