1 /*
2 * Copyright (c) 2023-2024 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_EWDG_DRV_H
9 #define HPM_EWDG_DRV_H
10
11 #include "hpm_common.h"
12 #include "hpm_ewdg_regs.h"
13 #include "hpm_soc_feature.h"
14
15 /**
16 * @brief EWDG driver APIs
17 * @defgroup ewdg_interface EWDG driver APIs
18 * @addtogroup ewdg_interface
19 * @{
20 */
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 /**
27 * @brief EWDG error codes
28 */
29 enum {
30 status_ewdg_tick_out_of_range = MAKE_STATUS(status_group_ewdg, 0), /*!< The tick is out of range */
31 status_ewdg_div_out_of_range = MAKE_STATUS(status_group_ewdg, 1), /*!< Clock Divider is out of range */
32 status_ewdg_feature_unsupported = MAKE_STATUS(status_group_ewdg, 2), /*!< Feature is not supported */
33 };
34
35 /**
36 * @brief EWDG Password Definitions
37 *
38 * @defgroup ewdg_password_def EWDG Password definitions
39 * @{
40 */
41 #define EWDG_REFRESH_UNLOCK_PASSWORD_DEFAULT (0xED09U) /*!< Default EWDG Refresh Password */
42 #define EWDG_UPDATE_PASSWORD_DEFAULT (0xECF9U) /*!< Default EWDG Update Password */
43 #define EWDG_REFRESH_UNLOCK_FIXED_KEY (0x55AAU) /*!< EWDG Unlock Fixed key */
44 #define EWDG_REFRESH_KEY (0x5A45524FUL) /*!< EWDG Refresh key */
45 /**
46 * @}
47 */
48
49 /**
50 * @brief EWDG Events
51 *
52 * @defgroup ewdg_event EWDG Event definitions
53 * @{
54 */
55 #define EWDG_EVENT_PARITY_ERROR (1UL << 6) /*!< Parity Error Event */
56 #define EWDG_EVENT_TIMEOUT_RESET (1UL << 5) /*!< Timeout Reset Event */
57 #define EWDG_EVENT_TIMEOUT_INTERRUPT (1UL << 4) /*!< Timeout Interrupt Event */
58 #define EWDG_EVENT_CFG_REG_UPDATE_UNLOCK_FAIL (1UL << 3) /*!< Update Unlock Fail Event */
59 #define EWDG_EVENT_CFG_REG_UPDATE_VIOLATION (1UL << 2) /*!< Update Violation Event */
60 #define EWDG_EVENT_REFRESH_UNLOCK_FAIL (1UL << 1) /*!< Refresh Unlock Fail Event */
61 #define EWDG_EVENT_REFRESH_VIOLATION (1UL << 0) /*!< Refresh Violation Event */
62 /**
63 * @}
64 */
65
66 /**
67 * @brief EWDG Interrupts
68 * @defgroup ewdg_interrupt EWDG interrupt definitions
69 * @{
70 */
71 #define EWDG_INT_PARITY_FAIL (1UL << 2) /*!< Parity Error Interrupt */
72 #define EWDG_INT_CTRL_REG_UNLOCK_FAIL (1UL << 4) /*!< Unlock Control Register Fail Interrupt */
73 #define EWDG_INT_CTRL_REG_UPDATE_FAIL (1UL << 6) /*!< Update Control Register Violation Interrupt */
74 #define EWDG_INT_TIMEOUT (1UL << 16) /*!< Watchdog Timeout Interrupt */
75 #define EWDG_INT_REFRESH_UNLOCK_FAIL (1UL << 20) /*!< Refresh Register Unlock Fail interrupt */
76 #define EWDG_INT_REFRESH_VIOLATION (1UL << 22) /*!< Refresh Register Violation interrupt */
77 /*! All Interrupt masks */
78 #define EWDG_INT_ALL (EWDG_INT_PARITY_FAIL | EWDG_INT_CTRL_REG_UNLOCK_FAIL | EWDG_INT_CTRL_REG_UPDATE_FAIL | \
79 EWDG_INT_TIMEOUT | EWDG_INT_REFRESH_UNLOCK_FAIL | EWDG_INT_REFRESH_VIOLATION)
80 /**
81 * @}
82 */
83
84 /**
85 * @brief EWDG Resets
86 *
87 * @defgroup ewdg_reset_source EWDG reset source definitions
88 * @{
89 */
90 #define EWDG_RST_PARITY_FAIL (1UL << 3) /*!< Parity Error Reset */
91 #define EWDG_RST_CTRL_REG_UNLOCK_FAIL (1UL << 5) /*!< Unlock Control Register Fail Reset */
92 #define EWDG_RST_CTRL_REG_UPDATE_FAIL (1UL << 7) /*!< Update Control Register Violation Reset */
93 #define EWDG_RST_TIMEOUT (1UL << 17) /*!< Watchdog Timeout Reset */
94 #define EWDG_RST_REFRESH_UNLOCK_FAIL (1UL << 21) /*!< Refresh Register Unlock Fail Reset */
95 #define EWDG_RST_REFRESH_VIOLATION (1UL << 23) /*!< Refresh Register Violation Reset */
96 /*! All Reset masks */
97 #define EWDG_RST_ALL (EWDG_RST_PARITY_FAIL | EWDG_RST_CTRL_REG_UNLOCK_FAIL | EWDG_RST_CTRL_REG_UPDATE_FAIL | \
98 EWDG_RST_TIMEOUT | EWDG_RST_REFRESH_UNLOCK_FAIL | EWDG_RST_REFRESH_VIOLATION)
99 /**
100 * @}
101 */
102
103
104
105 /**
106 * @brief EWDG Refresh Unlock Methods
107 */
108 typedef enum {
109 /*! Use the Unlock Password directly */
110 ewdg_refresh_unlock_method_password = 0,
111 /*! Use password[14:0] | password[15] */
112 ewdg_refresh_unlock_method_ring_left_shift_password_by_1 = 1,
113 /*! Use fixed key: 0x55AA */
114 ewdg_refresh_unlock_method_fixed_key = 2,
115 /*! Use last_password[14:0] | (last_password[15] ^ password[0]) */
116 ewdg_refresh_unlock_method_ring_left_shift_password_by_1_bit0_xor_password_bit0 = 3,
117 /*! Max allowed range */
118 ewdg_refresh_unlock_method_max = ewdg_refresh_unlock_method_ring_left_shift_password_by_1_bit0_xor_password_bit0
119 } ewdg_refresh_unlock_method_t;
120
121 /**
122 * @brief EWDG Clock source for internal counter
123 */
124 typedef enum {
125 ewdg_cnt_clk_src_bus_clk, /*!< Clock is from BUS clock */
126 ewdg_cnt_clk_src_ext_osc_clk, /*!< Clock is from External OSC */
127 } ewdg_cnt_clk_sel_t;
128
129 /**
130 * @brief EWDG Lower Window Limitations
131 */
132 typedef enum {
133 /*! Refresh should be issued after 8/16 of timeout period */
134 ewdg_window_lower_timeout_period_8_div_16 = 0,
135 /*! Refresh should be issued after 10/16 of timeout period */
136 ewdg_window_lower_timeout_period_10_div_16 = 1,
137 /*! Refresh should be issued after 12/16 of timeout period */
138 ewdg_window_lower_timeout_period_12_div_16 = 2,
139 /*! Refresh should be issued after 14/16 of timeout period */
140 ewdg_window_lower_timeout_period_14_div_16 = 3,
141 /*! Maximum allowed limit value */
142 ewdg_window_lower_timeout_period_max = ewdg_window_lower_timeout_period_14_div_16
143 } ewdg_window_low_limit_t;
144
145 /**
146 * @brief EWDG Upper Window Limitations
147 *
148 * The Actual Upper Window = Lower Window + Upper Window Limit
149 */
150 typedef enum {
151 ewdg_window_upper_timeout_period_8_div_16 = 0, /*!< 8/16 of timeout_reset_val */
152 ewdg_window_upper_timeout_period_1_div_16 = 1, /*!< 1/16 of timeout_reset_val */
153 ewdg_window_upper_timeout_period_2_div_16 = 2, /*!< 2/16 of timeout_reset_val */
154 ewdg_window_upper_timeout_period_3_div_16 = 3, /*!< 3/16 of timeout_reset_val */
155 ewdg_window_upper_timeout_period_4_div_16 = 4, /*!< 4/16 of timeout_reset_val */
156 ewdg_window_upper_timeout_period_5_div_16 = 5, /*!< 5/16 of timeout_reset_val */
157 ewdg_window_upper_timeout_period_6_div_16 = 6, /*!< 6/16 of timeout_reset_val */
158 ewdg_window_upper_timeout_period_7_div_16 = 8, /*!< 7/16 of timeout_reset_val */
159 /*! Maximum allowed upper limit */
160 ewdg_window_upper_timeout_period_max = ewdg_window_upper_timeout_period_7_div_16
161 } ewdg_window_upper_limit_t;
162
163 typedef enum {
164 ewdg_low_power_mode_halt = 0, /*!< Watchdog is halted in low power mode */
165 ewdg_low_power_mode_work_clock_normal = 1, /*!< Watchdog is will work with normal clock in low power mode */
166 } ewdg_low_power_mode_t;
167
168 /***
169 * @brief EWDG Function Control Configurations
170 */
171 typedef struct {
172 ewdg_cnt_clk_sel_t cnt_clk_sel; /*!< Clock source for counter */
173 bool enable_window_mode; /*!< Enable window mode */
174 ewdg_window_low_limit_t window_lower_limit; /*!< Lower limit of the window */
175 /*! Upper limit of the window
176 * The real upper window = (window_lower_limit/8 + window_upper_limit/16) * timeout_reset_val
177 */
178 ewdg_window_upper_limit_t window_upper_limit;
179
180 bool enable_config_lock; /*!< Enable Lock for the Configuration Registers */
181
182 bool enable_refresh_period; /*!< Enable Refresh period */
183 bool enable_refresh_lock; /*!< Enable Refresh lock */
184 ewdg_refresh_unlock_method_t refresh_unlock_method; /*!< Method to unlock REFRESH_REG */
185
186 bool enable_overtime_self_clear; /*!< Enable Over time self clear */
187
188 bool keep_running_in_debug_mode; /*!< Keep running even in debug mode */
189 ewdg_low_power_mode_t low_power_mode; /*!< Watchdog behavior in low power mode */
190 /*!
191 * Select timeout value type
192 * - true: use the IP-level value (in terms of EWDG counter ticks)
193 * - false: Use the user friendly timeout value (in terms of microseconds)
194 */
195 bool use_lowlevel_timeout;
196 union {
197 struct {
198 uint32_t timeout_interrupt_us; /*!< Timeout value for interrupt (in terms of microseconds) */
199 uint32_t timeout_reset_us; /*!< Timeout value for reset (in terms of microseconds */
200 };
201 struct {
202 uint32_t timeout_interrupt_val; /*!< Timeout value for interrupt (in terms of counter ticks) */
203 /*! Timeout value for reset (in terms of counter ticks
204 * Note: timeout_reset_val must > timeout_interrupt_val
205 */
206 uint32_t timeout_reset_val;
207 uint32_t clock_div_by_power_of_2; /*!< Power of 2 Divider */
208 };
209 };
210
211 uint16_t refresh_period_in_bus_cycles; /*!< Refresh period */
212 uint16_t refresh_unlock_password; /*!< Password for unlocking write to REFRESH_REG */
213
214 uint16_t ctrl_reg_update_password; /*!< Update Password */
215 uint16_t ctrl_reg_update_period_bus_clk_x_128; /*!< Update Period */
216 } ewdg_func_ctrl_config_t;
217
218 /**
219 * @brief EWDG Reset and Interrupt Configurations
220 */
221 typedef struct {
222 bool enable_ctrl_parity_fail_interrupt; /*!< Enable Parity Fail Interrupt */
223 bool enable_ctrl_parity_fail_reset; /*!< Enable Parity Fail Reset */
224 bool enable_ctrl_unlock_fail_interrupt; /*!< Enable Control Register Unlock Fail Interrupt */
225 bool enable_ctrl_unlock_fail_reset; /*!< Enable Control Register Unlock Fail Reset */
226 bool enable_ctrl_update_violation_interrupt; /*!< Enable Control Register Update Violation Interrupt */
227 bool enable_ctrl_update_violation_reset; /*!< Enable Control Register Update Violation Reset */
228 bool enable_timeout_interrupt; /*!< Enable Timeout Interrupt */
229 bool enable_timeout_reset; /*!< Enable Timeout Reset */
230 bool enable_refresh_unlock_fail_interrupt; /*!< Enable Refresh Unlock Fail Interrupt */
231 bool enable_refresh_unlock_fail_reset; /*!< Enable Refresh Unlock Fail Reset */
232 bool enable_refresh_violation_interrupt; /*!< Enable Refresh Violation Interrupt */
233 bool enable_refresh_violation_reset; /*!< Enable Refresh Violation Reset */
234 } ewdg_interrupt_reset_config_t;
235
236 /**
237 * @brief Enhanced Watchdog Configuration Structure
238 */
239 typedef struct {
240 ewdg_interrupt_reset_config_t int_rst_config; /*!< Error Control Configuration */
241 ewdg_func_ctrl_config_t ctrl_config; /*!< Function Control Configuration */
242 bool enable_watchdog; /*!< Enable Watchdog */
243 uint32_t cnt_src_freq; /*!< Frequency for the clock used as the counter clock source */
244 } ewdg_config_t;
245
246 /**
247 * @brief Check whether the Control Registers are locked
248 *
249 * @param [in] ptr EWDG base
250 *
251 * @retval true Control Registers are locked
252 * @retval false Control Registers are unlocked
253 */
ewdg_is_ctrl_reg_locked(EWDG_Type * ptr)254 static inline bool ewdg_is_ctrl_reg_locked(EWDG_Type *ptr)
255 {
256 return ((ptr->CTRL0 & EWDG_CTRL0_CFG_LOCK_MASK) != 0U);
257 }
258
259 /**
260 * @brief Get the Divider for Counter Clock
261 *
262 * @param [in] ptr EWDG base
263 *
264 * @return divider value
265 */
ewdg_get_count_clk_divider(EWDG_Type * ptr)266 static inline uint32_t ewdg_get_count_clk_divider(EWDG_Type *ptr)
267 {
268 return (1UL << EWDG_CTRL0_DIV_VALUE_GET(ptr->CTRL0));
269 }
270
271 /**
272 * @brief Check whether the Refresh register is locked
273 *
274 * @param [in] ptr EWDG base
275 *
276 * @retval true Control Registers are locked
277 * @retval false Control Registers are unlocked
278 */
ewdg_is_refresh_locked(EWDG_Type * ptr)279 static inline bool ewdg_is_refresh_locked(EWDG_Type *ptr)
280 {
281 return ((ptr->CTRL0 & EWDG_CTRL0_REF_LOCK_MASK) != 0U);
282 }
283
284 /**
285 * @brief Unlock Write to Control Registers
286 *
287 * @param [in] ptr EWDG base
288 */
ewdg_unlock_ctrl_regs(EWDG_Type * ptr)289 static inline void ewdg_unlock_ctrl_regs(EWDG_Type *ptr)
290 {
291 uint32_t ctrl_update_prot = ptr->CFG_PROT;
292 ptr->CFG_PROT = ctrl_update_prot;
293 }
294
295 /**
296 * @brief Write Refresh Magic Number to EWDG Refresh register
297 * @param [in] ptr EWDG base
298 */
ewdg_write_refresh_reg(EWDG_Type * ptr)299 static inline void ewdg_write_refresh_reg(EWDG_Type *ptr)
300 {
301 ptr->WDT_REFRESH_REG = EWDG_REFRESH_KEY;
302 }
303
304 /**
305 * @brief Get the Timeout Reset ticks
306 * @param [in] ptr EWDG base
307 * @return Timeout Reset ticks
308 */
ewdg_get_timeout_reset_ticks(EWDG_Type * ptr)309 static inline uint32_t ewdg_get_timeout_reset_ticks(EWDG_Type *ptr)
310 {
311 return ptr->OT_RST_VAL;
312 }
313
314 #if !defined(EWDG_SOC_SUPPORT_TIMEOUT_INTERRUPT) || (EWDG_SOC_SUPPORT_TIMEOUT_INTERRUPT == 1)
315 /**
316 * @brief Get the Timeout Interrupt ticks
317 * @param [in] ptr EWDG base
318 * @return Timeout Interrupt ticks
319 */
ewdg_get_timeout_interrupt_ticks(EWDG_Type * ptr)320 static inline uint32_t ewdg_get_timeout_interrupt_ticks(EWDG_Type *ptr)
321 {
322 return ptr->OT_INT_VAL;
323 }
324 #endif
325
326 /**
327 * @brief Clear Interrupt Status for EWDG
328 *
329 * @note The TIMEOUT_INT_EVENT cannot be cleared directly, it needs to be cleared by the refresh sequence
330 *
331 * @param [in] ptr EWDG base
332 * @param [in] mask Status Mask Bits, @ref ewdg_event
333 */
ewdg_clear_status_flags(EWDG_Type * ptr,uint32_t mask)334 static inline void ewdg_clear_status_flags(EWDG_Type *ptr, uint32_t mask)
335 {
336 ptr->WDT_STATUS = mask;
337 }
338
339 /**
340 * @brief Get the Status of EWDG
341 *
342 * @param [in] ptr EWDG base
343 *
344 * @return STATUS register value
345 */
ewdg_get_status_flags(EWDG_Type * ptr)346 static inline uint32_t ewdg_get_status_flags(EWDG_Type *ptr)
347 {
348 return ptr->WDT_STATUS;
349 }
350
351 /**
352 * @brief Get the Refresh Unlock Mechanism
353 * @param [in] ptr EWDG base
354 * @return EWDG refresh unlock method
355 */
ewdg_get_refresh_unlock_method(EWDG_Type * ptr)356 static inline ewdg_refresh_unlock_method_t ewdg_get_refresh_unlock_method(EWDG_Type *ptr)
357 {
358 return (ewdg_refresh_unlock_method_t) (EWDG_CTRL0_REF_UNLOCK_MEC_GET(ptr->CTRL0));
359 }
360
361 /**
362 * @brief Enable EWDG
363 *
364 * This function enables the functionality of the EWDG and start the watchdog timer
365 *
366 * @param [in] ptr EWDG base
367 *
368 * @note Once the EWDG is enabled,
369 * - if the software needs to update the control register, the update unlock must be
370 * performed first if the control register lock is enabled.
371 *
372 */
373 void ewdg_enable(EWDG_Type *ptr);
374
375
376 /**
377 * @brief Disable EWDG
378 * @param [in] ptr EWDG base
379 */
380 void ewdg_disable(EWDG_Type *ptr);
381
382 /**
383 * @brief Initialize the Control function for EWDG
384 *
385 * @param [in] ptr EWDG base
386 * @param [in] config Control Function Configuration
387 * @param [in] cnt_src_freq Source frequency for EWDG counter
388 *
389 * @retval status_invalid_argument Invalid argument was detected
390 * @retval status_success No error happened
391 */
392 hpm_stat_t ewdg_init_ctrl_func(EWDG_Type *ptr, ewdg_func_ctrl_config_t *config, uint32_t cnt_src_freq);
393
394 /**
395 * @brief Initialize the Error function for EWDG
396 *
397 * @param [in] ptr EWDG base
398 * @param [in] config Error Function Configuration
399 *
400 * @retval status_invalid_argument Invalid argument was detected
401 * @retval status_success No error happened
402 */
403 hpm_stat_t ewdg_init_interrupt_reset(EWDG_Type *ptr, ewdg_interrupt_reset_config_t *config);
404
405 /**
406 * @brief Get default configuration for EWDG
407 * @param [in] ptr EWDG base
408 * @param [out] config EWDG Configuration
409 */
410 void ewdg_get_default_config(EWDG_Type *ptr, ewdg_config_t *config);
411
412 /**
413 * @brief Initialize the EWDG module
414 *
415 * @param [in] ptr EWDG base
416 * @param [in] config EWDG configuration
417 *
418 * @retval status_invalid_argument Invalid argument was detected
419 * @retval status_success No error happened
420 */
421 hpm_stat_t ewdg_init(EWDG_Type *ptr, ewdg_config_t *config);
422
423 /**
424 * @brief Unlock the write to refresh register
425 *
426 * @param [in] ptr EWDG base
427 *
428 * @retval status_invalid_argument Invalid argument was detected
429 * @retval status_success No error happened
430 */
431 hpm_stat_t ewdg_unlock_refresh(EWDG_Type *ptr);
432
433 /**
434 * @brief Refresh EWDG
435 *
436 * @param [in] ptr EWDG base
437 *
438 * @retval status_invalid_argument Invalid argument was detected
439 * @retval status_success No error happened
440 */
441 hpm_stat_t ewdg_refresh(EWDG_Type *ptr);
442
443 /**
444 * @brief Get the Divided Counter Clock Frequency for EWDG
445 *
446 * @param [in] ptr EWDG base
447 * @param [in] src_clk_freq Source clock of the Counter clock
448 *
449 * @return divided Counter clock Frequency
450 */
451 uint32_t ewdg_get_count_clock_freq(EWDG_Type *ptr, uint32_t src_clk_freq);
452
453 /**
454 * @brief Convert the timeout in terms of microseconds to the timeout in terms of timeout ticks
455 *
456 * @param [in] src_clk_freq Clock Frequency of the counter clock source
457 * @param [in] timeout_us Timeout in terms of microseconds
458 *
459 * @return timeout in terms of counter clock ticks
460 */
461 uint64_t ewdg_convert_timeout_us_to_timeout_ticks(uint32_t src_clk_freq, uint32_t timeout_us);
462
463 /**
464 * @brief Convert the timeout in terms of timeout ticks to the timeout in terms of microseconds
465 *
466 * @param [in] ptr EWDG base
467 * @param [in] src_clk_freq Clock Frequency of the counter clock source
468 * @param [in] timeout_ticks Timeout in terms of ticks
469 *
470 * @return timeout in terms of counter clock ticks
471 */
472 uint32_t ewdg_convert_timeout_ticks_to_timeout_us(EWDG_Type *ptr, uint32_t src_clk_freq, uint32_t timeout_ticks);
473
474 /**
475 * @brief Enable EWDG interrupt
476 * @param [in] ptr EWDG base
477 * @param [in] mask Interrupt Mask, valid value refer to @ref ewdg_interrupt
478 */
479 void ewdg_enable_interrupt(EWDG_Type *ptr, uint32_t mask);
480
481 /**
482 * @brief Disable EWDG interrupt
483 * @param [in] ptr EWDG base
484 * @param [in] mask Interrupt Mask, valid value refer to @ref ewdg_interrupt
485 */
486 void ewdg_disable_interrupt(EWDG_Type *ptr, uint32_t mask);
487
488 /**
489 * @brief Enable EWDG Reset
490 * @param [in] ptr EWDG base
491 * @param [in] mask Reset Mask, valid value refer to @ref ewdg_reset_source
492 */
493 void ewdg_enable_reset(EWDG_Type *ptr, uint32_t mask);
494
495 /**
496 * @brief Disable EWDG Reset
497 * @param [in] ptr EWDG base
498 * @param [in] mask Reset Mask, valid value refer to @ref ewdg_reset_source
499 */
500 void ewdg_disable_reset(EWDG_Type *ptr, uint32_t mask);
501
502 /**
503 * @brief Switch the EWDG clock source
504 * @param [in] ptr EWDG base
505 * @param [in] clk_sel Clock source selection for EWDG counter
506 */
507 void ewdg_switch_clock_source(EWDG_Type *ptr, ewdg_cnt_clk_sel_t clk_sel);
508
509
510 #ifdef __cplusplus
511 }
512 #endif
513
514 /**
515 * @}
516 */
517
518 #endif /* HPM_EWDG_DRV_H */
519