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 <martin@libre.solar>
This commit is contained in:
parent
1aaf508bde
commit
2857c2e984
5 changed files with 199 additions and 0 deletions
7
samples/subsys/task_wdt/CMakeLists.txt
Normal file
7
samples/subsys/task_wdt/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(task_wdt)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
48
samples/subsys/task_wdt/README.rst
Normal file
48
samples/subsys/task_wdt/README.rst
Normal file
|
@ -0,0 +1,48 @@
|
|||
.. _task_wdt_sample:
|
||||
|
||||
Task Watchdog Sample
|
||||
####################
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This sample allows to test the task watchdog subsystem.
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
It should be possible to build and run the task watchdog sample on almost any
|
||||
board. If a hardware watchdog is defined in the devicetree, it is used as a
|
||||
fallback. Otherwise the task watchdog will run independently.
|
||||
|
||||
Building and Running for ST Nucleo L073RZ
|
||||
=========================================
|
||||
The sample can be built and executed for the
|
||||
:ref:`nucleo_l073rz_board` as follows:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/subsys/task_wdt
|
||||
:board: nucleo_l073rz
|
||||
:goals: build flash
|
||||
:compact:
|
||||
|
||||
For other boards just replace the board name.
|
||||
|
||||
Sample output
|
||||
=============
|
||||
|
||||
The following output is printed and continuously repeated (after each
|
||||
reset):
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
Task watchdog sample application.
|
||||
Main thread still alive...
|
||||
Control thread started.
|
||||
Main thread still alive...
|
||||
Main thread still alive...
|
||||
Main thread still alive...
|
||||
Control thread getting stuck...
|
||||
Main thread still alive...
|
||||
Task watchdog channel 1 callback, thread: control
|
||||
Resetting device...
|
10
samples/subsys/task_wdt/prj.conf
Normal file
10
samples/subsys/task_wdt/prj.conf
Normal file
|
@ -0,0 +1,10 @@
|
|||
CONFIG_LOG=y
|
||||
|
||||
CONFIG_WATCHDOG=y
|
||||
CONFIG_WDT_LOG_LEVEL_DBG=y
|
||||
CONFIG_WDT_DISABLE_AT_BOOT=y
|
||||
|
||||
CONFIG_TASK_WDT=y
|
||||
CONFIG_TASK_WDT_MIN_TIMEOUT=50
|
||||
|
||||
CONFIG_THREAD_NAME=y
|
20
samples/subsys/task_wdt/sample.yaml
Normal file
20
samples/subsys/task_wdt/sample.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
sample:
|
||||
name: Task Watchdog Subsytem Sample
|
||||
tests:
|
||||
sample.subsys.task_wdt:
|
||||
tags: subsys
|
||||
harness: console
|
||||
harness_config:
|
||||
type: multi_line
|
||||
ordered: true
|
||||
regex:
|
||||
- "Task watchdog sample application."
|
||||
- "Control thread started."
|
||||
- "Main thread still alive..."
|
||||
- "Control thread getting stuck..."
|
||||
- "Task watchdog channel 1 callback, thread: control"
|
||||
- "Resetting device...(.*)"
|
||||
- "Task watchdog sample application."
|
||||
depends_on: watchdog
|
||||
integration_platforms:
|
||||
- nucleo_g474re
|
114
samples/subsys/task_wdt/src/main.c
Normal file
114
samples/subsys/task_wdt/src/main.c
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Libre Solar Technologies GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <drivers/watchdog.h>
|
||||
#include <power/reboot.h>
|
||||
#include <task_wdt/task_wdt.h>
|
||||
#include <sys/printk.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* To use this sample, either the devicetree's /aliases must have a
|
||||
* 'watchdog0' property, or one of the following watchdog compatibles
|
||||
* must have an enabled node.
|
||||
*/
|
||||
#if DT_NODE_HAS_STATUS(DT_ALIAS(watchdog0), okay)
|
||||
#define WDT_NODE DT_ALIAS(watchdog0)
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_window_watchdog)
|
||||
#define WDT_NODE DT_INST(0, st_stm32_window_watchdog)
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_watchdog)
|
||||
#define WDT_NODE DT_INST(0, st_stm32_watchdog)
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_watchdog)
|
||||
#define WDT_NODE DT_INST(0, nordic_nrf_watchdog)
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_watchdog)
|
||||
#define WDT_NODE DT_INST(0, espressif_esp32_watchdog)
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(silabs_gecko_wdog)
|
||||
#define WDT_NODE DT_INST(0, silabs_gecko_wdog)
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_wdog32)
|
||||
#define WDT_NODE DT_INST(0, nxp_kinetis_wdog32)
|
||||
#elif DT_HAS_COMPAT_STATUS_OKAY(microchip_xec_watchdog)
|
||||
#define WDT_NODE DT_INST(0, microchip_xec_watchdog)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the devicetree has a watchdog node, get its label property. Otherwise
|
||||
* the task watchdog will be used without a hardware watchdog fallback.
|
||||
*/
|
||||
#ifdef WDT_NODE
|
||||
#define WDT_DEV_NAME DT_LABEL(WDT_NODE)
|
||||
#endif
|
||||
|
||||
static void task_wdt_callback(int channel_id, void *user_data)
|
||||
{
|
||||
printk("Task watchdog channel %d callback, thread: %s\n",
|
||||
channel_id, k_thread_name_get((k_tid_t)user_data));
|
||||
|
||||
/*
|
||||
* If the issue could be resolved, call task_wdt_feed(channel_id) here
|
||||
* to continue operation.
|
||||
*
|
||||
* Otherwise we can perform some cleanup and reset the device.
|
||||
*/
|
||||
|
||||
printk("Resetting device...\n");
|
||||
|
||||
sys_reboot(SYS_REBOOT_COLD);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
#ifdef WDT_DEV_NAME
|
||||
const struct device *hw_wdt_dev = device_get_binding(WDT_DEV_NAME);
|
||||
#else
|
||||
const struct device *hw_wdt_dev = NULL;
|
||||
#endif
|
||||
|
||||
printk("Task watchdog sample application.\n");
|
||||
|
||||
task_wdt_init(hw_wdt_dev);
|
||||
|
||||
/* passing NULL instead of callback to trigger system reset */
|
||||
int task_wdt_id = task_wdt_add(1100U, NULL, NULL);
|
||||
|
||||
while (true) {
|
||||
printk("Main thread still alive...\n");
|
||||
task_wdt_feed(task_wdt_id);
|
||||
k_sleep(K_MSEC(1000));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This high-priority thread needs a tight timing
|
||||
*/
|
||||
void control_thread(void)
|
||||
{
|
||||
int task_wdt_id;
|
||||
int count = 0;
|
||||
|
||||
printk("Control thread started.\n");
|
||||
|
||||
/*
|
||||
* Add a new task watchdog channel with custom callback function and
|
||||
* the current thread ID as user data.
|
||||
*/
|
||||
task_wdt_id = task_wdt_add(100U, task_wdt_callback,
|
||||
(void *)k_current_get());
|
||||
|
||||
while (true) {
|
||||
if (count == 50) {
|
||||
printk("Control thread getting stuck...\n");
|
||||
k_sleep(K_FOREVER);
|
||||
}
|
||||
|
||||
task_wdt_feed(task_wdt_id);
|
||||
k_sleep(K_MSEC(50));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
K_THREAD_DEFINE(control, 1024, control_thread, NULL, NULL, NULL, -1, 0, 1000);
|
Loading…
Add table
Add a link
Reference in a new issue