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