1 /*
2 * Copyright (c) 2025 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(wdt_vars, LOG_LEVEL_INF);
9
10 #include <zephyr/kernel.h>
11 #include <zephyr/cache.h>
12 #include <zephyr/drivers/watchdog.h>
13
14 #define WDT_WINDOW_MAX (500)
15
16 /* Watchdog related variables */
17 static const struct device *const my_wdt_device = DEVICE_DT_GET(DT_ALIAS(watchdog0));
18 static struct wdt_timeout_cfg m_cfg_wdt0;
19
20 /* No init section will contain WDT_HAS_FIRED if watchdog has fired */
21 #define WDT_HAS_FIRED (12345678U)
22 #define TEST_VALUE (2U)
23
24 #define NOINIT_SECTION ".noinit.test_wdt"
25 static volatile uint32_t wdt_status __attribute__((section(NOINIT_SECTION)));
26
27 /* Global variables to verify */
28 static int global_tmp_0;
29 static int global_tmp_1 = TEST_VALUE;
30
31
wdt_int_cb(const struct device * wdt_dev,int channel_id)32 static void wdt_int_cb(const struct device *wdt_dev, int channel_id)
33 {
34 ARG_UNUSED(wdt_dev);
35 ARG_UNUSED(channel_id);
36 wdt_status = WDT_HAS_FIRED;
37
38 /* Flush cache as reboot may invalidate all lines. */
39 sys_cache_data_flush_range((void *) &wdt_status, sizeof(wdt_status));
40 }
41
main(void)42 int main(void)
43 {
44 int ret;
45 static int tmp_0;
46 static int tmp_1 = TEST_VALUE;
47
48 LOG_INF("wdt_variables test on %s", CONFIG_BOARD_TARGET);
49
50 global_tmp_0++;
51 global_tmp_1++;
52 tmp_0++;
53 tmp_1++;
54
55 LOG_DBG("global_tmp_0 = %d", global_tmp_0);
56 LOG_DBG("global_tmp_1 = %d", global_tmp_1);
57 LOG_DBG("tmp_0 = %d", tmp_0);
58 LOG_DBG("tmp_1 = %d", tmp_1);
59
60 /* When watchdog fires, variable wdt_status is set to the value of WDT_HAS_FIRED
61 * in WDT callback wdt_int_cb(). Then, target is reset.
62 * Check value of wdt_status to prevent reset loop.
63 */
64 if (wdt_status != WDT_HAS_FIRED) {
65
66 LOG_INF("Reset wasn't due to watchdog.");
67
68 if (!device_is_ready(my_wdt_device)) {
69 LOG_ERR("WDT device %s is not ready", my_wdt_device->name);
70 return 1;
71 }
72
73 /* Configure Watchdog */
74 m_cfg_wdt0.callback = wdt_int_cb;
75 m_cfg_wdt0.flags = WDT_FLAG_RESET_SOC;
76 m_cfg_wdt0.window.min = 0U;
77 m_cfg_wdt0.window.max = WDT_WINDOW_MAX;
78 ret = wdt_install_timeout(my_wdt_device, &m_cfg_wdt0);
79 if (ret < 0) {
80 LOG_ERR("wdt_install_timeout() returned %d", ret);
81 return 1;
82 }
83
84 /* Start Watchdog */
85 ret = wdt_setup(my_wdt_device, WDT_OPT_PAUSE_HALTED_BY_DBG);
86 if (ret < 0) {
87 LOG_ERR("wdt_setup() returned %d", ret);
88 return 1;
89 }
90
91 LOG_INF("Watchdog shall fire in ~%u miliseconds", WDT_WINDOW_MAX);
92 k_sleep(K_FOREVER);
93 } else {
94 bool test_passing = true;
95
96 LOG_INF("Watchod has fired");
97
98 if (global_tmp_0 != 1) {
99 LOG_ERR("global_tmp_0 is %d instead of 1", global_tmp_0);
100 test_passing = false;
101 }
102
103 if (global_tmp_1 != (TEST_VALUE + 1)) {
104 LOG_ERR("global_tmp_1 is %d instead of %d", global_tmp_1, TEST_VALUE + 1);
105 test_passing = false;
106 }
107
108 if (tmp_0 != 1) {
109 LOG_ERR("tmp_0 is %d instead of 1", tmp_0);
110 test_passing = false;
111 }
112
113 if (tmp_1 != (TEST_VALUE + 1)) {
114 LOG_ERR("tmp_1 is %d instead of %d", tmp_1, TEST_VALUE + 1);
115 test_passing = false;
116 }
117
118 /* Cleanup */
119 wdt_status = 0;
120 sys_cache_data_flush_range((void *) &wdt_status, sizeof(wdt_status));
121
122 if (test_passing) {
123 LOG_INF("Test completed successfully");
124 } else {
125 LOG_INF("Test failed");
126 }
127 }
128
129 return 0;
130 }
131