1 /*
2 * Copyright (c) 2015 Intel Corporation
3 * Copyright (c) 2018 Nordic Semiconductor
4 * Copyright (c) 2019 Centaur Analytics, Inc
5 * Copyright 2023 NXP
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/watchdog.h>
13 #include <zephyr/sys/printk.h>
14 #include <stdbool.h>
15
16 #define WDT_FEED_TRIES 5
17
18 /*
19 * To use this sample the devicetree's /aliases must have a 'watchdog0' property.
20 */
21 #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_window_watchdog)
22 #define WDT_MAX_WINDOW 100U
23 #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_wdt)
24 /* Nordic supports a callback, but it has 61.2 us to complete before
25 * the reset occurs, which is too short for this sample to do anything
26 * useful. Explicitly disallow use of the callback.
27 */
28 #define WDT_ALLOW_CALLBACK 0
29 #elif DT_HAS_COMPAT_STATUS_OKAY(raspberrypi_pico_watchdog)
30 #define WDT_ALLOW_CALLBACK 0
31 #elif DT_HAS_COMPAT_STATUS_OKAY(gd_gd32_wwdgt)
32 #define WDT_MAX_WINDOW 24U
33 #define WDT_MIN_WINDOW 18U
34 #define WDG_FEED_INTERVAL 12U
35 #elif DT_HAS_COMPAT_STATUS_OKAY(intel_tco_wdt)
36 #define WDT_ALLOW_CALLBACK 0
37 #define WDT_MAX_WINDOW 3000U
38 #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_fs26_wdog)
39 #define WDT_MAX_WINDOW 1024U
40 #define WDT_MIN_WINDOW 320U
41 #define WDT_OPT 0
42 #define WDG_FEED_INTERVAL (WDT_MIN_WINDOW + ((WDT_MAX_WINDOW - WDT_MIN_WINDOW) / 4))
43 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_ra_wdt)
44 #define WDT_ALLOW_CALLBACK 0
45 #elif DT_HAS_COMPAT_STATUS_OKAY(wch_iwdg)
46 #define WDT_ALLOW_CALLBACK 0
47 #define WDT_OPT 0
48 #endif
49
50 #ifndef WDT_ALLOW_CALLBACK
51 #define WDT_ALLOW_CALLBACK 1
52 #endif
53
54 #ifndef WDT_MAX_WINDOW
55 #define WDT_MAX_WINDOW 1000U
56 #endif
57
58 #ifndef WDT_MIN_WINDOW
59 #define WDT_MIN_WINDOW 0U
60 #endif
61
62 #ifndef WDG_FEED_INTERVAL
63 #define WDG_FEED_INTERVAL 50U
64 #endif
65
66 #ifndef WDT_OPT
67 #define WDT_OPT WDT_OPT_PAUSE_HALTED_BY_DBG
68 #endif
69
70 #if WDT_ALLOW_CALLBACK
wdt_callback(const struct device * wdt_dev,int channel_id)71 static void wdt_callback(const struct device *wdt_dev, int channel_id)
72 {
73 static bool handled_event;
74
75 if (handled_event) {
76 return;
77 }
78
79 wdt_feed(wdt_dev, channel_id);
80
81 printk("Handled things..ready to reset\n");
82 handled_event = true;
83 }
84 #endif /* WDT_ALLOW_CALLBACK */
85
main(void)86 int main(void)
87 {
88 int err;
89 int wdt_channel_id;
90 const struct device *const wdt = DEVICE_DT_GET(DT_ALIAS(watchdog0));
91
92 printk("Watchdog sample application\n");
93
94 if (!device_is_ready(wdt)) {
95 printk("%s: device not ready.\n", wdt->name);
96 return 0;
97 }
98
99 struct wdt_timeout_cfg wdt_config = {
100 /* Reset SoC when watchdog timer expires. */
101 .flags = WDT_FLAG_RESET_SOC,
102
103 /* Expire watchdog after max window */
104 .window.min = WDT_MIN_WINDOW,
105 .window.max = WDT_MAX_WINDOW,
106 };
107
108 #if WDT_ALLOW_CALLBACK
109 /* Set up watchdog callback. */
110 wdt_config.callback = wdt_callback;
111
112 printk("Attempting to test pre-reset callback\n");
113 #else /* WDT_ALLOW_CALLBACK */
114 printk("Callback in RESET_SOC disabled for this platform\n");
115 #endif /* WDT_ALLOW_CALLBACK */
116
117 wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
118 if (wdt_channel_id == -ENOTSUP) {
119 /* IWDG driver for STM32 doesn't support callback */
120 printk("Callback support rejected, continuing anyway\n");
121 wdt_config.callback = NULL;
122 wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
123 }
124 if (wdt_channel_id < 0) {
125 printk("Watchdog install error\n");
126 return 0;
127 }
128
129 err = wdt_setup(wdt, WDT_OPT);
130 if (err < 0) {
131 printk("Watchdog setup error\n");
132 return 0;
133 }
134
135 #if WDT_MIN_WINDOW != 0
136 /* Wait opening window. */
137 k_msleep(WDT_MIN_WINDOW);
138 #endif
139 /* Feeding watchdog. */
140 printk("Feeding watchdog %d times\n", WDT_FEED_TRIES);
141 for (int i = 0; i < WDT_FEED_TRIES; ++i) {
142 printk("Feeding watchdog...\n");
143 wdt_feed(wdt, wdt_channel_id);
144 k_sleep(K_MSEC(WDG_FEED_INTERVAL));
145 }
146
147 /* Waiting for the SoC reset. */
148 printk("Waiting for reset...\n");
149 while (1) {
150 k_yield();
151 }
152 return 0;
153 }
154