Demo
本 Demo 是通过ioctl接口来访问设备节点/dev/watchdog,代码详见
samples/test-watchdog/wdt.c
#include <artinchip/sample_base.h> #include <sys/time.h> #include <linux/watchdog.h> /* Global macro and variables */ #define WDT_CHAN_NUM 4 #define WDT_MAX_TIMEOUT (60 * 60) #define WDT_MIN_TIMEOUT 1 #define WDT_DEV_PATH "/dev/watchdog" static const char sopts[] = "ic:s:gp:Gku"; static const struct option lopts[] = { {"info", no_argument, NULL, 'd'}, {"channel", required_argument, NULL, 'c'}, {"set-timeout", required_argument, NULL, 's'}, {"get-timeout", no_argument, NULL, 'g'}, {"set-pretimeout", required_argument, NULL, 'p'}, {"get-pretimeout", no_argument, NULL, 'G'}, {"keepalive", no_argument, NULL, 'k'}, {"usage", no_argument, NULL, 'u'}, {0, 0, 0, 0} }; /* Functions */ int usage(char *program) { printf("Compile time: %s %s\n", __DATE__, __TIME__); printf("Usage: %s [options]\n", program); printf("\t -i, --info\t\tPrint the status and infomation\n"); printf("\t -s, --set-timeout\tSet a timeout, in second\n"); printf("\t -g, --get-timeout\tGet the current timeout, in second\n"); printf("\t -p, --set-pretimeout\tSet a pretimeout, in second\n"); printf("\t -G, --get-pretimeout\tGet the current pretimeout, in second\n"); printf("\t -k, --keepalive\tKeepalive the watchdog\n"); printf("\t -u, --usage \n"); printf("\n"); printf("Example: %s -c 0 -s 12\n", program); printf("Example: %s -c 1 -s 100 -p 90\n\n", program); return 0; } /* Open a device file to be needed. */ int wdt_open(int chan) { s32 fd = -1; char filename[16] = {0}; sprintf(filename, "%s%d", WDT_DEV_PATH, chan); fd = open(filename, O_RDWR); if (fd < 0) ERR("Failed to open %s errno: %d[%s]\n", filename, errno, strerror(errno)); return fd; } int wdt_enable(int fd, int enable) { int ret = 0; int cmd = enable ? WDIOS_ENABLECARD : WDIOS_DISABLECARD; ret = ioctl(fd, WDIOC_SETOPTIONS, &cmd); if (ret < 0) ERR("Failed to %s wdt %d[%s]\n", enable ? "enable" : "disable", errno, strerror(errno)); return ret; } int wdt_info(int chan) { int ret = 0, devfd = -1; int status = 0; struct watchdog_info info = {0}; devfd = wdt_open(chan); if (devfd < 0) return -1; ret = ioctl(devfd, WDIOC_GETSUPPORT, &info); if (ret < 0) { ERR("Failed to get support %d[%s]\n", errno, strerror(errno)); goto err; } printf("In %s watchdog V%d, options %#x\n", info.identity, info.firmware_version, info.options); ret = ioctl(devfd, WDIOC_GETSTATUS, &status); if (ret < 0) { ERR("Failed to get status %d[%s]\n", errno, strerror(errno)); goto err; } printf("Status: %d\n", status); ret = ioctl(devfd, WDIOC_GETBOOTSTATUS, &status); if (ret < 0) { ERR("Failed to get bootstatus %d[%s]\n", errno, strerror(errno)); goto err; } printf("Boot status: %d\n", status); err: wdt_enable(devfd, 0); close(devfd); return ret; } int wdt_set_timeout(int chan, int timeout, int pretimeout) { int ret = 0, devfd = -1; devfd = wdt_open(chan); if (devfd < 0) return -1; DBG("Set chan%d timeout %d, pretimeout %d\n", chan, timeout, pretimeout); ret = ioctl(devfd, WDIOC_SETTIMEOUT, &timeout); if (ret < 0) ERR("Failed to set timeout %d[%s]\n", errno, strerror(errno)); if (pretimeout) { ret = ioctl(devfd, WDIOC_SETPRETIMEOUT, &pretimeout); if (ret < 0) ERR("Failed to set pretimeout %d[%s]\n", errno, strerror(errno)); } wdt_enable(devfd, 0); close(devfd); return ret; } int wdt_get_timeout(int chan) { int ret = 0, devfd = -1; int timeout; devfd = wdt_open(chan); if (devfd < 0) return -1; ret = ioctl(devfd, WDIOC_GETTIMEOUT, &timeout); if (ret < 0) ERR("Failed to get timeout %d[%s]\n", errno, strerror(errno)); else DBG("Get chan%d timeout %d\n", chan, timeout); wdt_enable(devfd, 0); close(devfd); return ret; } int wdt_set_pretimeout(int chan, int pretimeout) { int ret = 0, devfd = -1; devfd = wdt_open(chan); if (devfd < 0) return -1; DBG("Set chan%d pretimeout %d\n", chan, pretimeout); ret = ioctl(devfd, WDIOC_SETPRETIMEOUT, &pretimeout); if (ret < 0) ERR("Failed to set pretimeout %d[%s]\n", errno, strerror(errno)); wdt_enable(devfd, 0); close(devfd); return ret; } int wdt_get_pretimeout(int chan) { int ret = 0, devfd = -1; int pretimeout; devfd = wdt_open(chan); if (devfd < 0) return -1; ret = ioctl(devfd, WDIOC_GETPRETIMEOUT, &pretimeout); if (ret < 0) ERR("Failed to get pretimeout %d[%s]\n", errno, strerror(errno)); else DBG("Get chan%d pretimeout %d\n", chan, pretimeout); wdt_enable(devfd, 0); close(devfd); return ret; } int wdt_keepalive(int chan) { int ret = 0, devfd = -1; devfd = wdt_open(chan); if (devfd < 0) return -1; ret = ioctl(devfd, WDIOC_KEEPALIVE, NULL); if (ret < 0) ERR("Failed to keepalive %d[%s]\n", errno, strerror(errno)); else DBG("keepalive chan%d\n", chan); wdt_enable(devfd, 0); close(devfd); return ret; } int main(int argc, char **argv) { int c, chan = 0; int timeout = 0, pretimeout = 0; while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { switch (c) { case 'c': chan = str2int(optarg); if ((chan < 0) || (chan >= WDT_CHAN_NUM)) { ERR("Invalid channel No.%s\n", optarg); return -1; } DBG("You select the channel %d\n", chan); continue; case 's': timeout = str2int(optarg); continue; case 'g': return wdt_get_timeout(chan); case 'p': pretimeout = str2int(optarg); continue; case 'G': return wdt_get_pretimeout(chan); case 'i': return wdt_info(chan); case 'k': return wdt_keepalive(chan); case 'u': default: return usage(argv[0]); } } return wdt_set_timeout(chan, timeout, pretimeout); }
本Demo是通过test-wdt命令的实现(详见bsp/examples/test-wdt/test-wdt.c),可以作为Watchdog设备的使用参考:
#include <rtthread.h> #include <aic_core.h> #include <drivers/watchdog.h> #include <aic_drv_wdt.h> #include <hal_wdt.h> #include <getopt.h> irqreturn_t aic_wdt_irq(int irq, void *arg) { rt_kprintf("Watchdog chan0 IRQ happened\n"); return IRQ_HANDLED; } static void idle_hook(void) { rt_device_t wdt_dev = RT_NULL; wdt_dev = rt_device_find("wdt"); rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL); } static void usage(char * program) { printf("\n"); printf("Usage: %s [-s timeout] [-p pretimeout] [-c clear threshold] [-g] [-k] [-u]\n",\ program); printf("\t -s, --set-timeout\tSet a timeout, in second\n"); printf("\t -p, --set-pretimeout\tSet a pretimeout, in second\n"); printf("\t -c, --set-clear threshold\tSet clear threshold,in second(0~3)\n"); printf("\t -g, --get-timeout\tGet the current timeout, in second\n"); printf("\t -k, --keepalive\tKeepalive the watchdog\n"); printf("\t -u, --usage \n"); printf("\n"); } void test_wdt(int argc, char **argv) { int opt; int timeout = 0; rt_device_t wdt_dev = RT_NULL; wdt_dev = rt_device_find("wdt"); rt_device_init(wdt_dev); optind = 0; while ((opt = getopt(argc, argv, "s:p:c:gku")) != -1) { switch (opt) { case 'c': timeout = strtoul(optarg, NULL, 10); rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_SET_CLR_THD, &timeout); rt_kprintf("set clear threshold:%d\n", timeout); break; case 's': timeout = strtoul(optarg, NULL, 10); rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); rt_kprintf("set timeout:%d\n", timeout); break; case 'g': rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_GET_TIMEOUT, &timeout); rt_kprintf("timeout:%d\n", timeout); break; case 'p': timeout = strtoul(optarg, NULL, 10); rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_SET_IRQ_TIMEOUT, &timeout); rt_device_control(wdt_dev, RT_DEVICE_CTRL_WDT_IRQ_ENABLE, &aic_wdt_irq); rt_kprintf("set pretimeout:%d\n", timeout); break; case 'k': rt_thread_idle_sethook(idle_hook); rt_kprintf("feed the dog! \n"); break; case 'u': default: usage(argv[0]); } } } MSH_CMD_EXPORT_ALIAS(test_wdt, test_wdt, Reboot the system);