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