1
|
#include "watchdog.h"
|
2
|
#include <sys/ioctl.h>
|
3
|
#include <sys/types.h>
|
4
|
#include <sys/stat.h>
|
5
|
#include <fcntl.h>
|
6
|
#include <string.h>
|
7
|
#include <unistd.h>
|
8
|
#include <stdio.h>
|
9
|
#include <linux/watchdog.h>
|
10
|
|
11
|
using namespace MityDSP;
|
12
|
|
13
|
/**
|
14
|
* Constructor for the watchdog abstraction
|
15
|
*
|
16
|
* \param apDevice filename of device (defaults to /dev/watchdog)
|
17
|
*/
|
18
|
tcWatchdog::tcWatchdog(const char* apDevice)
|
19
|
: mnMask(0)
|
20
|
, mnSet(0)
|
21
|
, mnFd(-1)
|
22
|
{
|
23
|
sem_init(&mhSem, 0, 1);
|
24
|
mpFileName = new char[strlen(apDevice)+1];
|
25
|
strcpy(mpFileName, apDevice);
|
26
|
}
|
27
|
|
28
|
/**
|
29
|
* Destructor. Shuts down running watchdog. cleans up resources.
|
30
|
*/
|
31
|
tcWatchdog::~tcWatchdog(void)
|
32
|
{
|
33
|
const char *no_reboot = "V\n";
|
34
|
if (mnFd >= 0)
|
35
|
{
|
36
|
printf("shutting down watchdog\n");
|
37
|
write(mnFd,no_reboot,strlen(no_reboot));
|
38
|
close(mnFd);
|
39
|
}
|
40
|
delete [] mpFileName;
|
41
|
sem_destroy(&mhSem);
|
42
|
}
|
43
|
|
44
|
/**
|
45
|
* Enable the watchdog. This should typically be
|
46
|
* called after at least 1 checkpoint has been registered
|
47
|
* and the application is ready for the watchdog operation
|
48
|
* to begin.
|
49
|
*
|
50
|
* \param TimeoutSecs number of seconds before watchdog timeout
|
51
|
* \return non-zero on error.
|
52
|
*/
|
53
|
int tcWatchdog::StartWatchDog(int TimeoutSecs)
|
54
|
{
|
55
|
mnFd = open(mpFileName, O_RDWR);
|
56
|
if (mnFd < 0)
|
57
|
{
|
58
|
perror("open watchdog:");
|
59
|
return mnFd;
|
60
|
}
|
61
|
// NOTE: L138 watchdog driver doesn't support WDIOC_SETTIMEOUT.
|
62
|
// Timeout defaults to 60 seconds
|
63
|
ioctl(mnFd,WDIOC_SETTIMEOUT,&TimeoutSecs);
|
64
|
return 0;
|
65
|
}
|
66
|
|
67
|
/**
|
68
|
* Register a checkpoint. The tcWatchdog class supports multiple
|
69
|
* checkpoints (or threads, etc.) that must Checkin() prior to the
|
70
|
* watchdog being tagged. This routine generates a handle for a
|
71
|
* newly registered checkpoint.
|
72
|
*
|
73
|
* \return handle to use for Checkin() or -1 on failure.
|
74
|
*/
|
75
|
int tcWatchdog::RegisterCheckpoint(void)
|
76
|
{
|
77
|
int i, mask;
|
78
|
int rv = -1;
|
79
|
sem_wait(&mhSem);
|
80
|
/* find next available slot in mask */
|
81
|
for (i = 0, mask=1; i < 31; i++, mask<<=1)
|
82
|
{
|
83
|
if (!(mask & mnMask))
|
84
|
{
|
85
|
mnMask |= mask;
|
86
|
rv = mask;
|
87
|
break;
|
88
|
}
|
89
|
}
|
90
|
sem_post(&mhSem);
|
91
|
return rv;
|
92
|
}
|
93
|
|
94
|
/**
|
95
|
* Remove a registered checkpoint from the monitor list.
|
96
|
* \param handle the checkpoint previously from RegisterCheckpoint
|
97
|
* \return non-zero on error.
|
98
|
*/
|
99
|
int tcWatchdog::UnRegisterCheckpoint(int handle)
|
100
|
{
|
101
|
int rv = -1;
|
102
|
sem_wait(&mhSem);
|
103
|
if (handle & mnMask)
|
104
|
{
|
105
|
mnMask &= ~handle;
|
106
|
rv = 0;
|
107
|
}
|
108
|
sem_post(&mhSem);
|
109
|
return rv;
|
110
|
}
|
111
|
|
112
|
/**
|
113
|
* Check in for the watchdog update. When all registered
|
114
|
* methods have checked in, the watchdog timer will be
|
115
|
* tagged/reset.
|
116
|
*
|
117
|
* \param Checkpoint checkpoint handle from RegisterCheckpoint
|
118
|
*
|
119
|
* \return non-zero on error.
|
120
|
*/
|
121
|
int tcWatchdog::Checkin(int Checkpoint)
|
122
|
{
|
123
|
if (mnFd < 0)
|
124
|
return -1;
|
125
|
|
126
|
sem_wait(&mhSem);
|
127
|
mnSet |= Checkpoint;
|
128
|
if (mnSet == mnMask)
|
129
|
{
|
130
|
/* tag watchdog */
|
131
|
mnSet = 0;
|
132
|
ioctl(mnFd, WDIOC_KEEPALIVE, 0);
|
133
|
}
|
134
|
sem_post(&mhSem);
|
135
|
|
136
|
return 0;
|
137
|
}
|
138
|
|
139
|
#ifdef WATCHDOG_MAIN
|
140
|
int main()
|
141
|
{
|
142
|
tcWatchdog watch;
|
143
|
int watchHandle;
|
144
|
|
145
|
printf("Starting watchdog! Timeout interval 60s.\n");
|
146
|
watch.StartWatchDog(60000);
|
147
|
watchHandle = watch.RegisterCheckpoint();
|
148
|
|
149
|
while (1 == 1)
|
150
|
{
|
151
|
printf(".");
|
152
|
fflush(stdout);
|
153
|
|
154
|
// Tickle watchdog
|
155
|
watch.Checkin(watchHandle);
|
156
|
// Sleep 1 second
|
157
|
sleep(1);
|
158
|
}
|
159
|
|
160
|
return 0;
|
161
|
}
|
162
|
#endif
|