1 /******************************************************************************
2 *  Filename:       watchdog.h
3 *  Revised:        2020-09-07 16:11:55 +0200 (Mon, 07 Sep 2020)
4 *  Revision:       58511
5 *
6 *  Description:    Defines and prototypes for the Watchdog Timer.
7 *
8 *  Copyright (c) 2015 - 2020, Texas Instruments Incorporated
9 *  All rights reserved.
10 *
11 *  Redistribution and use in source and binary forms, with or without
12 *  modification, are permitted provided that the following conditions are met:
13 *
14 *  1) Redistributions of source code must retain the above copyright notice,
15 *     this list of conditions and the following disclaimer.
16 *
17 *  2) Redistributions in binary form must reproduce the above copyright notice,
18 *     this list of conditions and the following disclaimer in the documentation
19 *     and/or other materials provided with the distribution.
20 *
21 *  3) Neither the name of the ORGANIZATION nor the names of its contributors may
22 *     be used to endorse or promote products derived from this software without
23 *     specific prior written permission.
24 *
25 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 *  POSSIBILITY OF SUCH DAMAGE.
36 *
37 ******************************************************************************/
38 
39 //*****************************************************************************
40 //
41 //! \addtogroup peripheral_group
42 //! @{
43 //! \addtogroup wdt_api
44 //! @{
45 //
46 //*****************************************************************************
47 
48 #ifndef __WDT_H__
49 #define __WDT_H__
50 
51 //*****************************************************************************
52 //
53 // If building with a C++ compiler, make all of the definitions in this header
54 // have a C binding.
55 //
56 //*****************************************************************************
57 #ifdef __cplusplus
58 extern "C"
59 {
60 #endif
61 
62 #include <stdbool.h>
63 #include <stdint.h>
64 #include "../inc/hw_types.h"
65 #include "../inc/hw_ints.h"
66 #include "../inc/hw_memmap.h"
67 #include "../inc/hw_wdt.h"
68 #include "debug.h"
69 #include "interrupt.h"
70 
71 //*****************************************************************************
72 //
73 // The following are defines for the bit fields in the WDT_O_LOCK register.
74 //
75 //*****************************************************************************
76 #define WATCHDOG_LOCK_UNLOCKED      0x00000000  // Unlocked
77 #define WATCHDOG_LOCK_LOCKED        0x00000001  // Locked
78 #define WATCHDOG_LOCK_UNLOCK        0x1ACCE551  // Unlocks the Watchdog Timer
79 
80 //*****************************************************************************
81 //
82 // The following are defines for the bit fields in the WDT_ISR, WDT_RIS, and
83 // WDT_MIS registers.
84 //
85 //*****************************************************************************
86 #define WATCHDOG_INT_TIMEOUT        0x00000001  // Watchdog timer expired
87 
88 //*****************************************************************************
89 //
90 // The type of interrupt that can be generated by the watchdog.
91 //
92 //*****************************************************************************
93 #define WATCHDOG_INT_TYPE_INT       WDT_CTL_INTTYPE_MASKABLE
94 #define WATCHDOG_INT_TYPE_NMI       WDT_CTL_INTTYPE_NONMASKABLE
95 
96 //*****************************************************************************
97 //
98 // API Functions and prototypes
99 //
100 //*****************************************************************************
101 
102 //*****************************************************************************
103 //
104 //! \brief Determines if the watchdog timer is enabled.
105 //!
106 //! This function checks to see if the watchdog timer is enabled.
107 //!
108 //! \return Returns status of Watchdog Timer:
109 //! - \c true  : Watchdog timer is enabled.
110 //! - \c false : Watchdog timer is disabled.
111 //
112 //*****************************************************************************
113 __STATIC_INLINE bool
WatchdogRunning(void)114 WatchdogRunning(void)
115 {
116     // See if the watchdog timer module is enabled, and return.
117     return((HWREG(WDT_BASE + WDT_O_CTL) & WDT_CTL_INTEN) ? true : false);
118 }
119 
120 //*****************************************************************************
121 //
122 //! \brief Enables the watchdog timer.
123 //!
124 //! This function enables the watchdog timer counter and interrupt.
125 //!
126 //! Once enabled, the watchdog interrupt can only be disabled by a hardware reset.
127 //!
128 //! \note This function has no effect if the watchdog timer has been locked.
129 //!
130 //! \return None
131 //!
132 //! \sa \ref WatchdogLock(), \ref WatchdogUnlock()
133 //
134 //*****************************************************************************
135 __STATIC_INLINE void
WatchdogEnable(void)136 WatchdogEnable(void)
137 {
138     // Enable the watchdog timer module.
139     HWREGBITW(WDT_BASE + WDT_O_CTL, WDT_CTL_INTEN_BITN) = 1;
140 }
141 
142 //*****************************************************************************
143 //
144 //! \brief Enables the watchdog timer reset.
145 //!
146 //! This function enables the capability of the watchdog timer to issue a reset
147 //! to the processor after a second timeout condition.
148 //!
149 //! \note This function has no effect if the watchdog timer has been locked.
150 //!
151 //! \return None
152 //!
153 //! \sa \ref WatchdogLock(), \ref WatchdogUnlock()
154 //
155 //*****************************************************************************
156 __STATIC_INLINE void
WatchdogResetEnable(void)157 WatchdogResetEnable(void)
158 {
159     // Enable the watchdog reset.
160     HWREGBITW(WDT_BASE + WDT_O_CTL, WDT_CTL_RESEN_BITN) = 1;
161 }
162 
163 //*****************************************************************************
164 //
165 //! \brief Disables the watchdog timer reset.
166 //!
167 //! This function disables the capability of the watchdog timer to issue a
168 //! reset to the processor after a second timeout condition.
169 //!
170 //! \note This function has no effect if the watchdog timer has been locked.
171 //!
172 //! \return None
173 //!
174 //! \sa \ref WatchdogLock(), \ref WatchdogUnlock()
175 //
176 //*****************************************************************************
177 __STATIC_INLINE void
WatchdogResetDisable(void)178 WatchdogResetDisable(void)
179 {
180     // Disable the watchdog reset.
181     HWREGBITW(WDT_BASE + WDT_O_CTL, WDT_CTL_RESEN_BITN) = 0;
182 }
183 
184 //*****************************************************************************
185 //
186 //! \brief Enables the watchdog timer lock mechanism.
187 //!
188 //! This function locks out write access to the watchdog timer configuration
189 //! registers.
190 //!
191 //! \return None
192 //
193 //*****************************************************************************
194 __STATIC_INLINE void
WatchdogLock(void)195 WatchdogLock(void)
196 {
197     // Lock out watchdog register writes. Writing anything to the WDT_O_LOCK
198     // register causes the lock to go into effect.
199     HWREG(WDT_BASE + WDT_O_LOCK) = WATCHDOG_LOCK_LOCKED;
200 }
201 
202 //*****************************************************************************
203 //
204 //! \brief Disables the watchdog timer lock mechanism.
205 //!
206 //! This function enables write access to the watchdog timer configuration
207 //! registers.
208 //!
209 //! \return None
210 //
211 //*****************************************************************************
212 __STATIC_INLINE void
WatchdogUnlock(void)213 WatchdogUnlock(void)
214 {
215     // Unlock watchdog register writes.
216     HWREG(WDT_BASE + WDT_O_LOCK) = WATCHDOG_LOCK_UNLOCK;
217 }
218 
219 //*****************************************************************************
220 //
221 //! \brief Gets the state of the watchdog timer lock mechanism.
222 //!
223 //! This function returns the lock state of the watchdog timer registers.
224 //!
225 //! \return Returns state of lock mechanism.
226 //! - \c true  : Watchdog timer registers are locked.
227 //! - \c false : Registers are not locked.
228 //
229 //*****************************************************************************
230 __STATIC_INLINE bool
WatchdogLockState(void)231 WatchdogLockState(void)
232 {
233     // Get the lock state.
234     return((HWREG(WDT_BASE + WDT_O_LOCK) == WATCHDOG_LOCK_LOCKED) ?
235                true : false);
236 }
237 
238 //*****************************************************************************
239 //
240 //! \brief Sets the watchdog timer reload value.
241 //!
242 //! This function configures the value to load into the watchdog timer when the
243 //! count reaches zero for the first time; if the watchdog timer is running
244 //! when this function is called, then the value is immediately loaded into the
245 //! watchdog timer counter.  If the \c ui32LoadVal parameter is 0, then an
246 //! interrupt is immediately generated.
247 //!
248 //! \note This function has no effect if the watchdog timer has been locked.
249 //!
250 //! \param ui32LoadVal is the load value for the watchdog timer.
251 //!
252 //! \return None
253 //!
254 //! \sa \ref WatchdogLock(), \ref WatchdogUnlock(), \ref WatchdogReloadGet()
255 //
256 //*****************************************************************************
257 __STATIC_INLINE void
WatchdogReloadSet(uint32_t ui32LoadVal)258 WatchdogReloadSet(uint32_t ui32LoadVal)
259 {
260     // Set the load register.
261     HWREG(WDT_BASE + WDT_O_LOAD) = ui32LoadVal;
262 }
263 
264 //*****************************************************************************
265 //
266 //! \brief Gets the watchdog timer reload value.
267 //!
268 //! This function gets the value that is loaded into the watchdog timer when
269 //! the count reaches zero for the first time.
270 //!
271 //! \return None
272 //!
273 //! \sa \ref WatchdogReloadSet()
274 //
275 //*****************************************************************************
276 __STATIC_INLINE uint32_t
WatchdogReloadGet(void)277 WatchdogReloadGet(void)
278 {
279     // Get the load register.
280     return(HWREG(WDT_BASE + WDT_O_LOAD));
281 }
282 
283 //*****************************************************************************
284 //
285 //! \brief Gets the current watchdog timer value.
286 //!
287 //! This function reads the current value of the watchdog timer.
288 //!
289 //! \return Returns the current value of the watchdog timer.
290 //
291 //*****************************************************************************
292 __STATIC_INLINE uint32_t
WatchdogValueGet(void)293 WatchdogValueGet(void)
294 {
295     // Get the current watchdog timer register value.
296     return(HWREG(WDT_BASE + WDT_O_VALUE));
297 }
298 
299 //*****************************************************************************
300 //
301 //! \brief Registers an interrupt handler for the watchdog timer interrupt in the dynamic interrupt table.
302 //!
303 //! \note Only use this function if you want to use the dynamic vector table (in SRAM)!
304 //!
305 //! This function registers a function as the interrupt handler for a specific
306 //! interrupt and enables the corresponding interrupt in the interrupt controller.
307 //!
308 //! The watchdog timer interrupt must be enabled via \ref WatchdogIntEnable(). It is the
309 //! interrupt handler's responsibility to clear the interrupt source via
310 //! \ref WatchdogIntClear().
311 //!
312 //! \note This function registers the standard watchdog interrupt handler. To
313 //! register the NMI watchdog handler, use \ref IntRegister() to register the
314 //! handler for the \b INT_NMI_FAULT interrupt.
315 //!
316 //! \param pfnHandler is a pointer to the function to be called when the
317 //! watchdog timer interrupt occurs.
318 //!
319 //! \return None
320 //!
321 //! \sa \ref IntRegister() for important information about registering interrupt
322 //! handlers.
323 //
324 //*****************************************************************************
325 __STATIC_INLINE void
WatchdogIntRegister(void (* pfnHandler)(void))326 WatchdogIntRegister(void (*pfnHandler)(void))
327 {
328     // Register the interrupt handler.
329     IntRegister(INT_WDT_IRQ, pfnHandler);
330 
331     // Enable the watchdog timer interrupt.
332     IntEnable(INT_WDT_IRQ);
333 }
334 
335 //*****************************************************************************
336 //
337 //! \brief Unregisters an interrupt handler for the watchdog timer interrupt in the dynamic interrupt table.
338 //!
339 //! This function does the actual unregistering of the interrupt handler. This
340 //! function clears the handler to be called when a watchdog timer interrupt
341 //! occurs. This function also masks off the interrupt in the interrupt
342 //! controller so that the interrupt handler no longer is called.
343 //!
344 //! \note This function registers the standard watchdog interrupt handler. To
345 //! register the NMI watchdog handler, use \ref IntRegister() to register the
346 //! handler for the \b INT_NMI_FAULT interrupt.
347 //!
348 //! \return None
349 //!
350 //! \sa \ref IntRegister() for important information about registering interrupt
351 //! handlers.
352 //
353 //*****************************************************************************
354 __STATIC_INLINE void
WatchdogIntUnregister(void)355 WatchdogIntUnregister(void)
356 {
357     // Disable the interrupt.
358     IntDisable(INT_WDT_IRQ);
359 
360     // Unregister the interrupt handler.
361     IntUnregister(INT_WDT_IRQ);
362 }
363 
364 //*****************************************************************************
365 //
366 //! \brief Enables the watchdog timer.
367 //!
368 //! This function enables the watchdog timer interrupt by calling \ref WatchdogEnable().
369 //!
370 //! \return None
371 //!
372 //! \sa \ref WatchdogEnable()
373 //
374 //*****************************************************************************
375 __STATIC_INLINE void
WatchdogIntEnable(void)376 WatchdogIntEnable(void)
377 {
378     // Enable the Watchdog interrupt.
379     WatchdogEnable();
380 }
381 
382 //*****************************************************************************
383 //
384 //! \brief Gets the current watchdog timer interrupt status.
385 //!
386 //! This function returns the interrupt status for the watchdog timer module.
387 //!
388 //! \return Returns the interrupt status.
389 //! - 1 : Watchdog time-out has occurred.
390 //! - 0 : Watchdog time-out has not occurred.
391 //!
392 //! \sa \ref WatchdogIntClear();
393 //
394 //*****************************************************************************
395 __STATIC_INLINE uint32_t
WatchdogIntStatus(void)396 WatchdogIntStatus(void)
397 {
398     // Return either the interrupt status or the raw interrupt status as
399     // requested.
400     return(HWREG(WDT_BASE + WDT_O_RIS));
401 }
402 
403 //*****************************************************************************
404 //
405 //! \brief Clears the watchdog timer interrupt.
406 //!
407 //! The watchdog timer interrupt source is cleared, so that it no longer
408 //! asserts.
409 //!
410 //! \note Due to write buffers and synchronizers in the system it may take several
411 //! clock cycles from a register write clearing an event in a module and until the
412 //! event is actually cleared in the NVIC of the system CPU. It is recommended to
413 //! clear the event source early in the interrupt service routine (ISR) to allow
414 //! the event clear to propagate to the NVIC before returning from the ISR.
415 //! At the same time, an early event clear allows new events of the same type to be
416 //! pended instead of ignored if the event is cleared later in the ISR.
417 //! It is the responsibility of the programmer to make sure that enough time has passed
418 //! before returning from the ISR to avoid false re-triggering of the cleared event.
419 //! A simple, although not necessarily optimal, way of clearing an event before
420 //! returning from the ISR is:
421 //! -# Write to clear event (interrupt source). (buffered write)
422 //! -# Dummy read from the event source module. (making sure the write has propagated)
423 //! -# Wait two system CPU clock cycles (user code or two NOPs). (allowing cleared event to propagate through any synchronizers)
424 //!
425 //! \return None
426 //
427 //*****************************************************************************
428 __STATIC_INLINE void
WatchdogIntClear(void)429 WatchdogIntClear(void)
430 {
431     // Clear the interrupt source.
432     HWREG(WDT_BASE + WDT_O_ICR) = WATCHDOG_INT_TIMEOUT;
433 }
434 
435 //*****************************************************************************
436 //
437 //! \brief Sets the type of interrupt generated by the watchdog.
438 //!
439 //! This function sets the type of interrupt that is generated if the watchdog
440 //! timer expires.
441 //!
442 //! When configured to generate an NMI, the watchdog interrupt must still be
443 //! enabled with \ref WatchdogIntEnable(), and it must still be cleared inside the
444 //! NMI handler with \ref WatchdogIntClear().
445 //!
446 //! \param ui32Type is the type of interrupt to generate.
447 //! - \ref WATCHDOG_INT_TYPE_INT : Generate a standard interrupt (default).
448 //! - \ref WATCHDOG_INT_TYPE_NMI : Generate a non-maskable interrupt (NMI).
449 //!
450 //! \return None
451 //
452 //*****************************************************************************
453 __STATIC_INLINE void
WatchdogIntTypeSet(uint32_t ui32Type)454 WatchdogIntTypeSet(uint32_t ui32Type)
455 {
456     // Check the arguments.
457     ASSERT((ui32Type == WATCHDOG_INT_TYPE_INT) ||
458            (ui32Type == WATCHDOG_INT_TYPE_NMI));
459 
460     // Set the interrupt type.
461     HWREGBITW(WDT_BASE + WDT_O_CTL, WDT_CTL_INTTYPE_BITN) = (ui32Type == WATCHDOG_INT_TYPE_INT)? 0 : 1;
462 }
463 
464 //*****************************************************************************
465 //
466 //! \brief Enables stalling of the watchdog timer during debug events.
467 //!
468 //! This function allows the watchdog timer to stop counting when the processor
469 //! is stopped by the debugger. By doing so, the watchdog is prevented from
470 //! expiring and resetting the system (if reset is enabled). The watchdog instead expires
471 //! after the appropriate number of processor cycles have been executed while
472 //! debugging (or at the appropriate time after the processor has been
473 //! restarted).
474 //!
475 //! \return None
476 //
477 //*****************************************************************************
478 __STATIC_INLINE void
WatchdogStallEnable(void)479 WatchdogStallEnable(void)
480 {
481     // Enable timer stalling.
482     HWREGBITW(WDT_BASE + WDT_O_TEST, WDT_TEST_STALL_BITN) = 1;
483 }
484 
485 //*****************************************************************************
486 //
487 //! \brief Disables stalling of the watchdog timer during debug events.
488 //!
489 //! This function disables the debug mode stall of the watchdog timer. By
490 //! doing so, the watchdog timer continues to count regardless of the processor
491 //! debug state.
492 //!
493 //! \return None
494 //
495 //*****************************************************************************
496 __STATIC_INLINE void
WatchdogStallDisable(void)497 WatchdogStallDisable(void)
498 {
499     // Disable timer stalling.
500     HWREGBITW(WDT_BASE + WDT_O_TEST, WDT_TEST_STALL_BITN) = 0;
501 }
502 
503 //*****************************************************************************
504 //
505 // Mark the end of the C bindings section for C++ compilers.
506 //
507 //*****************************************************************************
508 #ifdef __cplusplus
509 }
510 #endif
511 
512 #endif // __WDT_H__
513 
514 //*****************************************************************************
515 //
516 //! Close the Doxygen group.
517 //! @}
518 //! @}
519 //
520 //*****************************************************************************
521