Skip to content

Commit 2857c2e

Browse files
martinjaegercarlescufi
authored andcommitted
samples: subsys: task_wdt: add sample application
The sample demonstrates how to use the task watchdog in different threads. Signed-off-by: Martin Jäger <[email protected]>
1 parent 1aaf508 commit 2857c2e

File tree

5 files changed

+199
-0
lines changed

5 files changed

+199
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.13.1)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(task_wdt)
6+
7+
target_sources(app PRIVATE src/main.c)

samples/subsys/task_wdt/README.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
.. _task_wdt_sample:
2+
3+
Task Watchdog Sample
4+
####################
5+
6+
Overview
7+
********
8+
9+
This sample allows to test the task watchdog subsystem.
10+
11+
Building and Running
12+
********************
13+
14+
It should be possible to build and run the task watchdog sample on almost any
15+
board. If a hardware watchdog is defined in the devicetree, it is used as a
16+
fallback. Otherwise the task watchdog will run independently.
17+
18+
Building and Running for ST Nucleo L073RZ
19+
=========================================
20+
The sample can be built and executed for the
21+
:ref:`nucleo_l073rz_board` as follows:
22+
23+
.. zephyr-app-commands::
24+
:zephyr-app: samples/subsys/task_wdt
25+
:board: nucleo_l073rz
26+
:goals: build flash
27+
:compact:
28+
29+
For other boards just replace the board name.
30+
31+
Sample output
32+
=============
33+
34+
The following output is printed and continuously repeated (after each
35+
reset):
36+
37+
.. code-block:: console
38+
39+
Task watchdog sample application.
40+
Main thread still alive...
41+
Control thread started.
42+
Main thread still alive...
43+
Main thread still alive...
44+
Main thread still alive...
45+
Control thread getting stuck...
46+
Main thread still alive...
47+
Task watchdog channel 1 callback, thread: control
48+
Resetting device...

samples/subsys/task_wdt/prj.conf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CONFIG_LOG=y
2+
3+
CONFIG_WATCHDOG=y
4+
CONFIG_WDT_LOG_LEVEL_DBG=y
5+
CONFIG_WDT_DISABLE_AT_BOOT=y
6+
7+
CONFIG_TASK_WDT=y
8+
CONFIG_TASK_WDT_MIN_TIMEOUT=50
9+
10+
CONFIG_THREAD_NAME=y

samples/subsys/task_wdt/sample.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
sample:
2+
name: Task Watchdog Subsytem Sample
3+
tests:
4+
sample.subsys.task_wdt:
5+
tags: subsys
6+
harness: console
7+
harness_config:
8+
type: multi_line
9+
ordered: true
10+
regex:
11+
- "Task watchdog sample application."
12+
- "Control thread started."
13+
- "Main thread still alive..."
14+
- "Control thread getting stuck..."
15+
- "Task watchdog channel 1 callback, thread: control"
16+
- "Resetting device...(.*)"
17+
- "Task watchdog sample application."
18+
depends_on: watchdog
19+
integration_platforms:
20+
- nucleo_g474re

samples/subsys/task_wdt/src/main.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright (c) 2020 Libre Solar Technologies GmbH
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr.h>
8+
#include <device.h>
9+
#include <drivers/watchdog.h>
10+
#include <power/reboot.h>
11+
#include <task_wdt/task_wdt.h>
12+
#include <sys/printk.h>
13+
#include <stdbool.h>
14+
15+
/*
16+
* To use this sample, either the devicetree's /aliases must have a
17+
* 'watchdog0' property, or one of the following watchdog compatibles
18+
* must have an enabled node.
19+
*/
20+
#if DT_NODE_HAS_STATUS(DT_ALIAS(watchdog0), okay)
21+
#define WDT_NODE DT_ALIAS(watchdog0)
22+
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_window_watchdog)
23+
#define WDT_NODE DT_INST(0, st_stm32_window_watchdog)
24+
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_watchdog)
25+
#define WDT_NODE DT_INST(0, st_stm32_watchdog)
26+
#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_watchdog)
27+
#define WDT_NODE DT_INST(0, nordic_nrf_watchdog)
28+
#elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_watchdog)
29+
#define WDT_NODE DT_INST(0, espressif_esp32_watchdog)
30+
#elif DT_HAS_COMPAT_STATUS_OKAY(silabs_gecko_wdog)
31+
#define WDT_NODE DT_INST(0, silabs_gecko_wdog)
32+
#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_wdog32)
33+
#define WDT_NODE DT_INST(0, nxp_kinetis_wdog32)
34+
#elif DT_HAS_COMPAT_STATUS_OKAY(microchip_xec_watchdog)
35+
#define WDT_NODE DT_INST(0, microchip_xec_watchdog)
36+
#endif
37+
38+
/*
39+
* If the devicetree has a watchdog node, get its label property. Otherwise
40+
* the task watchdog will be used without a hardware watchdog fallback.
41+
*/
42+
#ifdef WDT_NODE
43+
#define WDT_DEV_NAME DT_LABEL(WDT_NODE)
44+
#endif
45+
46+
static void task_wdt_callback(int channel_id, void *user_data)
47+
{
48+
printk("Task watchdog channel %d callback, thread: %s\n",
49+
channel_id, k_thread_name_get((k_tid_t)user_data));
50+
51+
/*
52+
* If the issue could be resolved, call task_wdt_feed(channel_id) here
53+
* to continue operation.
54+
*
55+
* Otherwise we can perform some cleanup and reset the device.
56+
*/
57+
58+
printk("Resetting device...\n");
59+
60+
sys_reboot(SYS_REBOOT_COLD);
61+
}
62+
63+
void main(void)
64+
{
65+
#ifdef WDT_DEV_NAME
66+
const struct device *hw_wdt_dev = device_get_binding(WDT_DEV_NAME);
67+
#else
68+
const struct device *hw_wdt_dev = NULL;
69+
#endif
70+
71+
printk("Task watchdog sample application.\n");
72+
73+
task_wdt_init(hw_wdt_dev);
74+
75+
/* passing NULL instead of callback to trigger system reset */
76+
int task_wdt_id = task_wdt_add(1100U, NULL, NULL);
77+
78+
while (true) {
79+
printk("Main thread still alive...\n");
80+
task_wdt_feed(task_wdt_id);
81+
k_sleep(K_MSEC(1000));
82+
}
83+
}
84+
85+
/*
86+
* This high-priority thread needs a tight timing
87+
*/
88+
void control_thread(void)
89+
{
90+
int task_wdt_id;
91+
int count = 0;
92+
93+
printk("Control thread started.\n");
94+
95+
/*
96+
* Add a new task watchdog channel with custom callback function and
97+
* the current thread ID as user data.
98+
*/
99+
task_wdt_id = task_wdt_add(100U, task_wdt_callback,
100+
(void *)k_current_get());
101+
102+
while (true) {
103+
if (count == 50) {
104+
printk("Control thread getting stuck...\n");
105+
k_sleep(K_FOREVER);
106+
}
107+
108+
task_wdt_feed(task_wdt_id);
109+
k_sleep(K_MSEC(50));
110+
count++;
111+
}
112+
}
113+
114+
K_THREAD_DEFINE(control, 1024, control_thread, NULL, NULL, NULL, -1, 0, 1000);

0 commit comments

Comments
 (0)