1. 程式人生 > >嵌入式開發之看門狗

嵌入式開發之看門狗

開始今天的課程----linux嵌入式系統開發之看門狗----應用篇。

  話說這個看門狗,還真是形象。什麼個意思呢?就是一直“狗”它會盯著系統的定時器,如果定時器的時間值到了,你還沒有餵它東西的話,它肯定就不爽了,就把你的系統重啟,懲罰一下你,為啥這麼久了不餵它東西吃。所以嘛,為了保持系統正常執行,就要在定時器到之前不斷的餵它東西吃,賄賂一下它。

   回到這個程式,為了不是看門狗叫(重啟咱們的電腦),就不斷地要從終端輸入字元來喂狗(清空定時器,讓計時值總是從0開始計數),這樣的話,就可以保持狗不會飢餓,也就不會重啟我們的電腦了。不多說了,咱們結合程式碼來詳細介紹。

必要的標頭檔案#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <sys/signal.h>
#include <termios.h>

struct watchdog_info{
    unsigned int options;   //options the card/driver supprots 19         
    unsigned int firmware_version;  //firmcard version of the card
    unsigned char identity[32];     //identity of the board 21
 };

#define WATCHDOG_IOCTL_BASE 'W'
#define WDIOC_GETSUPPORT _IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
#define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
#define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int) 27 
#define WDIOS_DISABLECARD 0x0001        /* Turn off the watchdog timer */
#define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */
#define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int)
#define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int)

int Getch (void)   //無回顯的從螢幕輸入字元,來達到喂狗的目的
{
     int ch;
     struct termios oldt, newt;   //終端裝置結構體
     tcgetattr(STDIN_FILENO, &oldt);   //獲得終端屬性
     newt = oldt;
     newt.c_lflag &= ~(ECHO|ICANON);   //設定無回顯屬性
     tcsetattr(STDIN_FILENO, TCSANOW, &newt);  //設定新的終端屬性
     ch = getchar();   //從鍵盤輸入一個數據
     tcsetattr(STDIN_FILENO, TCSANOW, &oldt);  //恢復終端裝置初始設定
     return ch;
}
 //suspend some seconds
int zsleep(int millisecond)
{
     unsigned long usec;
     usec=1000*millisecond;
     usleep(usec); //睡眠usec秒
}
int Init()

     int fd;
     //open device file
     fd = open("/dev/watchdog",O_RDWR);   //開啟看門狗裝置
      if(fd < 0)
     {
         printf("device open fail\n");
         return -1;
     }
     return fd;
}

int main(int argc,char **argv)
{
     int fd,ch;
     int i,j;
     char c;
     struct watchdog_info wi;
     fd=Init();  //開啟終端看門狗裝置
     //讀板卡資訊,但不常用
      ioctl(fd,WDIOC_GETSUPPORT,&wi);
     printf("%d,%s\n",wi.options,wi.identity);
     //讀看門狗溢位時間,預設是5s
     //重新設定時間為10s
     i=5;
     printf("%d\n",ioctl(fd,WDIOC_SETTIMEOUT,&i));
     //讀新的設定時間
      printf("%d\n",ioctl(fd,WDIOC_GETTIMEOUT,&i));
     printf("%d\n",i); 
     //看門狗開始和停止工作,開啟和關閉裝置具有同樣的功能
     //關閉
      i=WDIOS_DISABLECARD;
     printf("%d\n",ioctl(fd,WDIOC_SETOPTIONS,&i));
     //開啟
      i=WDIOS_ENABLECARD;
     printf("%d\n",ioctl(fd,WDIOC_SETOPTIONS,&i));
     while(1)
     {
           zsleep(100);
           if((c=Getch())!=27){
                //輸入如果不是ESC,就喂狗,否則不喂狗,到時間後系統重啟
                ioctl(fd,WDIOC_KEEPALIVE,NULL);
                //write(fd,NULL,1);     //同樣是喂狗
           }
     }
    close(fd);   //關閉裝置
     return 0;

}

(轉)Linux 看門狗原理

主機板上提供一個可按分或秒計時的,最長達255級的可程式設計看門狗定時器,WDT超時事件發生時系統復位.
本程式(w83627hf_wdt.c)是基於Winbond83627晶片的看門狗驅動程式.
驅動程式介面
wdt_open :開啟裝置,應用程式呼叫open時進入該函式.
wdt_close :關閉裝置,應用程式呼叫close時進入該函式
wdt_write :寫裝置,若傳入資料大小不為0則喂狗;應用程式呼叫write時進入該函式.
wdt_ioctl :應用程式呼叫ioctl時進入該函式,通過傳入不同的引數實現不同的功能.主要引數如下:
WDIOC_GETSUPPORT :獲取看門狗資訊watchdog_info(見w83627hf_wdt.h)
WDIOC_KEEPALIVE :喂狗,同write函式功能類似
WDIOC_SETTIMEOUT :設定超時值
WDIOC_GETTIMEOUT :獲取超時值
WDIOC_SETOPTIONS:設定看門狗狀態,開啟(WDIOS_ENABLECARD)或關閉(WDIOS_DISABLECARD)
應用程式編寫
主要步驟如下(請參考程式碼w83627hf_test.c):
1、開啟裝置
呼叫open方法,返回值為已開啟的裝置,若小於0表示開啟失敗,以下的呼叫都要用該返回值做引數,表示操作該裝置.
        wdt = open(WDT_DEVICE, O_RDWR);
2、開啟看門狗
呼叫ioctl方法,傳入WDIOC_SETOPTIONS引數,設定開啟(WDIOS_ENABLECARD)狀態,方法如下:
        ioctl(wdt, WDIOC_SETOPTIONS, WDIOS_ENABLECARD);
3、設定看門狗超時值(可選,預設為60s)
呼叫ioctl方法,傳入WDIOC_SETTIMEOUT引數,設定指定的超時值.
        ioctl(wdt, WDIOC_SETTIMEOUT, &timeout);//timeout為超時值
4、喂狗
一般用while(1)迴圈在超時時間(timeout)內定時喂狗,若在timeout內沒喂狗,則系統復位.提供2種喂狗方法:
(1) 呼叫write方法,注意傳入引數大小不要為0.
         write(wdt, &arg, sizeof(arg));//若sizeof(arg)為0則不會喂狗
(2)呼叫ioctl方法,傳入WDIOC_KEEPALIVE引數
        ioctl(wdt, WDIOC_KEEPALIVE,0);//第3個引數驅動不用
5、關閉看門狗
若不需要使用看門狗,則關閉它,注意關閉後即使超時值到也不會復位.呼叫ioctl方法實現,傳入WDIOC_SETOPTIONS引數,設定關閉狀態
         ioctl(wdt, WDIOC_SETOPTIONS, WDIOS_DISABLECARD)
6、關閉裝置
呼叫close方法.
         close(wdt);