Can't run NVIDIA's example watchdog user space code on Jetson TK1. Need to compile kernel?

I’m trying to follow the instructions in the “NVIDIA Tegra Linux Driver Package Development Guide” for enabling the watchdog via the “To enable WDT0 from user space” section on Page 74. I’m running L4T 21.4 and /dev/watchdog0 is present.

It’s unclear to me… Do I need to recompile the kernel and flash it? I don’t understand the instructions in the guide:

  1. Go to the kernel configuration file:
    arch/arm/configs/tegra12_defconfig
  2. Add the following line under CONFIG_WATCHDOG_NOWAYOUT=y:
    CONFIG_TEGRA_WATCHDOG=y

If I have to recompile the kernel under this method, how is this notably different from the instructions in the “To enable WDT0 from the Linux kernel”, which state:

  1. Go to the kernel configuration file:
    arch/arm/configs/tegra12_defconfig
  2. Add the following 2 lines under CONFIG_WATCHDOG_NOWAYOUT=y:
    CONFIG_TEGRA_WATCHDOG=y
    CONFIG_TEGRA_WATCHDOG_ENABLE_ON_PROBE=y

I’ve tried the code below on my current platform. It compiles fine, but if fails to open the watchdog device: “Open watchdog device failed!”

Here’s my code, which is basically identical to that in the manual except I have the #includes and I also try to close the watchdog after kicking it once.

// watchdogtest.cpp

#include <stdio.h>
#include <fcntl.h> // for watchdog timer
#include <unistd.h> // needed only if close() is used to close watchdog timer
#include <sys/ioctl.h> // for watchdog timer
#include <linux/watchdog.h> // for watchdog timer

int main() {

int fd, ret;
int timeout = 0;

/* open WDT0 device (WDT0 enables itself automatically) */
fd = open("/dev/watchdog0", O_RDWR);
if (fd<0) {
    fprintf(stderr, "Open watchdog device failed!\n");
    return -1;
}

/* WDT0 is counting now,check the default timeout value */
ret = ioctl(fd, WDIOC_GETTIMEOUT, &timeout);
if(ret) {
    fprintf(stderr, "Get watchdog timeout value failed!\n");
    return -1;
}
fprintf(stdout, "Watchdog timeout value: %d\n", timeout);

/* set new timeout value 60s */
/* Note the value should be within [5, 1000] */
timeout = 60;
ret = ioctl(fd, WDIOC_SETTIMEOUT, &timeout);
if(ret) {
    fprintf(stderr, "Set watchdog timeout value failed!\n");
    return -1;
}
fprintf(stdout, "New watchdog timeout value: %d\n", timeout);

/*Kick WDT0, this should be running periodically */
ret = ioctl(fd, WDIOC_KEEPALIVE, NULL);
if(ret) {
    fprintf(stderr, "Kick watchdog failed!\n");
    return -1;
}

/* close WDT0 device */
close(fd);
if (ret<0) {
    fprintf(stderr, "Failed to close watchdog device.");
    return -1;
}

return 0;

}

I haven’t set up any watchdog programs, but it’s fairly simple to demo. I’m looking at an R21.4 Jetson which has this enabled in the kernel by default. Having the feature enabled is visible because it produces /dev/watchdog0…there may be other devices created if other watchdog programs are added. Further features for a watchdog timer may require kernel reconfiguration.

To demo this just run this, and after a minute or two it should reboot:

sudo tail -f /dev/watchdog0

If you were to echo any text and redirect it to “/dev/watchdog0” prior to reaching the countdown, then the timer is reset and reboot won’t occur. Running “tail -f” simply opens the file for reading and starts the timer. Killing the “tail -f” or writing to watchdog0 cancels reboot. I have not attempted to deal with customizing timeout periods.

If just anyone could read or write to the watchdog timer, there’d be a security issue. So watchdog devices are read/write only to root. If your program failed it may just require “sudo”.

Thanks, linuxdev. I saw your other/similar post about this. Good thinking–the sudo/permission aspect may indeed be the culprit. I had previously tested it with your “tail” method, and it worked (although when it rebooted something was wrong with ubuntu desktop and I had to reinstall it).