From bccf9d3dcfd000b81b89b9ef862f9bc6104df99d Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 3 Jul 2018 15:31:10 +1000 Subject: [PATCH] esp8266: Let machine.WDT trigger the software WDT if obj is not fed. This patch allows scripts to have more control over the software WDT. If an instance of machine.WDT is created then the underlying OS is prevented from feeding the software WDT, and it is up to the user script to feed it instead via WDT.feed(). The timeout for this WDT is currently fixed and will be between 1.6 and 3.2 seconds. --- ports/esp8266/ets_alt_task.c | 16 +++++++++++++++- ports/esp8266/ets_alt_task.h | 1 + ports/esp8266/machine_wdt.c | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ports/esp8266/ets_alt_task.c b/ports/esp8266/ets_alt_task.c index ff7dba1869..6f9ae67f21 100644 --- a/ports/esp8266/ets_alt_task.c +++ b/ports/esp8266/ets_alt_task.c @@ -109,6 +109,7 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) { } int ets_loop_iter_disable = 0; +int ets_loop_dont_feed_sw_wdt = 0; // to implement a 64-bit wide microsecond counter static uint32_t system_time_prev = 0; @@ -128,10 +129,18 @@ bool ets_loop_iter(void) { system_time_prev = system_time_cur; ets_intr_unlock(); + // 6 words before pend_flag_noise_check is a variable that is used by + // the software WDT. A 1.6 second period timer will increment this + // variable and if it gets to 2 then the SW WDT will trigger a reset. + extern uint32_t pend_flag_noise_check; + uint32_t *sw_wdt = &pend_flag_noise_check - 6; + //static unsigned cnt; bool progress = false; for (volatile struct task_entry *t = emu_tasks; t < &emu_tasks[MP_ARRAY_SIZE(emu_tasks)]; t++) { - system_soft_wdt_feed(); + if (!ets_loop_dont_feed_sw_wdt) { + system_soft_wdt_feed(); + } ets_intr_lock(); //printf("etc_loop_iter: "); dump_task(t - emu_tasks + FIRST_PRIO, t); if (t->i_get != t->i_put) { @@ -146,7 +155,12 @@ bool ets_loop_iter(void) { t->i_get = 0; } //ets_intr_unlock(); + uint32_t old_sw_wdt = *sw_wdt; t->task(&t->queue[idx]); + if (ets_loop_dont_feed_sw_wdt) { + // Restore previous SW WDT counter, in case task fed/cleared it + *sw_wdt = old_sw_wdt; + } //ets_intr_lock(); //printf("Done calling task %d\n", t - emu_tasks + FIRST_PRIO); } diff --git a/ports/esp8266/ets_alt_task.h b/ports/esp8266/ets_alt_task.h index 33a9d3a002..e7a15c3ad5 100644 --- a/ports/esp8266/ets_alt_task.h +++ b/ports/esp8266/ets_alt_task.h @@ -2,6 +2,7 @@ #define MICROPY_INCLUDED_ESP8266_ETS_ALT_TASK_H extern int ets_loop_iter_disable; +extern int ets_loop_dont_feed_sw_wdt; extern uint32_t system_time_high_word; bool ets_loop_iter(void); diff --git a/ports/esp8266/machine_wdt.c b/ports/esp8266/machine_wdt.c index 4432297fa8..fad0b2e4de 100644 --- a/ports/esp8266/machine_wdt.c +++ b/ports/esp8266/machine_wdt.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "user_interface.h" #include "etshal.h" +#include "ets_alt_task.h" const mp_obj_type_t esp_wdt_type; @@ -49,6 +50,8 @@ STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args switch (id) { case 0: + ets_loop_dont_feed_sw_wdt = 1; + system_soft_wdt_feed(); return &wdt_default; default: mp_raise_ValueError(NULL);