1 /*
2 * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "esp_xt_wdt.h"
8 #include "sdkconfig.h"
9 #include "soc/soc_caps.h"
10
11 #include "esp_log.h"
12 #include "esp_check.h"
13 #include "esp_attr.h"
14 #include "esp_intr_alloc.h"
15 #include "freertos/FreeRTOS.h"
16 #include "freertos/semphr.h"
17
18 #if SOC_XT_WDT_SUPPORTED
19
20 #include "driver/rtc_cntl.h"
21 #include "hal/xt_wdt_hal.h"
22 #include "hal/xt_wdt_ll.h"
23 #include "soc/rtc.h"
24
25 #define RTC_CLK_CAL_CYCLES 500
26
27 const static char *TAG = "esp_xt_wdt";
28
29 static xt_wdt_hal_context_t s_hal_ctx;
30
31 static esp_xt_callback_t s_callback_func;
32 static void *s_callback_arg;
33
34 portMUX_TYPE s_xt_wdt_lock = portMUX_INITIALIZER_UNLOCKED;
35
rtc_xt_wdt_default_isr_handler(void * arg)36 static IRAM_ATTR void rtc_xt_wdt_default_isr_handler(void *arg)
37 {
38 ESP_EARLY_LOGE(TAG, "XTAL32K watchdog timer got triggered");
39
40 portENTER_CRITICAL_ISR(&s_xt_wdt_lock);
41 if (s_callback_func) {
42 (*s_callback_func)(s_callback_arg);
43 }
44 portEXIT_CRITICAL_ISR(&s_xt_wdt_lock);
45 }
46
esp_xt_wdt_init(const esp_xt_wdt_config_t * cfg)47 esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg)
48 {
49 esp_err_t ret = ESP_OK;
50
51 xt_wdt_hal_config_t hal_config = {
52 .timeout = cfg->timeout,
53 };
54
55 xt_wdt_hal_init(&s_hal_ctx, &hal_config);
56
57 if (cfg->auto_backup_clk_enable) {
58 /* Estimate frequency of internal RTC oscillator */
59 uint32_t rtc_clk_frequency_khz = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_INTERNAL_OSC, RTC_CLK_CAL_CYCLES)) / 1000;
60 ESP_LOGD(TAG, "Calibrating backup clock from rtc clock with frequency %d", rtc_clk_frequency_khz);
61
62 xt_wdt_hal_enable_backup_clk(&s_hal_ctx, rtc_clk_frequency_khz);
63 }
64
65 ESP_GOTO_ON_ERROR(rtc_isr_register(rtc_xt_wdt_default_isr_handler, NULL, XT_WDT_LL_XTAL32_DEAD_INTR_MASK), err, TAG, "Failed to register isr");
66
67 xt_wdt_hal_enable(&s_hal_ctx, 1);
68
69 return ESP_OK;
70 err:
71 return ret;
72 }
73
esp_xt_wdt_restore_clk(void)74 void esp_xt_wdt_restore_clk(void)
75 {
76 xt_wdt_hal_enable(&s_hal_ctx, false);
77
78 REG_CLR_BIT(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
79 REG_SET_BIT(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
80
81 /* Needs some time after switching to 32khz XTAL before turning on WDT again */
82 esp_rom_delay_us(300);
83
84 xt_wdt_hal_enable(&s_hal_ctx, true);
85 }
86
esp_xt_wdt_register_callback(esp_xt_callback_t func,void * arg)87 void esp_xt_wdt_register_callback(esp_xt_callback_t func, void *arg)
88 {
89 portENTER_CRITICAL(&s_xt_wdt_lock);
90 s_callback_func = func;
91 s_callback_arg = arg;
92 portEXIT_CRITICAL(&s_xt_wdt_lock);
93 }
94
95 #endif //SOC_XT_WDT_SUPPORTED
96