| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- /*
- * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- #include <stdint.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include "sdkconfig.h"
- #include "hal/wdt_hal.h"
- #include "esp_err.h"
- #include "esp_attr.h"
- #include "esp_check.h"
- #include "esp_log.h"
- #include "esp_debug_helpers.h"
- #include "esp_timer.h"
- #include "esp_private/esp_task_wdt_impl.h"
- /**
- * Context for the software implementation of the Task WatchDog Timer.
- * This will be passed as a parameter to public functions below. */
- typedef struct {
- esp_timer_handle_t sw_timer;
- uint32_t period_ms;
- } twdt_ctx_soft_t;
- /**
- * Declare the initial context as static. It will be passed to the
- * task_wdt implementation as the implementation context in the
- * init function. */
- static twdt_ctx_soft_t init_context;
- static const char *TAG = "task_wdt_impl_soft";
- esp_err_t esp_task_wdt_impl_timer_allocate(const esp_task_wdt_config_t *config,
- twdt_isr_callback callback,
- twdt_ctx_t *obj)
- {
- twdt_ctx_soft_t *ctx = &init_context;
- const esp_timer_create_args_t timer_args = {
- .callback = callback,
- .arg = NULL,
- .dispatch_method = ESP_TIMER_ISR,
- .name = "Task software watchdog",
- .skip_unhandled_events = true
- };
- /* Software Task timer. As we don't have a spare hardware watchdog timer, we will use esp_timer to simulate one */
- esp_err_t ret = esp_timer_create(&timer_args, &ctx->sw_timer);
- ESP_GOTO_ON_FALSE((ret == ESP_OK), ret, reterr, TAG, "could not start periodic timer");
- /* Configure it as a periodic timer, so that we check the Tasks everytime it is triggered.
- * No need to start the timer here, it will be started later with `esp_task_wdt_impl_timer_restart` */
- ctx->period_ms = config->timeout_ms;
- /* Return our context to the caller */
- *obj = (twdt_ctx_t) ctx;
- reterr:
- return ret;
- }
- esp_err_t esp_task_wdt_impl_timer_reconfigure(twdt_ctx_t obj, const esp_task_wdt_config_t *config)
- {
- esp_err_t ret = ESP_OK;
- twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
- if (config == NULL || ctx == NULL) {
- ret = ESP_ERR_INVALID_STATE;
- }
- if (ret == ESP_OK) {
- /* The timer is stopped, we only need to update the period in our context, next time we start the
- * timer with `esp_task_wdt_impl_timer_restart`, we will pass the context's period to the
- * underlying esp_timer instance. */
- ctx->period_ms = config->timeout_ms;
- }
- return ret;
- }
- void esp_task_wdt_impl_timer_free(twdt_ctx_t obj)
- {
- const twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
- if (ctx != NULL && ctx->sw_timer != NULL) {
- ESP_ERROR_CHECK(esp_timer_delete(ctx->sw_timer));
- }
- }
- esp_err_t esp_task_wdt_impl_timer_feed(twdt_ctx_t obj)
- {
- esp_err_t ret = ESP_OK;
- const twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
- if (ctx == NULL) {
- ret = ESP_ERR_INVALID_STATE;
- }
- if (ret == ESP_OK) {
- /* Feed the periodic timer by restarting it, specifying the same period */
- ret = esp_timer_restart(ctx->sw_timer, ctx->period_ms * 1000);
- }
- return ret;
- }
- void esp_task_wdt_impl_timeout_triggered(twdt_ctx_t obj)
- {
- (void) obj;
- }
- esp_err_t esp_task_wdt_impl_timer_stop(twdt_ctx_t obj)
- {
- esp_err_t ret = ESP_OK;
- const twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
- if (ctx == NULL || ctx->sw_timer == NULL) {
- ret = ESP_ERR_INVALID_STATE;
- }
- if (ret == ESP_OK) {
- ret = esp_timer_stop(ctx->sw_timer);
- }
- return ret;
- }
- esp_err_t esp_task_wdt_impl_timer_restart(twdt_ctx_t obj)
- {
- esp_err_t ret = ESP_OK;
- twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
- if (ctx == NULL || ctx->sw_timer == NULL) {
- ret = ESP_ERR_INVALID_STATE;
- }
- if (ret == ESP_OK) {
- esp_timer_start_periodic(ctx->sw_timer, ctx->period_ms * 1000);
- }
- return ret;
- }
|