Edit online

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);