The goal of the document is to illustrate how to enable and use watchdog of SP7021.
As an embedded system, to minimize the use of system resources, SP7021 Linux only enables necessary kernel features by default. Watchdog of SP7021 is not enabled by default. To enable watchdog, first, you need to download source files of SP7021 from GitHub. Second, you need to run kernel menuconfig to enable watchdog drivers. Third, you need to re-build SP7021 Linux images. Finally, you need to build and run an application which activates and feeds watchdog periodically. Please follow the following steps.
...
Source files of SP7021 can be downloaded from GitHub or Yocto server of SP7021. Refer to https://github.com/sunplus-plus1/SP7021 or 2. HOW TO GET SOURCE FILE AND PACKAGE.
2. Enable watchdog driver
Run make kconfig command in project top folder, or go to linux/kernel folder and run make menuconfig command. When “Linux/arm 5.4.35 Kernel Configuration” menu pops up, please use arrow key to move cursor down to “Device Drivers”. Refer to screenshot below, cursor is moved to “Device Drivers”:
...
Press <Enter> to enter “Device Driver” sub-menu. Next, move cursor down to “Watchdog Timer Support” and press <Space> or “y” to enable it. Refer to screenshot below, “Watchdog Timer Support” is enabled:
...
Next, press <Enter> to enter “Watchdog Timer Support” sub-menu. Next, move cursor down to “Sunplus to “Device Drivers > Watchdog Timer Support > Sunplus watchdog support” and press <Space> or “y” to enable it. Refer to screenshot below, “Sunplus watchdog support” is enabled:
...
Boot system with the built image. You can find watchdog device devices in directory /dev by using ls -l /dev command:
Code Block |
---|
~ # 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 ~ # |
5. Run watchdog setup and feeding application
Refer to the following C example code which setups and of watchdog setup and feeding application. The application setups, starts, and then feeds watchdog every 10 12 seconds. Note that the maximum feed The maximum time-out time of watchdog of SP7021 is about 11 seconds.have no limit.
watchdog.c
Code Block | ||
---|---|---|
| ||
#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, 210, int) int ret; int wd_fd; volatile int wd_feed_time = 8; void* 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("FailedFeed towatchdog feedfailed. watchdog!\n"); close(wd_fd); } else { printf("Feed watchdog every %d seconds.\n", wd_feed_time); } sleep( } sleep(wd_feed_time); } } /* a int main(void) { pthread_t watchdogThd; int timeout = 10; int option_en = WDIOS_ENABLECARD; int option_dis = WDIOS_DISABLECARD; 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_en); 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(&watchdogThdwd_feed_thread, NULL, feedwdt_thd, NULL); if (ret<ret < 0) printf("Failed to create feeddog thread!\n"); #if 0 while (1) { printf("If you want to quit, please press 'e' character!\n"); printf("If you want to modify the feeddog time, please input the val (default 8, timeout is 10)!\n"); // 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_dis); if (ret != 0) { printf("Failed to stop watchdog!\n"); } } printf("StoppedDisabled watchdog!\n"); close( close(wd_fd); break; } break; } if (strspn(str, "0123456789") == strlen(str)) { while (*ptr) { num *= 10; num += *ptr - '0'; ptr++; } // 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 timeoutfeed time!\n"); } } } return 0; } |
Reference Makefile (You need to modify CC path):
Code Block |
---|
CC=/home/your_home_dir/youyour_sp7021_project_folder/crossgcc/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc LDFLAGS=-lpthread .PHONY: all clean all: watchdog watchdog: watchdog.c $(CC) $< -o $@ $(LDFLAGS) clean: rm -f watchdog |
...