1 /**
2  * @file xmc_wdt.h
3  * @date 2015-08-06
4  *
5  * @cond
6  *********************************************************************************************************************
7  * XMClib v2.1.24 - XMC Peripheral Driver Library
8  *
9  * Copyright (c) 2015-2019, Infineon Technologies AG
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
13  * following conditions are met:
14  *
15  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16  * disclaimer.
17  *
18  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19  * disclaimer in the documentation and/or other materials provided with the distribution.
20  *
21  * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22  * products derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33  * Infineon Technologies AG dave@infineon.com).
34  *********************************************************************************************************************
35  *
36  * Change History
37  * --------------
38  *
39  * 2015-02-20:
40  *     - Initial <br>
41  *     - Documentation updates <br>
42  *
43  * 2015-06-20:
44  *     - Removed version macros and declaration of GetDriverVersion API <br>
45  *
46  * 2015-08-06:
47  *     - Bug fix in XMC_WDT_SetDebugMode() API, Wrong register is being configured.<br>
48  * @endcond
49  */
50 
51 #ifndef XMC_WDT_H
52 #define XMC_WDT_H
53 
54 /*********************************************************************************************************************
55  * HEADER FILES
56  ********************************************************************************************************************/
57 
58 #include "xmc_common.h"
59 #include "xmc_scu.h"
60 /**
61  * @addtogroup XMClib XMC Peripheral Library
62  * @{
63  */
64 
65 /**
66  * @addtogroup WDT
67  * @brief Watchdog driver for the XMC microcontroller family.
68  *
69  * The watchdog unit (WDT) improves the system integrity, by triggering the system reset request to bring the system
70  * back from the unresponsive state to normal operation.
71  *
72  * This LLD provides the Configuration structure XMC_WDT_CONFIG_t and initialization function XMC_WDT_Init().\n
73  * It can be used to:
74  * -# Start or Stop the watchdog timer. (XMC_WDT_Start() and XMC_WDT_Stop())
75  * -# Service the watchdog timer. (XMC_WDT_Service())
76  * -# Configure the service window upper bound and lower bound timing values. (XMC_WDT_SetWindowBounds())
77  * -# Enable the generation of the pre-warning event for the first overflow of the timer. (XMC_WDT_SetMode())
78  * -# Clear the pre-warning alarm event. It is mandatory to clear the flag during pre-warning alarm ISR, to stop
79       generating reset request for the second overflow of the timer. (XMC_WDT_ClearAlarm())
80  * -# Suspend the watchdog timer during Debug HALT mode. (XMC_WDT_SetDebugMode())
81  * -# Configure service indication pulse width.(XMC_WDT_SetServicePulseWidth())
82  *
83  * @{
84  */
85 
86 /*********************************************************************************************************************
87  * MACROS
88   ********************************************************************************************************************/
89 
90 #define XMC_WDT_MAGIC_WORD             (0xABADCAFEU) /* Magic word to be written in Service Register (SRV),
91                                                           to service or feed the watchdog. */
92 
93 /*********************************************************************************************************************
94  * ENUMS
95   ********************************************************************************************************************/
96 
97 /**
98  *  Defines working modes for watchdog. Use type XMC_WDT_MODE_t for this enum.
99  */
100 typedef enum XMC_WDT_MODE
101 {
102   XMC_WDT_MODE_TIMEOUT    = (uint32_t)0x0 << WDT_CTR_PRE_Pos, /**< Generates reset request as soon as the timer overflow
103                                                                    occurs. */
104   XMC_WDT_MODE_PREWARNING = (uint32_t)0x1 << WDT_CTR_PRE_Pos  /**< Generates an alarm event for the first overflow. And
105                                                                    reset request after subsequent overflow, if not
106                                                                    serviced after first overflow. */
107 } XMC_WDT_MODE_t;
108 
109 /**
110  *  Defines debug behaviour of watchdog when the CPU enters HALT mode. Use type XMC_WDT_DEBUG_MODE_t for this enum.
111  */
112 typedef enum XMC_WDT_DEBUG_MODE
113 {
114   XMC_WDT_DEBUG_MODE_STOP = (uint32_t)0x0 << WDT_CTR_DSP_Pos, /**< Watchdog counter is paused during debug halt. */
115   XMC_WDT_DEBUG_MODE_RUN  = (uint32_t)0x1 << WDT_CTR_DSP_Pos  /**< Watchdog counter is not paused during debug halt. */
116 } XMC_WDT_DEBUG_MODE_t;
117 
118 /*********************************************************************************************************************
119  * DATA STRUCTURES
120   ********************************************************************************************************************/
121  /* Anonymous structure/union guard start */
122 #if defined(__CC_ARM)
123   #pragma push
124   #pragma anon_unions
125 #elif defined(__TASKING__)
126   #pragma warning 586
127 #endif
128 
129 /**
130  * Structure for initializing watchdog timer. Use type XMC_WDT_CONFIG_t for this structure.
131  */
132 typedef struct XMC_WDT_CONFIG
133 {
134   uint32_t window_upper_bound; /**< Upper bound for service window (WUB). Reset request is generated up on overflow of
135                                     timer. ALways upper bound value has to be more than lower bound value. If it is set
136                                     lower than WLB, triggers a system reset after timer crossed upper bound value.\n
137                                     Range: [0H to FFFFFFFFH] */
138   uint32_t window_lower_bound; /**< Lower bound for servicing window (WLB). Setting the lower bound to 0H disables the
139                                     window mechanism.\n
140                                     Range: [0H to FFFFFFFFH] */
141   union
142   {
143     struct
144     {
145       uint32_t : 1;
146       uint32_t prewarn_mode : 1;        /**< Pre-warning mode (PRE). This accepts boolean values as input. */
147       uint32_t : 2;
148       uint32_t run_in_debug_mode : 1;   /**< Watchdog timer behaviour during debug (DSP). This accepts boolean values as input. */
149       uint32_t : 3;
150       uint32_t service_pulse_width : 8; /**< Service Indication Pulse Width (SPW). Generated Pulse width is of (SPW+1),
151                                              in fwdt cycles.\n
152                                              Range: [0H to FFH] */
153       uint32_t : 16;
154     };
155     uint32_t wdt_ctr; /* Value of operation mode control register (CTR). It’s bit fields are represented by above
156                            union members. */
157   };
158 } XMC_WDT_CONFIG_t;
159 /* Anonymous structure/union guard end */
160 #if defined(__CC_ARM)
161   #pragma pop
162 #elif defined(__TASKING__)
163   #pragma warning restore
164 #endif
165 /*********************************************************************************************************************
166  * API PROTOTYPES
167   ********************************************************************************************************************/
168 
169 #ifdef __cplusplus
170 extern "C" {
171 #endif
172 
173 /**
174  * @param None
175  *
176  * @return None
177  *
178  * \par<b>Description:</b><br>
179  * \if XMC4
180  * Enables watchdog clock and releases watchdog reset.\n
181  * \endif
182  * \if XMC1
183  * Enables watchdog clock.\n
184  * \endif
185  * \par
186  * This API is invoked by XMC_WDT_Init() and therefore no need to call it explicitly during watchdog initialization
187  * sequence. Invoke this API to enable watchdog once again if the watchdog is disabled by invoking XMC_WDT_Disable().
188  *
189  * \par<b>Note:</b><br>
190  * \if XMC4
191  * 1. It is required to configure the watchdog, again after invoking XMC_WDT_Disable(). Since all the registers are
192  *    reset with default values.
193  * \endif
194  * \if XMC1
195  * 1. Not required to configure the watchdog again after invoking XMC_WDT_Disable(). Since the registers retains with
196  *    the configured values.
197  * \endif
198  * \par<b>Related APIs:</b><BR>
199  * XMC_WDT_Init(), XMC_WDT_Disable()
200  */
201 void XMC_WDT_Enable(void);
202 
203 /**
204  * @param None
205  *
206  * @return None
207  *
208  * \par<b>Description:</b><br>
209  * \if XMC4
210  * Disables the clock and resets watchdog timer.\n
211  * \endif
212  * \if XMC1
213  * Disables the clock to the watchdog timer.\n
214  * \endif
215  *
216  * \par<b>Note:</b><br>
217  * \if XMC4
218  * 1. Resets the registers with default values. So XMC_WDT_Init() has to be invoked again to configure the watchdog.
219  * \endif
220  * \if XMC1
221  * 1. After invoking XMC_WDT_Disable(), all register values are displayed with 0F in debugger. Once enabled by
222       calling XMC_WDT_Enable(), previous configured register values are displayed. No need to invoke XMC_WDT_Init()
223       again.
224  * \endif
225  * \par<b>Related APIs:</b><BR>
226  * XMC_WDT_Enable()
227  */
228 void XMC_WDT_Disable(void);
229 
230 /**
231  * @param config pointer to a constant watchdog configuration data structure. Refer data structure XMC_WDT_CONFIG_t
232  *               for detail.
233  *
234  * @return None
235  *
236  * \par<b>Description:</b><br>
237  * Initializes and configures watchdog with configuration data pointed by \a config.\n
238  * \par
239  * It invokes XMC_WDT_Enable() to enable clock and release reset. Then configures the lower and upper window bounds,
240  * working mode (timeout/pre-warning), debug behaviour and service request indication pulse width.
241  *
242  * \par<b>Note:</b><br>
243  * 1. With out invoking this XMC_WDT_Init() or XMC_WDT_Enable(), invocation of other APIs like XMC_WDT_SetWindowBounds(),
244  *    XMC_WDT_SetMode(), XMC_WDT_SetServicePulseWidth(), XMC_WDT_SetDebugMode(), XMC_WDT_Start(), XMC_WDT_GetCounter(),
245  *    XMC_WDT_Service(), XMC_WDT_ClearAlarm() has no affect.
246  */
247 void XMC_WDT_Init(const XMC_WDT_CONFIG_t *const config);
248 
249 /**
250  * @param lower_bound specifies watchdog window lower bound in terms of watchdog clock (fWDT) cycles.
251  *                    Range: [0H to FFFFFFFFH].
252  * @param upper_bound specifies watchdog window upper bound in terms of watchdog clock (fWDT) cycles.
253  *                    Range: [0H to FFFFFFFFH].
254  *
255  * @return None
256  *
257  * \par<b>Description:</b><br>
258  * Sets watchdog window lower and upper bounds by updating WLB and WUB registers.\n
259  * \par
260  * Window lower and upper bounds are set during initialization in XMC_WDT_Init(). Invoke this API to alter the values as
261  * needed later in the program. This upper bound and lower bound can be calculated by using the below formula\n
262  *       upper_bound or lower_bound = desired_boundary_time(sec) * fwdt(hz)
263  *
264  * \par<b>Note:</b>
265  * 1. Always ensure that upper_bound is greater than the lower_bound value. If not, whenever timer crosses the
266  *    upper_bound value it triggers the reset(wdt_rst_req) of the controller.
267  */
XMC_WDT_SetWindowBounds(uint32_t lower_bound,uint32_t upper_bound)268 __STATIC_INLINE void XMC_WDT_SetWindowBounds(uint32_t lower_bound, uint32_t upper_bound)
269 {
270   WDT->WLB = lower_bound;
271   WDT->WUB = upper_bound;
272 }
273 
274 /**
275  * @param mode is one of the working modes of the watchdog timer, i.e timeout or pre-warning. Refer @ref XMC_WDT_MODE_t
276  *             for valid values.
277  *
278  * @return None
279  *
280  * \par<b>Description:</b><br>
281  * Sets watchdog working mode (timeout or pre-warning) by updating PRE bit of CTR register.\n
282  * \par
283  * The working mode is set during initialization in XMC_WDT_Init(). Invoke this API to alter the mode as needed later in
284  * the program.
285  */
XMC_WDT_SetMode(XMC_WDT_MODE_t mode)286 __STATIC_INLINE void XMC_WDT_SetMode(XMC_WDT_MODE_t mode)
287 {
288   WDT->CTR = (WDT->CTR & (uint32_t)~WDT_CTR_PRE_Msk) | (uint32_t)mode;
289 }
290 
291 /**
292  * @param service_pulse_width specifies Service indication pulse width in terms of fwdt.
293  *                            Range: [0H – FFH].
294  * @return None
295  *
296  * \par<b>Description:</b><br>
297  * Sets service indication pulse width by updating SPW bit field of CTR register.\n
298  * \par
299  * The service indication pulse (with width service_pulse_width + 1 in fwdt cycles) is generated on successful servicing
300  * or feeding of watchdog. The pulse width is initially set during initialization in XMC_WDT_Init(). Invoke this API to
301  * alter the width as needed later in the program.
302  */
XMC_WDT_SetServicePulseWidth(uint8_t service_pulse_width)303 __STATIC_INLINE void XMC_WDT_SetServicePulseWidth(uint8_t service_pulse_width)
304 {
305   WDT->CTR = (WDT->CTR & (uint32_t)~WDT_CTR_SPW_Msk) | ((uint32_t)service_pulse_width << WDT_CTR_SPW_Pos);
306 }
307 
308 /**
309  * @param debug_mode running state of watchdog during debug halt mode. Refer @ref XMC_WDT_DEBUG_MODE_t for
310  *                   valid values.
311  *
312  * @return None
313  *
314  * \par<b>Description:</b><br>
315  * Sets debug behaviour of watchdog by modifying DSP bit of CTR register.\n
316  * \par
317  * Depending upon DSP bit, the watchdog timer stops when CPU is in HALT mode. The debug behaviour is initially set as
318  * XMC_WDT_DEBUG_MODE_STOP during initialization in XMC_WDT_Init(). Invoke this API to change the debug behaviour as
319  * needed later in the program.
320  */
XMC_WDT_SetDebugMode(const XMC_WDT_DEBUG_MODE_t debug_mode)321 __STATIC_INLINE void XMC_WDT_SetDebugMode(const XMC_WDT_DEBUG_MODE_t debug_mode)
322 {
323   WDT->CTR = (WDT->CTR & (uint32_t)~WDT_CTR_DSP_Msk) | (uint32_t)debug_mode;
324 }
325 
326 /**
327  * @param None
328  *
329  * @return None
330  *
331  * \par<b>Description:</b><br>
332  * Start the watchdog timer by setting ENB bit of CTR register.\n
333  * \par
334  * Invoke this API to start the watchdog after initialization, or to resume the watchdog when
335  * paused by invoking XMC_WDT_Stop().
336  *
337  * \par<b>Related APIs:</b><BR>
338  * XMC_WDT_Init(), XMC_WDT_Stop()
339  */
XMC_WDT_Start(void)340 __STATIC_INLINE void XMC_WDT_Start(void)
341 {
342   WDT->CTR |= (uint32_t)WDT_CTR_ENB_Msk;
343 }
344 
345 /**
346  * @param None
347  *
348  * @return None
349  *
350  * \par<b>Description:</b><br>
351  * Pauses watchdog timer by resetting ENB bit of CTR register.\n
352  * \par
353  * Invoke this API to pause the watchdog as needed in the program e.g. debugging through software control.
354  *
355  * \par<b>Related APIs:</b><BR>
356  * XMC_WDT_Init(), XMC_WDT_Stop()
357  */
XMC_WDT_Stop(void)358 __STATIC_INLINE void XMC_WDT_Stop(void)
359 {
360   WDT->CTR &= (uint32_t)~WDT_CTR_ENB_Msk;
361 }
362 
363 /**
364  * @param None
365  *
366  * @return uint32_t Current count value of watchdog timer register (TIM).
367  *                  Range: [0H to FFFFFFFFH]
368  *
369  * \par<b>Description:</b><br>
370  * Reads current count of timer register (TIM).\n
371  * \par
372  * Invoke this API before servicing or feeding the watchdog to check whether count is between lower and upper
373  * window bounds.
374  *
375  * \par<b>Related APIs:</b><BR>
376  * XMC_WDT_Service()
377  */
XMC_WDT_GetCounter(void)378 __STATIC_INLINE uint32_t XMC_WDT_GetCounter(void)
379 {
380   return WDT->TIM;
381 }
382 
383 /**
384  * @param None
385  *
386  * @return None
387  *
388  * \par<b>Description:</b><br>
389  * Services or feeds the watchdog by writing the Magic word in SRV register.\n
390  * \par
391  * Service watchdog when count value of watchdog timer is between lower and upper window bounds. Successful servicing
392  * will reset watchdog timer (TIM register) to 0H and generate service indication pulse.
393  *
394  * \par<b>Note:</b><br>
395  * 1. invoking this API when count value of watchdog timer is less than window lower bound results
396  *    wrong servicing and immediately triggers reset request.
397  *
398  * \par<b>Related APIs:</b><BR>
399  * XMC_WDT_GetCounter(), XMC_WDT_SetWindowBounds(), XMC_WDT_SetServicePulseWidth()
400  */
XMC_WDT_Service(void)401 __STATIC_INLINE void XMC_WDT_Service(void)
402 {
403   WDT->SRV = XMC_WDT_MAGIC_WORD;
404 }
405 
406 /**
407  * @param None
408  *
409  * @return None
410  *
411  * \par<b>Description:</b><br>
412  * Clears pre-warning alarm by setting ALMC bit in WDTCLR register.\n
413  * \par
414  * In pre-warning mode, first overflow of the timer upper window bound fires the pre-warning alarm. XMC_WDT_ClearAlarm()
415  * must be invoked to clear the alarm alarm. After clearing of the alarm, watchdog timer must be serviced within valid
416  * time window. Otherwise watchdog timer triggers the reset request up on crossing the upper bound value in a subsequent
417  * cycle.
418  *
419  * \par<b>Related APIs:</b><BR>
420  * XMC_WDT_Service(), XMC_WDT_SetMode()
421  */
XMC_WDT_ClearAlarm(void)422 __STATIC_INLINE void XMC_WDT_ClearAlarm(void)
423 {
424   WDT->WDTCLR = WDT_WDTCLR_ALMC_Msk;
425 }
426 
427 #ifdef __cplusplus
428 }
429 #endif
430 
431 /**
432  * @}
433  */
434 
435 /**
436  * @}
437  */
438 
439 #endif /* XMC_WDT_H */
440