Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

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

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):

CC=/home/your_home_dir/your_sp7350_project_folder/crossgcc/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc
LDFLAGS=-lpthread

.PHONY: all clean
all: watchdog

watchdog: watchdog.c
	$(CC) $< -o $@ $(LDFLAGS)

clean:
	rm -f watchdog

 

  • No labels