Utilizing Watchdog Functionality

The goal of the document is to illustrate how to use watchdog of SP7350.

 

Table of Contents

1. Checking Watchdog Device Existence

1.1 Checking Watchdog Devices in /dev/

To verify the existence of watchdog devices, execute the command:

ls /dev/watchdog*

Typically, two watchdog devices are present, as illustrated below:

~ # ls -l /dev/watchdog* crw-rw---- 1 root root 10, 130 Jan 1 00:00 /dev/watchdog crw-rw---- 1 root root 252, 0 Jan 1 00:00 /dev/watchdog0 ~ #

If watchdog devices are not found, ensure to:

  • Verify if the watchdog node in dts is not set as "disabled".

  • Confirm the watchdog driver is enabled.

1.2 Verifying Watchdog Node Status in dts

Refer to the watchdog node in DTS:

&watchdog { timeout-sec = <10>; };

1.3 Ensuring Watchdog Driver Enablement

To verify the watchdog driver's status, navigate to the project's top directory and execute:

make kconfig

In the kernel configuration menu, locate "Device Drivers > Watchdog Timer Support > Sunplus watchdog support" and ensure "Sunplus watchdog support" is enabled. Refer to the Linux kernel configuration menu below:

2. Implementing Watchdog Setup and Feeding Application

Refer to the following C example code demonstrating watchdog setup and feeding application. This application configures, initiates, and feeds the watchdog every 12 seconds. The watchdog on SP7350 has no maximum timeout limit.

watchdog.c

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <pthread.h> #include <sys/ioctl.h> #define WATCHDOG_IOCTL_BASE 'W' #define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int) #define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int) #define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int) #define WDIOS_DISABLECARD 1 #define WDIOS_ENABLECARD 2 #define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int) int ret; int wd_fd; volatile int wd_feed_time = 12; // Feed watchdog every 12 second by default. int wd_timeout = 15; // Timeout time of watchdog. Reset event occurs if watchdog is not fed within this time. /* a thread feed dog */ void *feedwdt_thd() { while(1) { // Feed (reset) watchdog. ret = ioctl(wd_fd, WDIOC_KEEPALIVE, 0); if (ret != 0) { printf("Feed watchdog failed. \n"); close(wd_fd); } else { printf("Feed watchdog every %d seconds.\n", wd_feed_time); } sleep(wd_feed_time); } } /* a thread read counter and print the value */ void *readwdt_thd() { int arg; int i; while(1) { ret = ioctl(wd_fd, WDIOC_GETTIMELEFT, &arg); if (ret != 0) { printf("get data failed. \n"); } printf("cnt value is 0x%x\n", arg); usleep(200000); } } int main(void) { pthread_t wd_feed_thread; pthread_t wd_read_thread; int wd_option; char str[10]; int num = 0; char* ptr = str; // Get file handle of watchdog device. wd_fd = open("/dev/watchdog0", O_WRONLY); if (wd_fd == -1) { perror("watchdog"); exit(EXIT_FAILURE); } // Enable wacthdog. wd_option = WDIOS_ENABLECARD; ret = ioctl(wd_fd, WDIOC_SETOPTIONS, &wd_option); if (ret != 0) { printf("Failed to start watchdog!\n"); close(wd_fd); return -1; } // Setup timeout time. ret = ioctl(wd_fd, WDIOC_SETTIMEOUT, &wd_timeout); if (ret != 0) { printf("Failed to set timeout time!n"); close(wd_fd); return -1; } // Create a thread for feeding watchdog. ret = pthread_create(&wd_feed_thread, NULL, feedwdt_thd, NULL); if (ret < 0) printf("Failed to create feeddog thread!\n"); #if 0 // Create a thread for reading and printing counter value. ret = pthread_create(&wd_read_thread, NULL, readwdt_thd, NULL); if (ret < 0) printf("Failed to create read counter thread!\n"); #endif while(1) { printf("Press 'e' to disable watchdog and exit.\n"); printf("Enter a number for new feed time (current feed time is %d seconds, timeout time is %d seconds):\n", wd_feed_time, wd_timeout); scanf("%s", str); //printf("debug why feedtime invarible %s\n",str); if (!strcmp(str,"e")) { wd_option = WDIOS_DISABLECARD; ret = ioctl(wd_fd, WDIOC_SETOPTIONS, &wd_option); if (ret != 0) { printf("Failed to stop watchdog!\n"); } printf("Disabled watchdog!\n"); close(wd_fd); break; } if (strspn(str, "0123456789") == strlen(str)) { // Get new feed time. num = atoi(str); if (num > 0) { wd_feed_time = num; } else { printf("Feed time can not be zero!\n"); } } else { printf("Invalid feed time!\n"); } } return 0; }

Makefile (You need to modify CC path):

Â