diff --git a/ports/espressif/common-hal/watchdog/WatchDogTimer.c b/ports/espressif/common-hal/watchdog/WatchDogTimer.c index 159c99458f..6a7c91622e 100644 --- a/ports/espressif/common-hal/watchdog/WatchDogTimer.c +++ b/ports/espressif/common-hal/watchdog/WatchDogTimer.c @@ -33,9 +33,18 @@ #include "esp_task_wdt.h" extern void esp_task_wdt_isr_user_handler(void); + void esp_task_wdt_isr_user_handler(void) { + // just delete, deiniting TWDT in isr context causes a crash + if (esp_task_wdt_delete(NULL) == ESP_OK) { + watchdog_watchdogtimer_obj_t *self = &common_hal_mcu_watchdogtimer_obj; + self->mode = WATCHDOGMODE_NONE; + } + + // schedule watchdog timeout exception mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&mp_watchdog_timeout_exception)); MP_STATE_THREAD(mp_pending_exception) = &mp_watchdog_timeout_exception; + #if MICROPY_ENABLE_SCHEDULER if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { MP_STATE_VM(sched_state) = MP_SCHED_PENDING; @@ -44,12 +53,13 @@ void esp_task_wdt_isr_user_handler(void) { } void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self) { - if (esp_task_wdt_reset() != ESP_OK) { - mp_raise_RuntimeError(translate("watchdog not initialized")); - } + esp_task_wdt_reset(); } void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self) { + if (self->mode == WATCHDOGMODE_NONE) { + return; + } if (esp_task_wdt_delete(NULL) == ESP_OK && esp_task_wdt_deinit() == ESP_OK) { self->mode = WATCHDOGMODE_NONE; } @@ -59,11 +69,11 @@ void watchdog_reset(void) { common_hal_watchdog_deinit(&common_hal_mcu_watchdogtimer_obj); } -static void wdt_config(watchdog_watchdogtimer_obj_t *self) { +static void wdt_config(uint32_t timeout, watchdog_watchdogmode_t mode) { // enable panic hanler in WATCHDOGMODE_RESET mode // initialize Task Watchdog Timer (TWDT) - if (esp_task_wdt_init((uint32_t)self->timeout, (self->mode == WATCHDOGMODE_RESET)) != ESP_OK) { - mp_raise_RuntimeError(translate("Initialization failed due to lack of memory")); + if (esp_task_wdt_init(timeout, mode == WATCHDOGMODE_RESET) != ESP_OK) { + mp_raise_msg(&mp_type_MemoryError, NULL); } esp_task_wdt_add(NULL); } @@ -73,12 +83,17 @@ mp_float_t common_hal_watchdog_get_timeout(watchdog_watchdogtimer_obj_t *self) { } void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self, mp_float_t new_timeout) { - if ((uint64_t)new_timeout > UINT32_MAX) { - mp_raise_ValueError(translate("timeout duration exceeded the maximum supported value")); + if (!(self->timeout < new_timeout || self->timeout > new_timeout)) { + return; } - if ((uint32_t)self->timeout != (uint32_t)new_timeout) { - self->timeout = new_timeout; - wdt_config(self); + + if ((uint64_t)new_timeout > UINT32_MAX) { + mp_raise_ValueError_varg(translate("%q must be <= %d"), MP_QSTR_timeout, UINT32_MAX); + } + self->timeout = new_timeout; + + if (self->mode != WATCHDOGMODE_NONE) { + wdt_config(new_timeout, self->mode); } } @@ -87,8 +102,21 @@ watchdog_watchdogmode_t common_hal_watchdog_get_mode(watchdog_watchdogtimer_obj_ } void common_hal_watchdog_set_mode(watchdog_watchdogtimer_obj_t *self, watchdog_watchdogmode_t new_mode) { - if (self->mode != new_mode) { - self->mode = new_mode; - wdt_config(self); + if (self->mode == new_mode) { + return; } + + switch (new_mode) { + case WATCHDOGMODE_NONE: + common_hal_watchdog_deinit(self); + break; + case WATCHDOGMODE_RAISE: + case WATCHDOGMODE_RESET: + wdt_config(self->timeout, new_mode); + break; + default: + return; + } + + self->mode = new_mode; }