User manual

LwWDG library is very simple and easy to use. LwWDG was designed to implement software watchdog functionality, primarily used in the operating systems.

Each task in the system defines its very own Watchdog structure, and is responsible to periodically call reload function, while one of the tasks, (it can be) called master task checks the processing function, and reloads hardware watchdog, if everything is fine.

When one of the software watchdogs isn’t reloaded within maximum timeout window, main task is not supposed to reload hardware timer anymore. As a consequence, hardware watchdog will reset the system.

Note

This library is designed for operating system, where operations are splitted in the tasks. To ensure stable operation, each task should have a monitoring system.

Since microcontrollers typical utilize single independent watchdog, such solution must be implemented as a combination of hardware and software components.

Platform migration

Library requires atomicity in the processing function, and a milliseconds time source. These should be implemented as macros in the configuration file. Checkout the configuration window or follow to example mentioned below.

Example

A simple example to illustrate functionality.

WIN32 example code
 1#include "lwwdg/lwwdg.h"
 2#include "windows.h"
 3#include <stdio.h>
 4#include <stdlib.h>
 5
 6HANDLE lwwdg_mutex;                        /* Mutex to simulate interrupt lock */
 7static LARGE_INTEGER freq, sys_start_time; /* Milliseconds time variable */
 8
 9/**
10 * \brief           Get current tick in ms from start of program
11 * \return          uint32_t: Tick in ms
12 */
13uint32_t
14sys_get_tick(void) {
15    LONGLONG ret;
16    LARGE_INTEGER now;
17
18    QueryPerformanceFrequency(&freq);
19    QueryPerformanceCounter(&now);
20    ret = now.QuadPart - sys_start_time.QuadPart;
21    return (uint32_t)((ret * 1000) / freq.QuadPart);
22}
23
24/* Task 1 */
25static void
26task1(void* arg) {
27    static lwwdg_wdg_t wdg;
28    (void)arg;
29
30    printf("%8u: Task 1 started...\r\n", (unsigned)sys_get_tick());
31    lwwdg_add(&wdg, 3000);
32    lwwdg_set_name(&wdg, "task_1_wdg");
33    while (1) {
34        /* Periodic reloads... */
35        lwwdg_reload(&wdg);
36    }
37}
38
39/* Task 1 */
40static void
41task2(void* arg) {
42    static lwwdg_wdg_t wdg;
43    (void)arg;
44
45    printf("%8u: Task 2 started...\r\n", (unsigned)sys_get_tick());
46    lwwdg_add(&wdg, 5000);
47    lwwdg_set_name(&wdg, "task_2_wdg");
48    while (1) {
49        /* No reload in this task -> consider it failed to run properly */
50        Sleep(1000);
51    }
52}
53
54/**
55 * \brief           Example main function
56 */
57void
58example_win32(void) {
59    DWORD id;
60
61    QueryPerformanceFrequency(&freq);
62    QueryPerformanceCounter(&sys_start_time);
63
64    /* Create lock for lwwdg */
65    lwwdg_mutex = CreateMutex(NULL, 0, NULL);
66    lwwdg_init(); /* Init library */
67
68    /* Start other tasks */
69    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)task1, NULL, 0, &id);
70    CreateThread(0, 0, (LPTHREAD_START_ROUTINE)task2, NULL, 0, &id);
71
72    /* Main task... */
73    while (1) {
74        /* Check if all tasks are OK */
75        if (lwwdg_process()) {
76            printf("%8u: Refreshing hardware watchdog...\r\n", (unsigned)sys_get_tick());
77            /* TODO: This is where you should reload hardware watchdog */
78        } else {
79            printf("%8u: At least one task is out of window -> HW watchdog should not be reloaded anymore\r\n",
80                   (unsigned)sys_get_tick());
81            break;
82        }
83        Sleep(500); /* Make some sleep to offload messages in the WIN32 example */
84    }
85    printf("List of expired watchdogs\r\n");
86    lwwdg_print_expired();
87    printf("Example completed - a hardware should reset the system now...\r\n");
88}

A corresponding options file, tested for WIN32.

WIN32 LwWDG options file
 1/**
 2 * \file            lwwdg_opts_template.h
 3 * \brief           LwWDG configuration file
 4 */
 5
 6/*
 7 * Copyright (c) 2024 Tilen MAJERLE
 8 *
 9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without restriction,
12 * including without limitation the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be
18 * included in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23 * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 * OTHER DEALINGS IN THE SOFTWARE.
28 *
29 * This file is part of LWWDG - Lightweight watchdog for RTOS in embedded systems.
30 *
31 * Author:          Tilen MAJERLE <tilen@majerle.eu>
32 * Version:         v1.1.2
33 */
34#ifndef LWWDG_HDR_OPTS_H
35#define LWWDG_HDR_OPTS_H
36
37#include <stdio.h>
38
39/* Win32 port */
40#include "windows.h"
41extern uint32_t sys_get_tick(void); /* Milliseconds tick is available externally */
42extern HANDLE lwwdg_mutex;          /* Mutex is defined and initialized externally */
43
44#define LWWDG_CRITICAL_SECTION_DEFINE /* Nothing to do here... */
45#define LWWDG_CRITICAL_SECTION_LOCK()                                                                                  \
46    do {                                                                                                               \
47        WaitForSingleObject(lwwdg_mutex, INFINITE);                                                                    \
48    } while (0)
49#define LWWDG_CRITICAL_SECTION_UNLOCK()     ReleaseMutex(lwwdg_mutex)
50#define LWWDG_GET_TIME()                    sys_get_tick()
51
52#define LWWDG_CFG_ENABLE_WDG_NAME           1
53#define LWWDG_CFG_WDG_NAME_ERR_DEBUG(_wdg_) printf("Watchdog %s failed to reload in time!\r\n", (_wdg_))
54
55#endif /* LWWDG_HDR_OPTS_H */