update watchdog implementation for espressif

This commit is contained in:
MicroDev 2023-03-15 13:18:13 +05:30
parent 5e0dce286e
commit 0acf2e8c9b
No known key found for this signature in database
GPG Key ID: 2C0867BE60967730
1 changed files with 42 additions and 14 deletions

View File

@ -33,9 +33,18 @@
#include "esp_task_wdt.h" #include "esp_task_wdt.h"
extern void esp_task_wdt_isr_user_handler(void); extern void esp_task_wdt_isr_user_handler(void);
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_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&mp_watchdog_timeout_exception));
MP_STATE_THREAD(mp_pending_exception) = &mp_watchdog_timeout_exception; MP_STATE_THREAD(mp_pending_exception) = &mp_watchdog_timeout_exception;
#if MICROPY_ENABLE_SCHEDULER #if MICROPY_ENABLE_SCHEDULER
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) { if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
MP_STATE_VM(sched_state) = MP_SCHED_PENDING; 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) { void common_hal_watchdog_feed(watchdog_watchdogtimer_obj_t *self) {
if (esp_task_wdt_reset() != ESP_OK) { esp_task_wdt_reset();
mp_raise_RuntimeError(translate("watchdog not initialized"));
}
} }
void common_hal_watchdog_deinit(watchdog_watchdogtimer_obj_t *self) { 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) { if (esp_task_wdt_delete(NULL) == ESP_OK && esp_task_wdt_deinit() == ESP_OK) {
self->mode = WATCHDOGMODE_NONE; self->mode = WATCHDOGMODE_NONE;
} }
@ -59,11 +69,11 @@ void watchdog_reset(void) {
common_hal_watchdog_deinit(&common_hal_mcu_watchdogtimer_obj); 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 // enable panic hanler in WATCHDOGMODE_RESET mode
// initialize Task Watchdog Timer (TWDT) // initialize Task Watchdog Timer (TWDT)
if (esp_task_wdt_init((uint32_t)self->timeout, (self->mode == WATCHDOGMODE_RESET)) != ESP_OK) { if (esp_task_wdt_init(timeout, mode == WATCHDOGMODE_RESET) != ESP_OK) {
mp_raise_RuntimeError(translate("Initialization failed due to lack of memory")); mp_raise_msg(&mp_type_MemoryError, NULL);
} }
esp_task_wdt_add(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) { void common_hal_watchdog_set_timeout(watchdog_watchdogtimer_obj_t *self, mp_float_t new_timeout) {
if ((uint64_t)new_timeout > UINT32_MAX) { if (!(self->timeout < new_timeout || self->timeout > new_timeout)) {
mp_raise_ValueError(translate("timeout duration exceeded the maximum supported value")); return;
} }
if ((uint32_t)self->timeout != (uint32_t)new_timeout) {
self->timeout = new_timeout; if ((uint64_t)new_timeout > UINT32_MAX) {
wdt_config(self); 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) { void common_hal_watchdog_set_mode(watchdog_watchdogtimer_obj_t *self, watchdog_watchdogmode_t new_mode) {
if (self->mode != new_mode) { if (self->mode == new_mode) {
self->mode = new_mode; return;
wdt_config(self);
} }
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;
} }