task_wdt_impl_esp_timer.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdint.h>
  7. #include <stdbool.h>
  8. #include <stdio.h>
  9. #include "sdkconfig.h"
  10. #include "hal/wdt_hal.h"
  11. #include "esp_err.h"
  12. #include "esp_attr.h"
  13. #include "esp_check.h"
  14. #include "esp_log.h"
  15. #include "esp_debug_helpers.h"
  16. #include "esp_timer.h"
  17. #include "esp_private/esp_task_wdt_impl.h"
  18. /**
  19. * Context for the software implementation of the Task WatchDog Timer.
  20. * This will be passed as a parameter to public functions below. */
  21. typedef struct {
  22. esp_timer_handle_t sw_timer;
  23. uint32_t period_ms;
  24. } twdt_ctx_soft_t;
  25. /**
  26. * Declare the initial context as static. It will be passed to the
  27. * task_wdt implementation as the implementation context in the
  28. * init function. */
  29. static twdt_ctx_soft_t init_context;
  30. static const char *TAG = "task_wdt_impl_soft";
  31. esp_err_t esp_task_wdt_impl_timer_allocate(const esp_task_wdt_config_t *config,
  32. twdt_isr_callback callback,
  33. twdt_ctx_t *obj)
  34. {
  35. twdt_ctx_soft_t *ctx = &init_context;
  36. const esp_timer_create_args_t timer_args = {
  37. .callback = callback,
  38. .arg = NULL,
  39. .dispatch_method = ESP_TIMER_ISR,
  40. .name = "Task software watchdog",
  41. .skip_unhandled_events = true
  42. };
  43. /* Software Task timer. As we don't have a spare hardware watchdog timer, we will use esp_timer to simulate one */
  44. esp_err_t ret = esp_timer_create(&timer_args, &ctx->sw_timer);
  45. ESP_GOTO_ON_FALSE((ret == ESP_OK), ret, reterr, TAG, "could not start periodic timer");
  46. /* Configure it as a periodic timer, so that we check the Tasks everytime it is triggered.
  47. * No need to start the timer here, it will be started later with `esp_task_wdt_impl_timer_restart` */
  48. ctx->period_ms = config->timeout_ms;
  49. /* Return our context to the caller */
  50. *obj = (twdt_ctx_t) ctx;
  51. reterr:
  52. return ret;
  53. }
  54. esp_err_t esp_task_wdt_impl_timer_reconfigure(twdt_ctx_t obj, const esp_task_wdt_config_t *config)
  55. {
  56. esp_err_t ret = ESP_OK;
  57. twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
  58. if (config == NULL || ctx == NULL) {
  59. ret = ESP_ERR_INVALID_STATE;
  60. }
  61. if (ret == ESP_OK) {
  62. /* The timer is stopped, we only need to update the period in our context, next time we start the
  63. * timer with `esp_task_wdt_impl_timer_restart`, we will pass the context's period to the
  64. * underlying esp_timer instance. */
  65. ctx->period_ms = config->timeout_ms;
  66. }
  67. return ret;
  68. }
  69. void esp_task_wdt_impl_timer_free(twdt_ctx_t obj)
  70. {
  71. const twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
  72. if (ctx != NULL && ctx->sw_timer != NULL) {
  73. ESP_ERROR_CHECK(esp_timer_delete(ctx->sw_timer));
  74. }
  75. }
  76. esp_err_t esp_task_wdt_impl_timer_feed(twdt_ctx_t obj)
  77. {
  78. esp_err_t ret = ESP_OK;
  79. const twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
  80. if (ctx == NULL) {
  81. ret = ESP_ERR_INVALID_STATE;
  82. }
  83. if (ret == ESP_OK) {
  84. /* Feed the periodic timer by restarting it, specifying the same period */
  85. ret = esp_timer_restart(ctx->sw_timer, ctx->period_ms * 1000);
  86. }
  87. return ret;
  88. }
  89. void esp_task_wdt_impl_timeout_triggered(twdt_ctx_t obj)
  90. {
  91. (void) obj;
  92. }
  93. esp_err_t esp_task_wdt_impl_timer_stop(twdt_ctx_t obj)
  94. {
  95. esp_err_t ret = ESP_OK;
  96. const twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
  97. if (ctx == NULL || ctx->sw_timer == NULL) {
  98. ret = ESP_ERR_INVALID_STATE;
  99. }
  100. if (ret == ESP_OK) {
  101. ret = esp_timer_stop(ctx->sw_timer);
  102. }
  103. return ret;
  104. }
  105. esp_err_t esp_task_wdt_impl_timer_restart(twdt_ctx_t obj)
  106. {
  107. esp_err_t ret = ESP_OK;
  108. twdt_ctx_soft_t* ctx = (twdt_ctx_soft_t*) obj;
  109. if (ctx == NULL || ctx->sw_timer == NULL) {
  110. ret = ESP_ERR_INVALID_STATE;
  111. }
  112. if (ret == ESP_OK) {
  113. esp_timer_start_periodic(ctx->sw_timer, ctx->period_ms * 1000);
  114. }
  115. return ret;
  116. }