1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <stdbool.h>
9 #include "hal/wdt_types.h"
10 #include "hal/wdt_hal.h"
11 
12 /* ---------------------------- Init and Config ----------------------------- */
13 
wdt_hal_init(wdt_hal_context_t * hal,wdt_inst_t wdt_inst,uint32_t prescaler,bool enable_intr)14 void wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t prescaler, bool enable_intr)
15 {
16     //Initialize HAL context
17     memset(hal, 0, sizeof(wdt_hal_context_t));
18     if (wdt_inst == WDT_MWDT0) {
19         hal->mwdt_dev = &TIMERG0;
20     }
21 #if SOC_TIMER_GROUPS >= 2
22     else if (wdt_inst == WDT_MWDT1) {
23         hal->mwdt_dev = &TIMERG1;
24     }
25 #endif
26     else {
27         hal->rwdt_dev = RWDT_DEV_GET();
28     }
29     hal->inst = wdt_inst;
30 
31     if (hal->inst == WDT_RWDT) {
32         //Unlock RTC WDT
33         rwdt_ll_write_protect_disable(hal->rwdt_dev);
34         //Disable RTC WDT, all stages, and all interrupts.
35         rwdt_ll_disable(hal->rwdt_dev);
36         rwdt_ll_disable_stage(hal->rwdt_dev, WDT_STAGE0);
37         rwdt_ll_disable_stage(hal->rwdt_dev, WDT_STAGE1);
38         rwdt_ll_disable_stage(hal->rwdt_dev, WDT_STAGE2);
39         rwdt_ll_disable_stage(hal->rwdt_dev, WDT_STAGE3);
40 #ifdef CONFIG_IDF_TARGET_ESP32
41         //Enable or disable level interrupt. Edge interrupt is always disabled.
42         rwdt_ll_set_edge_intr(hal->rwdt_dev, false);
43         rwdt_ll_set_level_intr(hal->rwdt_dev, enable_intr);
44 #else
45         //Enable or disable chip reset on timeout, and length of chip reset signal
46         rwdt_ll_set_chip_reset_width(hal->rwdt_dev, 0);
47         rwdt_ll_set_chip_reset_en(hal->rwdt_dev, false);
48 #endif
49         rwdt_ll_clear_intr_status(hal->rwdt_dev);
50         rwdt_ll_set_intr_enable(hal->rwdt_dev, enable_intr);
51         //Set default values
52 #if SOC_CPU_CORES_NUM > 1
53         rwdt_ll_set_appcpu_reset_en(hal->rwdt_dev, true);
54 #endif
55         rwdt_ll_set_procpu_reset_en(hal->rwdt_dev, true);
56         rwdt_ll_set_pause_in_sleep_en(hal->rwdt_dev, true);
57         rwdt_ll_set_cpu_reset_length(hal->rwdt_dev, WDT_RESET_SIG_LENGTH_3_2us);
58         rwdt_ll_set_sys_reset_length(hal->rwdt_dev, WDT_RESET_SIG_LENGTH_3_2us);
59         //Lock RTC WDT
60         rwdt_ll_write_protect_enable(hal->rwdt_dev);
61     } else {
62         //Unlock WDT
63         mwdt_ll_write_protect_disable(hal->mwdt_dev);
64         //Disable WDT and stages.
65         mwdt_ll_disable(hal->mwdt_dev);
66         mwdt_ll_disable_stage(hal->mwdt_dev, 0);
67         mwdt_ll_disable_stage(hal->mwdt_dev, 1);
68         mwdt_ll_disable_stage(hal->mwdt_dev, 2);
69         mwdt_ll_disable_stage(hal->mwdt_dev, 3);
70 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
71         //Enable or disable level interrupt. Edge interrupt is always disabled.
72         mwdt_ll_set_edge_intr(hal->mwdt_dev, false);
73         mwdt_ll_set_level_intr(hal->mwdt_dev, enable_intr);
74 #endif
75         mwdt_ll_clear_intr_status(hal->mwdt_dev);
76         mwdt_ll_set_intr_enable(hal->mwdt_dev, enable_intr);
77         //Set default values
78         mwdt_ll_set_cpu_reset_length(hal->mwdt_dev, WDT_RESET_SIG_LENGTH_3_2us);
79         mwdt_ll_set_sys_reset_length(hal->mwdt_dev, WDT_RESET_SIG_LENGTH_3_2us);
80         mwdt_ll_set_clock_source(hal->mwdt_dev, MWDT_CLK_SRC_DEFAULT);
81         mwdt_ll_enable_clock(hal->mwdt_dev, true);
82         //Set tick period
83         mwdt_ll_set_prescaler(hal->mwdt_dev, prescaler);
84         //Lock WDT
85         mwdt_ll_write_protect_enable(hal->mwdt_dev);
86     }
87 }
88 
wdt_hal_deinit(wdt_hal_context_t * hal)89 void wdt_hal_deinit(wdt_hal_context_t *hal)
90 {
91     if (hal->inst == WDT_RWDT) {
92         //Unlock WDT
93         rwdt_ll_write_protect_disable(hal->rwdt_dev);
94         //Disable WDT and clear any interrupts
95         rwdt_ll_feed(hal->rwdt_dev);
96         rwdt_ll_disable(hal->rwdt_dev);
97         rwdt_ll_clear_intr_status(hal->rwdt_dev);
98         rwdt_ll_set_intr_enable(hal->rwdt_dev, false);
99         //Lock WDT
100         rwdt_ll_write_protect_enable(hal->rwdt_dev);
101     } else {
102         //Unlock WDT
103         mwdt_ll_write_protect_disable(hal->mwdt_dev);
104         //Disable WDT and clear/disable any interrupts
105         mwdt_ll_feed(hal->mwdt_dev);
106         mwdt_ll_disable(hal->mwdt_dev);
107         mwdt_ll_clear_intr_status(hal->mwdt_dev);
108         mwdt_ll_set_intr_enable(hal->mwdt_dev, false);
109         mwdt_ll_enable_clock(hal->mwdt_dev, false);
110         //Lock WDT
111         mwdt_ll_write_protect_enable(hal->mwdt_dev);
112     }
113     //Deinit HAL context
114     hal->mwdt_dev = NULL;
115 }
116 
wdt_hal_config_stage(wdt_hal_context_t * hal,wdt_stage_t stage,uint32_t timeout_ticks,wdt_stage_action_t behavior)117 void wdt_hal_config_stage(wdt_hal_context_t *hal, wdt_stage_t stage, uint32_t timeout_ticks, wdt_stage_action_t behavior)
118 {
119     if (hal->inst == WDT_RWDT) {
120         rwdt_ll_config_stage(hal->rwdt_dev, stage, timeout_ticks, behavior);
121     } else {
122         mwdt_ll_config_stage(hal->mwdt_dev, stage, timeout_ticks, behavior);
123     }
124 }
125 
126 /* -------------------------------- Runtime --------------------------------- */
127 
wdt_hal_write_protect_disable(wdt_hal_context_t * hal)128 void wdt_hal_write_protect_disable(wdt_hal_context_t *hal)
129 {
130     if (hal->inst == WDT_RWDT) {
131         rwdt_ll_write_protect_disable(hal->rwdt_dev);
132     } else {
133         mwdt_ll_write_protect_disable(hal->mwdt_dev);
134     }
135 }
136 
wdt_hal_write_protect_enable(wdt_hal_context_t * hal)137 void wdt_hal_write_protect_enable(wdt_hal_context_t *hal)
138 {
139     if (hal->inst == WDT_RWDT) {
140         rwdt_ll_write_protect_enable(hal->rwdt_dev);
141     } else {
142         mwdt_ll_write_protect_enable(hal->mwdt_dev);
143     }
144 }
145 
wdt_hal_enable(wdt_hal_context_t * hal)146 void wdt_hal_enable(wdt_hal_context_t *hal)
147 {
148     if (hal->inst == WDT_RWDT) {
149         rwdt_ll_feed(hal->rwdt_dev);
150         rwdt_ll_enable(hal->rwdt_dev);
151     } else {
152         mwdt_ll_feed(hal->mwdt_dev);
153         mwdt_ll_enable(hal->mwdt_dev);
154     }
155 }
156 
wdt_hal_disable(wdt_hal_context_t * hal)157 void wdt_hal_disable(wdt_hal_context_t *hal)
158 {
159     if (hal->inst == WDT_RWDT) {
160         rwdt_ll_disable(hal->rwdt_dev);
161     } else {
162         mwdt_ll_disable(hal->mwdt_dev);
163     }
164 }
165 
wdt_hal_handle_intr(wdt_hal_context_t * hal)166 void wdt_hal_handle_intr(wdt_hal_context_t *hal)
167 {
168     if (hal->inst == WDT_RWDT) {
169         rwdt_ll_feed(hal->rwdt_dev);
170         rwdt_ll_clear_intr_status(hal->rwdt_dev);
171     } else {
172         mwdt_ll_feed(hal->mwdt_dev);
173         mwdt_ll_clear_intr_status(hal->mwdt_dev);
174     }
175 }
176 
wdt_hal_feed(wdt_hal_context_t * hal)177 void wdt_hal_feed(wdt_hal_context_t *hal)
178 {
179     if (hal->inst == WDT_RWDT) {
180         rwdt_ll_feed(hal->rwdt_dev);
181     } else {
182         mwdt_ll_feed(hal->mwdt_dev);
183     }
184 }
185 
wdt_hal_set_flashboot_en(wdt_hal_context_t * hal,bool enable)186 void wdt_hal_set_flashboot_en(wdt_hal_context_t *hal, bool enable)
187 {
188     if (hal->inst == WDT_RWDT) {
189         rwdt_ll_set_flashboot_en(hal->rwdt_dev, enable);
190     } else {
191         mwdt_ll_set_flashboot_en(hal->mwdt_dev, enable);
192     }
193 }
194 
wdt_hal_is_enabled(wdt_hal_context_t * hal)195 bool wdt_hal_is_enabled(wdt_hal_context_t *hal)
196 {
197     if (hal->inst == WDT_RWDT) {
198         return rwdt_ll_check_if_enabled(hal->rwdt_dev);
199     } else {
200         return mwdt_ll_check_if_enabled(hal->mwdt_dev);
201     }
202 }
203