1 // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // The LL layer for Timer Group register operations.
16 // Note that most of the register operations in this layer are non-atomic operations.
17
18 #pragma once
19
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23
24 #include <stdlib.h>
25 #include <stdbool.h>
26 #include "hal/wdt_types.h"
27 #include "soc/rtc_cntl_periph.h"
28 #include "soc/rtc_cntl_struct.h"
29 #include "esp_attr.h"
30
31 #if defined(__ZEPHYR__)
32 #include "stubs.h"
33 #endif
34
35 //Type check wdt_stage_action_t
36 _Static_assert(WDT_STAGE_ACTION_OFF == RTC_WDT_STG_SEL_OFF, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
37 _Static_assert(WDT_STAGE_ACTION_INT == RTC_WDT_STG_SEL_INT, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
38 _Static_assert(WDT_STAGE_ACTION_RESET_CPU == RTC_WDT_STG_SEL_RESET_CPU, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
39 _Static_assert(WDT_STAGE_ACTION_RESET_SYSTEM == RTC_WDT_STG_SEL_RESET_SYSTEM, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
40 _Static_assert(WDT_STAGE_ACTION_RESET_RTC == RTC_WDT_STG_SEL_RESET_RTC, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
41 //Type check wdt_reset_sig_length_t
42 _Static_assert(WDT_RESET_SIG_LENGTH_100ns == RTC_WDT_RESET_LENGTH_100_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
43 _Static_assert(WDT_RESET_SIG_LENGTH_200ns == RTC_WDT_RESET_LENGTH_200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
44 _Static_assert(WDT_RESET_SIG_LENGTH_300ns == RTC_WDT_RESET_LENGTH_300_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
45 _Static_assert(WDT_RESET_SIG_LENGTH_400ns == RTC_WDT_RESET_LENGTH_400_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
46 _Static_assert(WDT_RESET_SIG_LENGTH_500ns == RTC_WDT_RESET_LENGTH_500_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
47 _Static_assert(WDT_RESET_SIG_LENGTH_800ns == RTC_WDT_RESET_LENGTH_800_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
48 _Static_assert(WDT_RESET_SIG_LENGTH_1_6us == RTC_WDT_RESET_LENGTH_1600_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
49 _Static_assert(WDT_RESET_SIG_LENGTH_3_2us == RTC_WDT_RESET_LENGTH_3200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
50
51
52 /**
53 * @brief Enable the RWDT
54 *
55 * @param hw Start address of the peripheral registers.
56 */
rwdt_ll_enable(rtc_cntl_dev_t * hw)57 FORCE_INLINE_ATTR void rwdt_ll_enable(rtc_cntl_dev_t *hw)
58 {
59 hw->wdt_config0.en = 1;
60 }
61
62 /**
63 * @brief Disable the RWDT
64 *
65 * @param hw Start address of the peripheral registers.
66 * @note This function does not disable the flashboot mode. Therefore, given that
67 * the MWDT is disabled using this function, a timeout can still occur
68 * if the flashboot mode is simultaneously enabled.
69 */
rwdt_ll_disable(rtc_cntl_dev_t * hw)70 FORCE_INLINE_ATTR void rwdt_ll_disable(rtc_cntl_dev_t *hw)
71 {
72 hw->wdt_config0.en = 0;
73 }
74
75 /**
76 * @brief Check if the RWDT is enabled
77 *
78 * @param hw Start address of the peripheral registers.
79 * @return True if RTC WDT is enabled
80 */
rwdt_ll_check_if_enabled(rtc_cntl_dev_t * hw)81 FORCE_INLINE_ATTR bool rwdt_ll_check_if_enabled(rtc_cntl_dev_t *hw)
82 {
83 return (hw->wdt_config0.en) ? true : false;
84 }
85
86 /**
87 * @brief Configure a particular stage of the RWDT
88 *
89 * @param hw Start address of the peripheral registers.
90 * @param stage Which stage to configure
91 * @param timeout Number of timer ticks for the stage to timeout
92 * @param behavior What action to take when the stage times out
93 */
rwdt_ll_config_stage(rtc_cntl_dev_t * hw,wdt_stage_t stage,uint32_t timeout_ticks,wdt_stage_action_t behavior)94 FORCE_INLINE_ATTR void rwdt_ll_config_stage(rtc_cntl_dev_t *hw, wdt_stage_t stage, uint32_t timeout_ticks, wdt_stage_action_t behavior)
95 {
96 switch (stage) {
97 case WDT_STAGE0:
98 hw->wdt_config0.stg0 = behavior;
99 hw->wdt_config1 = timeout_ticks;
100 break;
101 case WDT_STAGE1:
102 hw->wdt_config0.stg1 = behavior;
103 hw->wdt_config2 = timeout_ticks;
104 break;
105 case WDT_STAGE2:
106 hw->wdt_config0.stg2 = behavior;
107 hw->wdt_config3 = timeout_ticks;
108 break;
109 case WDT_STAGE3:
110 hw->wdt_config0.stg3 = behavior;
111 hw->wdt_config4 = timeout_ticks;
112 break;
113 default:
114 abort();
115 }
116 }
117
118 /**
119 * @brief Disable a particular stage of the RWDT
120 *
121 * @param hw Start address of the peripheral registers.
122 * @param stage Which stage to disable
123 */
rwdt_ll_disable_stage(rtc_cntl_dev_t * hw,wdt_stage_t stage)124 FORCE_INLINE_ATTR void rwdt_ll_disable_stage(rtc_cntl_dev_t *hw, wdt_stage_t stage)
125 {
126 switch (stage) {
127 case WDT_STAGE0:
128 hw->wdt_config0.stg0 = WDT_STAGE_ACTION_OFF;
129 break;
130 case WDT_STAGE1:
131 hw->wdt_config0.stg1 = WDT_STAGE_ACTION_OFF;
132 break;
133 case WDT_STAGE2:
134 hw->wdt_config0.stg2 = WDT_STAGE_ACTION_OFF;
135 break;
136 case WDT_STAGE3:
137 hw->wdt_config0.stg3 = WDT_STAGE_ACTION_OFF;
138 break;
139 default:
140 abort();
141 }
142 }
143
144 /**
145 * @brief Enable or disable RWDT edge interrupt
146 *
147 * @param hw Start address of the peripheral registers.
148 * @param enable Whether to enable edge interrupt
149 */
rwdt_ll_set_edge_intr(rtc_cntl_dev_t * hw,bool enable)150 FORCE_INLINE_ATTR void rwdt_ll_set_edge_intr(rtc_cntl_dev_t *hw, bool enable)
151 {
152 hw->wdt_config0.edge_int_en = (enable) ? 1 : 0;
153 }
154
155 /**
156 * @brief Enable or disable RWDT level interrupt
157 *
158 * @param hw Start address of the peripheral registers.
159 * @param enable Whether to enable level interrupt
160 */
rwdt_ll_set_level_intr(rtc_cntl_dev_t * hw,bool enable)161 FORCE_INLINE_ATTR void rwdt_ll_set_level_intr(rtc_cntl_dev_t *hw, bool enable)
162 {
163 hw->wdt_config0.level_int_en = (enable) ? 1 : 0;
164 }
165
166 /**
167 * @brief Set the length of the CPU reset action
168 *
169 * @param hw Start address of the peripheral registers.
170 * @param length Length of CPU reset signal
171 */
rwdt_ll_set_cpu_reset_length(rtc_cntl_dev_t * hw,wdt_reset_sig_length_t length)172 FORCE_INLINE_ATTR void rwdt_ll_set_cpu_reset_length(rtc_cntl_dev_t *hw, wdt_reset_sig_length_t length)
173 {
174 hw->wdt_config0.cpu_reset_length = length;
175 }
176
177 /**
178 * @brief Set the length of the system reset action
179 *
180 * @param hw Start address of the peripheral registers.
181 * @param length Length of system reset signal
182 */
rwdt_ll_set_sys_reset_length(rtc_cntl_dev_t * hw,wdt_reset_sig_length_t length)183 FORCE_INLINE_ATTR void rwdt_ll_set_sys_reset_length(rtc_cntl_dev_t *hw, wdt_reset_sig_length_t length)
184 {
185 hw->wdt_config0.sys_reset_length = length;
186 }
187
188 /**
189 * @brief Enable/Disable the RWDT flashboot mode.
190 *
191 * @param hw Start address of the peripheral registers.
192 * @param enable True to enable RWDT flashboot mode, false to disable RWDT flashboot mode.
193 *
194 * @note Flashboot mode is independent and can trigger a WDT timeout event if the
195 * WDT's enable bit is set to 0. Flashboot mode for RWDT is automatically enabled
196 * on flashboot, and should be disabled by software when flashbooting completes.
197 */
rwdt_ll_set_flashboot_en(rtc_cntl_dev_t * hw,bool enable)198 FORCE_INLINE_ATTR void rwdt_ll_set_flashboot_en(rtc_cntl_dev_t* hw, bool enable)
199 {
200 hw->wdt_config0.flashboot_mod_en = (enable) ? 1 : 0;
201 }
202
203 /**
204 * @brief Enable/Disable the CPU0 to be reset on WDT_STAGE_ACTION_RESET_CPU
205 *
206 * @param hw Start address of the peripheral registers.
207 * @param enable True to enable CPU0 to be reset, false to disable.
208 */
rwdt_ll_set_procpu_reset_en(rtc_cntl_dev_t * hw,bool enable)209 FORCE_INLINE_ATTR void rwdt_ll_set_procpu_reset_en(rtc_cntl_dev_t* hw, bool enable)
210 {
211 hw->wdt_config0.procpu_reset_en = (enable) ? 1 : 0;
212 }
213
214 /**
215 * @brief Enable/Disable the CPU1 to be reset on WDT_STAGE_ACTION_RESET_CPU
216 *
217 * @param hw Start address of the peripheral registers.
218 * @param enable True to enable CPU1 to be reset, false to disable.
219 */
rwdt_ll_set_appcpu_reset_en(rtc_cntl_dev_t * hw,bool enable)220 FORCE_INLINE_ATTR void rwdt_ll_set_appcpu_reset_en(rtc_cntl_dev_t* hw, bool enable)
221 {
222 hw->wdt_config0.appcpu_reset_en = (enable) ? 1 : 0;
223 }
224
225 /**
226 * @brief Enable/Disable the RWDT pause during sleep functionality
227 *
228 * @param hw Start address of the peripheral registers.
229 * @param enable True to enable, false to disable.
230 */
rwdt_ll_set_pause_in_sleep_en(rtc_cntl_dev_t * hw,bool enable)231 FORCE_INLINE_ATTR void rwdt_ll_set_pause_in_sleep_en(rtc_cntl_dev_t* hw, bool enable)
232 {
233 hw->wdt_config0.pause_in_slp = (enable) ? 1 : 0;
234 }
235
236 /**
237 * @brief Feed the RWDT
238 *
239 * Resets the current timer count and current stage.
240 *
241 * @param hw Start address of the peripheral registers.
242 */
rwdt_ll_feed(rtc_cntl_dev_t * hw)243 FORCE_INLINE_ATTR void rwdt_ll_feed(rtc_cntl_dev_t *hw)
244 {
245 hw->wdt_feed.feed = 1;
246 }
247
248 /**
249 * @brief Enable write protection of the RWDT registers
250 *
251 * @param hw Start address of the peripheral registers.
252 */
rwdt_ll_write_protect_enable(rtc_cntl_dev_t * hw)253 FORCE_INLINE_ATTR void rwdt_ll_write_protect_enable(rtc_cntl_dev_t *hw)
254 {
255 hw->wdt_wprotect = 0;
256 }
257
258 /**
259 * @brief Disable write protection of the RWDT registers
260 *
261 * @param hw Start address of the peripheral registers.
262 */
rwdt_ll_write_protect_disable(rtc_cntl_dev_t * hw)263 FORCE_INLINE_ATTR void rwdt_ll_write_protect_disable(rtc_cntl_dev_t *hw)
264 {
265 hw->wdt_wprotect = RTC_CNTL_WDT_WKEY_VALUE;
266 }
267
268 /**
269 * @brief Enable the RWDT interrupt.
270 *
271 * @param hw Start address of the peripheral registers.
272 * @param enable True to enable RWDT interrupt, false to disable.
273 */
rwdt_ll_set_intr_enable(rtc_cntl_dev_t * hw,bool enable)274 FORCE_INLINE_ATTR void rwdt_ll_set_intr_enable(rtc_cntl_dev_t* hw, bool enable)
275 {
276 hw->int_ena.rtc_wdt = (enable) ? 1 : 0;
277 }
278
279 /**
280 * @brief Check if the RWDT interrupt has been triggered
281 *
282 * @param hw Start address of the peripheral registers.
283 * @return True if the RWDT interrupt was triggered
284 */
rwdt_ll_check_intr_status(rtc_cntl_dev_t * hw)285 FORCE_INLINE_ATTR bool rwdt_ll_check_intr_status(rtc_cntl_dev_t *hw)
286 {
287 return (hw->int_st.rtc_wdt) ? true : false;
288 }
289
290 /**
291 * @brief Clear the RWDT interrupt status.
292 *
293 * @param hw Start address of the peripheral registers.
294 */
rwdt_ll_clear_intr_status(rtc_cntl_dev_t * hw)295 FORCE_INLINE_ATTR void rwdt_ll_clear_intr_status(rtc_cntl_dev_t* hw)
296 {
297 hw->int_clr.rtc_wdt = 1;
298 }
299
300 #ifdef __cplusplus
301 }
302 #endif
303