aboutsummaryrefslogtreecommitdiffstats
path: root/erts/etc/vxworks/wd_example.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/etc/vxworks/wd_example.c')
-rw-r--r--erts/etc/vxworks/wd_example.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/erts/etc/vxworks/wd_example.c b/erts/etc/vxworks/wd_example.c
new file mode 100644
index 0000000000..0e3a6a1cb2
--- /dev/null
+++ b/erts/etc/vxworks/wd_example.c
@@ -0,0 +1,141 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1997-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+/*
+ * File: frc5te_wd.c
+ * Purpose: Watchdog NMI handling for FORCE 5TE
+ *
+ * Description:
+ * The watchdog handler routines are system specific. A program that
+ * wants to utilize a hardware watchdog should call wd_init and test
+ * the return value. If wd_init returns true (!0); there is a hardware
+ * watchdog, and that watchdog has been activated. If no watchdog exists,
+ * wd_init returns false (0).
+ *
+ * To keep the watchdog happy, call wd_reset at least every X seconds,
+ * where X is the number of seconds specified in the call to wd_init.
+ *
+ * The watchdog can be disarmed by setting the variable wd_disarmed to 1,
+ * and armed again by setting the same variable to 0. Watchdog status
+ * information can be retrieved using the function wd_status.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <frc5e.h>
+#include <logLib.h>
+#include <taskLib.h>
+#include <sysLib.h>
+#include <stdio.h>
+#include "hw_watchdog.h"
+
+/* prototypes */
+extern sysNMIConnect();
+#ifdef __STDC__
+void wd_keeper(int);
+void wd_nmi_int(UINT8);
+void wd_status(void);
+#else
+void wd_keeper();
+void wd_nmi_int();
+void wd_status();
+#endif
+
+#define WD_NMI_MIN_DELAY 0.830 /* Min time before watchdog NMI (in seconds) */
+#define WD_RESET_FREQUENCY (WD_NMI_MIN_DELAY / 2) /* how often the timer is reset */
+
+#define WD_KEEPER_STACK_SIZE 10000
+
+/* global variables */
+extern int spTaskOptions;
+static volatile int wd_count_startval; /* start value set by wd_init */
+static volatile int wd_count; /* counter for wd_keeper */
+volatile int wd_disarmed = 0; /* debug feature */
+
+/* wd_init is executed to initialize the watchdog. It spawns the task */
+/* wd_keeper and returns true (non-zero) if a hardware watchdog exists, */
+/* or returns false (zero) otherwise. */
+int wd_init(timeout, prio)
+ int timeout, prio;
+{
+ taskSpawn("wd_keeper", prio, spTaskOptions, WD_KEEPER_STACK_SIZE,
+ (FUNCPTR)wd_keeper, timeout,0,0,0,0,0,0,0,0,0);
+ return !0; /* watchdog exists */
+}
+
+
+/* wd_reset is called as an alive-signal from the supervisor process. */
+/* If there is no call to this function within a certain time, the */
+/* watchdog will reboot the system. */
+void wd_reset()
+{
+ wd_count = wd_count_startval;
+}
+
+
+/* wd_keeper runs as a separate task and resets the watchdog timer */
+/* before an NMI is generated. This task uses the counter wd_count to */
+/* decide if it should exit or keep resetting the timer. */
+/* Note! This task must run with higher priority than the application! */
+void wd_keeper(timeout)
+ int timeout;
+{
+ int wd_delay = sysClkRateGet() * WD_RESET_FREQUENCY;
+ wd_count_startval = (int)(timeout / WD_RESET_FREQUENCY);
+ wd_count = wd_count_startval;
+
+ /* Connect and enable level 15 interrupts */
+ sysNMIConnect((VOIDFUNCPTR) wd_nmi_int, WD_NMI, WD_NMI);
+ *(char *)FRC5CE_GEN_PURPOSE2_REG |= FRC5CE_NMI_ENABLE;
+
+ while ((wd_count > 0) || wd_disarmed) {
+ *(char *)FRC5CE_VME_A32MAP_REG |= FRC5CE_WATCHDOG_ENABLE;
+ taskDelay(wd_delay);
+ if (!wd_disarmed) wd_count--;
+ else wd_count = wd_count_startval;
+ }
+ logMsg("Watchdog keeper exits. No alive signal from application in %d seconds.\n",wd_count_startval * WD_RESET_FREQUENCY,0,0,0,0,0);
+}
+
+
+/* wd_nmi_int is the function connected to the watchdog interrupt. */
+/* It will report the failure to reset the watchdog timer. */
+void wd_nmi_int(type)
+ UINT8 type;
+{
+ switch(type) {
+ case WD_NMI:
+ logMsg("Watchdog interrupt! System will reboot.\n",0,0,0,0,0,0);
+ break;
+ default:
+ logMsg("Bad type (%d) in call to watchdog interrupt handler.\n",type,0,0,0,0,0);
+ break;
+ }
+}
+
+
+/* wd_status displays the current value of the counter. */
+void wd_status()
+{
+ fprintf(stderr, "Watchdog is %sarmed.\n", wd_disarmed ? "dis" : "");
+ fprintf(stderr, "Counter value: %d\n", wd_count);
+ fprintf(stderr, "Start value is: %d (%d seconds)\n",
+ wd_count_startval, (int)(wd_count_startval * WD_RESET_FREQUENCY));
+}