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