TS-4710 Watchdog: Difference between revisions

From embeddedTS Manuals
No edit summary
(Replaced content with "{{:TS-7600 Watchdog}}")
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
The watchdog is manipulated via the tshwctl utility.  The startup scripts automatically run and daemonize tshwctl to feed the watchdog by default.  It can be armed in 3 modes (0 - .4s, 1- 2.7s, 2 - 10.8s). It can be either auto-fed from a background process that continually feeds the watchdog while running (--autofeed option), or via a /dev/watchdog UNIX named pipe which receives single ASCII characters which are written to feed it from another application.
{{:TS-7600 Watchdog}}
 
{| class="wikitable"
|-
! Value
! Result
|-
| 0
| feed watchdog for another .338s
|-
| 1
| feed watchdog for another 2.706s
|-
| 2
| feed watchdog for another 10.824s
|-
| 3
| disable watchdog
|}
 
Watchdog by default comes out of reset armed for .338 seconds. TS-BOOTROM firmware feeds for 10.824 and OS code has 10.824 seconds to take over.
 
You can feed the watchdog from your application by poking a register:
<source lang=c>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
 
static volatile unsigned short *syscon;
static unsigned short peek16(unsigned int adr) {
return syscon[adr / 2];
}
 
static void poke16(unsigned int adr, unsigned short val) {
syscon[adr / 2] = val;
}
int main(void) {
    int devmem = open("/dev/mem", O_RDWR|O_SYNC);
    assert(devmem != -1);
    syscon = (unsigned short *) mmap(0, 4096,
          PROT_READ | PROT_WRITE, MAP_SHARED, devmem, 0x80004000);
    while(1) {
          poke16(0x6, 0x2); // Feed watchdog
          sleep(5);
    }
    return 0;
}
</source>

Latest revision as of 10:00, 12 August 2013

By default there is a /dev/watchdog with the tshwctl daemon running at the highest possible priority to feed the watchdog. This is a pipe that is created in userspace, so for many applications this may provide enough functionality for the watchdog by verifying that userspace is still executing applications. If you would like to have the watchdog functionality more tightly integrated with your application you can specify various feed options.

At the lower level there are 3 valid watchdog feed values that are written to the watchdog register in the #Syscon:

Value Result
0 feed watchdog for another .338s
1 feed watchdog for another 2.706s
2 feed watchdog for another 10.824s
3 disable watchdog

The watchdog is armed by default for 10s for the operating system to take over, after which the startup scripts autofeed the watchdog with:

echo a2 > /dev/watchdog

The /dev/watchdog fifo accepts 3 types of commands:

Value Function
f<3 digits> One time feed for a specified amount of time which uses the 3 digit number / 10. For example, "f456" would feed for 45.6 seconds.
"0", "1", "2", "3" One time feed with the value in the above table.
a<num 0-3> This value autofeeds with the value in the above table.

Most applications should use the f<3 digits> option to more tightly integrate this to their application. For example:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

void do_some_work(int data) {
	/* The contract for sleep(int n) is that it will sleep for at least n
	 * seconds, but not less.  If other kernel threads or processes require
	 * more time sleep can take longer, but when your process has a high
	 * priority this is usually measured in millseconds */
	sleep(5);
}

int read_some_io() {
	/* If this function (or do_some_work) misbehave and stall thee watchdog 
         * will not be fed in the main loop and cause a reboot.  You can test 
         * this by uncommenting the next line to force an infinite loop */
	// while (1) {}
	return 42;
}

int main(int argc, char **argv)
{
	int wdfd;
	/* In languages other than C/C++ this is still essentially the same, but
	 * make sure you are opening the watchdog file synchronously so the writes
	 * happen immediately.  Many languages will buffer writes together to make 
	 * them more efficient, but the watchdog needs the writes to be timed 
	 * precisely */
	wdfd = open("/dev/watchdog", O_SYNC|O_RDWR);

	while (1) {
		int data;
		/* This loop is expected to take about 5-6 seconds, but to allow some
		 * headroom for other applications, I will feed the watchdog for 10s. */
		write(wdfd, "f100", 4);

		data = read_some_io();
		do_some_work(data);
	}
}