16

Following on from the question and excellent answer provided by Steve Robillard here:

How do I hard reset a Raspberry Pi?

How can I send a heartbeat signal from my own program to the BCM2708's hardware watchdog instead of from the Linux watchdog daemon? In other words, I want to reset the RPi if MY program is not running (which executes on startup), not only when the whole system is frozen.

Thanks.

Guy
  • 1,657
  • 1
  • 16
  • 18

1 Answers1

8

You can and it's quite easy. RPi has a Linux module that implements the standard Linux watchdog API. You can find documentation of this here.

Now, if you read this, you will know that there is a special device file called /dev/watchdog and in order to use watchdog you have to open this file and write some data (one byte, it's best to write something other than 'V' which I'm explaining later) to it from time to time. If you won't write anything to this file for long enough, watchdog will trigger a reboot. You can find an example program (very simple) here.

Note that in a normal situation, if you close /dev/watchdog, watchdog can be disabled. There is a special mode called 'Magic Close feature' which seems to be implemented by a RPi driver but AFAIK it's not enabled in the default kernel configuration (CONFIG_WATCHDOG_NOWAYOUT option). In this case, reboot will be triggered even if you close /dev/watchdog unless you write 'V' to it just before quitting the app.

You should test yourself if it is indeed disabled (I don't have a RPi here right now to test), but if it isn't, it's not good for you. If your application crashes, the watchdog device file will be closed and reboot won't be triggered and this is why you want it. In this situation, you can either change the kernel configuration and rebuild it or write a customized application that is going to monitor if your main application is working (using some IPC method for example).

There is also the ioctl API which allows you to do some more with watchdog. You can, for example, set a different timeout - IOCTL with WDIOC_SETTIMEOUT (seems to be supported by the RPI driver) or get timeout - IOCTL with WDIOC_GETTIMEOUT (which also seems to be supported). You may want to use it to modify the default timeout (10 seconds). There is hard limit to 16 seconds however. Here's an example:

int timeout = 15;
int fd = open("/dev/watchdog", O_WRONLY);
ioctl(fd, WDIOC_SETTIMEOUT, &timeout);

You can also use IOCTL with WDIOC_KEEPALIVE instead of writing a character if you want. Both methods are valid.

tlhIngan
  • 3,372
  • 5
  • 19
  • 33
Krzysztof Adamski
  • 9,615
  • 1
  • 37
  • 53
  • Oh, and I forgot - you can actually use watchdogd for this. It supports calling external program that will check and report the system state. Read "Check Binary" in this man page – Krzysztof Adamski Aug 09 '12 at 11:53
  • Thanks. I got it working! After adding bcm2708_wdog to /etc/modules I created a simple VB.NET test app to check my understanding: Dim fs As New System.IO.FileStream(fn, IO.FileMode.Open) to start the timer running and fs.WriteByte(H) then fs.Flush() to send it heartbeats. Works great! – Guy Aug 09 '12 at 16:16
  • what's the numeric representation of WDIOC_KEEPALIVE ? can't find it anywhere. – Flash Thunder Apr 26 '16 at 09:27
  • @FlashThunder: It's defined here: http://lxr.free-electrons.com/source/include/uapi/linux/watchdog.h#L29 but you would have to resolve couple of levels of macros to find the exact value. The better way is to just write simple C program to print the value. Just include the <linux/watchdog.h>. On my system it's 0x80045705 – Krzysztof Adamski Jul 22 '16 at 19:38