zoukankan      html  css  js  c++  java
  • [Reprinted] Howto Use Linux Watchdog

    This artical is reprinted from the URL below:

    http://embeddedfreak.wordpress.com/2010/08/23/howto-use-linux-watchdog/

    Howto Use Linux Watchdog

    Filed under: ARM9, embedded-linux — Tags: , — kunilkuda @ 4:08 pm

    If you’re new with embedded Linux, one of interesting thing that you can start to learn is how to use the watchdog.

    Watchdog, like its name, is a kind of peripheral that will boot the system if it doesn’t being ‘fed’ at certain time (In our daily terms: it will bite your system, unless you kick it). Therefore, it will prevent your system from hanging. It’s a nice feature to have, specially if there’s nobody around to press the ‘reset’ button for you =)

    Watchdog Driver

    To use watchdog peripheral in Linux, you will need:

    1. Watchdog driver: Most of board suppliers will provide you for free (ask their support if you need to). This article is using EA3131 Linux BSP’s provided watchdog driver.
    2. Watchdog device file: Device file is a special kind of file to mark the device node in your root filesystem (so you can access the peripheral like accessing file..’everything is a file’ in UNIX system). Normally it is called ‘/dev/watchdog’

    If you don’t have watchdog device file in your target root filesystem, you can recreate it using ‘mknod’

    # mknod /dev/watchdog c 10 130
    

    Of course, the ‘mknod’ tool must be present in your root filesystem first before you can execute this. To run the watchdog driver in your system

    # insmod your_watchdog_driver.ko
    

    Starting – Stopping Watchdog

    The watchdog is automatically started once you open ‘/dev/watchdog’. To stop the watchdog, you will need to:

    1. Write character ‘V’ into ‘/dev/watchdog’ to prevent stopping the watchdog accidentally
    2. Close the ‘/dev/watchdog’ file

    An exception on stopping the watchdog by closing the file is when ‘CONFIG_WATCHDOG_NOWAYOUT’ is enabled in your kernel configuration. When this option is enabled, the watchdog cannot be stopped at all. Hence, you will need to feed / kick it all the time or it will reset the system

    ‘Kicking’ Watchdog

    To kick or to feed the watchdog you can do it in two ways:

    1. Write any character into ‘/dev/watchdog’. You can write any character into /dev/watchdog, but, my suggestion, don’t write ‘V’ character (See the ‘Starting-Stopping Watchdog’ point above)
    2. Use IOCTL to insert ‘WDIOC_KEEPALIVE’ value.

    Other Things To Do with Watchdog

    If you’re bored with the standard start-kick-stop things, you can also try out other watchdog features:

    • Set the watchdog timeout. Use IOCTL with WDIOC_SETTIMEOUT
    • Get the current watchdog timeout. Use IOCTL with WDIOC_GETTIMEOUT
    • Check if the last boot is caused by watchdog or it is power-on-reset. Use IOCTL with WDIOC_GETBOOTSTATUS.

    If you are interested to know more about using watchdog in Linux, read the watchdog documentation in Linux source code (Linux-x.y.z/Documentation/watchdog/watchdog-api.txt). Here’s some demo code to test the Linux watchdog:

    /*
     * Linux watchdog demo for LPC313x
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * (at your option) any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     *
     */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <getopt.h>
    #include <string.h>
    #include <errno.h>
    
    #include <linux/watchdog.h>
    
    #define WATCHDOGDEV "/dev/watchdog"
    static const char *const short_options = "hd:i:";
    static const struct option long_options[] = {
       {"help", 0, NULL, 'h'},
       {"dev", 1, NULL, 'd'},
       {"interval", 1, NULL, 'i'},
       {NULL, 0, NULL, 0},
    };
    
    static void print_usage(FILE * stream, char *app_name, int exit_code)
    {
       fprintf(stream, "Usage: %s [options]
    ", app_name);
       fprintf(stream,
          " -h  --help                Display this usage information.
    "
          " -d  --dev <device_file>   Use <device_file> as watchdog device file.
    "
          "                           The default device file is '/dev/watchdog'
    "
          " -i  --interval <interval> Change the watchdog interval time
    ");
    
       exit(exit_code);
    }
    
    int main(int argc, char **argv)
    {
       int fd;         /* File handler for watchdog */
       int interval;      /* Watchdog timeout interval (in secs) */
       int bootstatus;      /* Wathdog last boot status */
       char *dev;      /* Watchdog default device file */
    
       int next_option;   /* getopt iteration var */
       char kick_watchdog;   /* kick_watchdog options */
    
       /* Init variables */
       dev = WATCHDOGDEV;
       interval = 0;
       kick_watchdog = 0;
    
       /* Parse options if any */
       do {
          next_option = getopt_long(argc, argv, short_options,
                     long_options, NULL);
          switch (next_option) {
          case 'h':
             print_usage(stdout, argv[0], EXIT_SUCCESS);
          case 'd':
             dev = optarg;
             break;
          case 'i':
             interval = atoi(optarg);
             break;
          case '?':   /* Invalid options */
             print_usage(stderr, argv[0], EXIT_FAILURE);
          case -1:   /* Done with options */
             break;
          default:   /* Unexpected stuffs */
             abort();
          }
       } while (next_option != -1);
    
       /* Once the watchdog device file is open, the watchdog will be activated by
          the driver */
       fd = open(dev, O_RDWR);
       if (-1 == fd) {
          fprintf(stderr, "Error: %s
    ", strerror(errno));
          exit(EXIT_FAILURE);
       }
    
       /* If user wants to change the watchdog interval */
       if (interval != 0) {
          fprintf(stdout, "Set watchdog interval to %d
    ", interval);
          if (ioctl(fd, WDIOC_SETTIMEOUT, &interval) != 0) {
             fprintf(stderr,
                "Error: Set watchdog interval failed
    ");
             exit(EXIT_FAILURE);
          }
       }
    
       /* Display current watchdog interval */
       if (ioctl(fd, WDIOC_GETTIMEOUT, &interval) == 0) {
          fprintf(stdout, "Current watchdog interval is %d
    ", interval);
       } else {
          fprintf(stderr, "Error: Cannot read watchdog interval
    ");
          exit(EXIT_FAILURE);
       }
    
       /* Check if last boot is caused by watchdog */
       if (ioctl(fd, WDIOC_GETBOOTSTATUS, &bootstatus) == 0) {
          fprintf(stdout, "Last boot is caused by : %s
    ",
             (bootstatus != 0) ? "Watchdog" : "Power-On-Reset");
       } else {
          fprintf(stderr, "Error: Cannot read watchdog status
    ");
          exit(EXIT_FAILURE);
       }
    
       /* There are two ways to kick the watchdog:
          - by writing any dummy value into watchdog device file, or
          - by using IOCTL WDIOC_KEEPALIVE
        */
       fprintf(stdout,
          "Use:
    "
          " <w> to kick through writing over device file
    "
          " <i> to kick through IOCTL
    " " <x> to exit the program
    ");
       do {
          kick_watchdog = getchar();
          switch (kick_watchdog) {
          case 'w':
             write(fd, "w", 1);
             fprintf(stdout,
                "Kick watchdog through writing over device file
    ");
             break;
          case 'i':
             ioctl(fd, WDIOC_KEEPALIVE, NULL);
             fprintf(stdout, "Kick watchdog through IOCTL
    ");
             break;
          case 'x':
             fprintf(stdout, "Goodbye !
    ");
             break;
          default:
             fprintf(stdout, "Unknown command
    ");
             break;
          }
       } while (kick_watchdog != 'x');
    
       /* The 'V' value needs to be written into watchdog device file to indicate
          that we intend to close/stop the watchdog. Otherwise, debug message
          'Watchdog timer closed unexpectedly' will be printed
        */
       write(fd, "V", 1);
       /* Closing the watchdog device will deactivate the watchdog. */
       close(fd);
    }
    

    Note1:  The watchdog driver may not implement all of IOCTL that is used in this demo code
    Note2: The demo is tested on LPC313x (on EA3131 board). See LPCLinux forum for the details.
    Note3: Assuming you’re using CodeSourcery’s GNU/Linux, the command to compile it for ARM926EJ-S is

    $ arm-none-linux-gnueabi-gcc -mcpu=arm926ej-s watchdog_demo.c -o watchdog_demo
    
  • 相关阅读:
    IE6中布局常见问题
    -bash: grunt-cli: command not found
    字符长度
    Mac下safari、chrome打开开发者工具快捷键
    line-height:150%和line-height:1.5的区别
    JavaScript中的apply()、call()、bind()
    JavaScript中的 this
    JavaScript中的var与作用域
    onload与ready的区别
    浏览器的同源策略
  • 原文地址:https://www.cnblogs.com/lake-of-embedded-system/p/3259488.html
Copyright © 2011-2022 走看看