- Notifications
You must be signed in to change notification settings - Fork13.3k
Renamings for thatesp_yield is really suspend, replacing delay(0), shimmable suspend-CONT API for async esp_suspend() / esp_schedule()#7148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
4df7186b64622d9bb489497d59ae08ed7d0397408f0bb470c971ad2899ed6fccd8d2d3070eb48d11be8b4b92d28208c4a33720ac03be70a467ced1262af940863c482679ecb16199eb97cfaeeaFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -135,8 +135,6 @@ bool schedule_recurrent_function_us(const std::function<bool(void)>& fn, | ||
| void run_scheduled_functions() | ||
| { | ||
| // prevent scheduling of new functions during this run | ||
| auto stop = sLast; | ||
| bool done = false; | ||
| @@ -161,13 +159,10 @@ void run_scheduled_functions() | ||
| recycle_fn_unsafe(to_recycle); | ||
| } | ||
| // 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); | ||
mcspr marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| } | ||
| } | ||
| @@ -241,9 +236,10 @@ void run_scheduled_recurrent_functions() | ||
| 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); | ||
| } | ||
| } while (current && !done); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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_ts_cycles_at_resume; | ||
| /* For ets_intr_lock_nest / ets_intr_unlock_nest | ||
| * Max nesting seen by SDK so far is 2. | ||
| @@ -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)); | ||
| @@ -106,32 +110,71 @@ extern "C" void __preloop_update_frequency() { | ||
| extern "C" void preloop_update_frequency() __attribute__((weak, alias("__preloop_update_frequency"))); | ||
| extern "C" bool can_yield() { | ||
| returncont_can_suspend(g_pcont); | ||
| } | ||
| static inline voidesp_suspend_within_cont() __attribute__((always_inline)); | ||
| static voidesp_suspend_within_cont() { | ||
| cont_suspend(g_pcont); | ||
| s_cycles_at_resume = ESP.getCycleCount(); | ||
| run_scheduled_recurrent_functions(); | ||
| } | ||
| extern "C" void__esp_suspend() { | ||
| if (cont_can_suspend(g_pcont)) { | ||
| esp_suspend_within_cont(); | ||
| } | ||
| } | ||
| extern "C" voidesp_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_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_yield() { | ||
| esp_schedule(); | ||
| 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"))); | ||
| 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; | ||
| } | ||
| esp_delay(std::min((timeout_ms - expired), intvl_ms)); | ||
| return false; | ||
| } | ||
| ||
| extern "C" void __yield() { | ||
| if (cont_can_suspend(g_pcont)) { | ||
| esp_schedule(); | ||
| esp_suspend_within_cont(); | ||
| } | ||
| else { | ||
| panic(); | ||
| @@ -140,14 +183,17 @@ 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) | ||
| clockCyclesPerMicrosecond(); | ||
| #else | ||
| ESP.getCpuFreqMHz(); | ||
| #endif | ||
| if ((ESP.getCycleCount() -s_cycles_at_resume) > intvl_cycles && | ||
| can_yield()) | ||
| { | ||
| yield(); | ||
| @@ -207,16 +253,16 @@ static void loop_wrapper() { | ||
| static void loop_task(os_event_t *events) { | ||
| (void) events; | ||
| s_cycles_at_resume = ESP.getCycleCount(); | ||
| ESP.resetHeap(); | ||
| cont_run(g_pcont, &loop_wrapper); | ||
| ESP.setDramHeap(); | ||
| if (cont_check(g_pcont) != 0) { | ||
| panic(); | ||
| } | ||
| } | ||
| extern "C" { | ||
| struct object { long placeholder[ 10 ]; }; | ||
| void __register_frame_info (const void *begin, struct object *ob); | ||
| extern char __eh_frame[]; | ||
| @@ -253,7 +299,6 @@ static void __unhandled_exception_cpp() | ||
| } | ||
| #endif | ||
| } | ||
| } | ||
| void init_done() { | ||
Uh oh!
There was an error while loading.Please reload this page.