//--------------------------------------------------------------------------------------------
// 作者:longtian635241([email protected])
// 論壇ID:idea6410
// 版權:idea6410
// 平臺:友堅idea6410開發板
// 發佈日期:2012-11-22
// 最後修改:2012-11-22
//----------------------------------------------------------------------------------------------
linux-3.6.6其實已經有看門狗驅動了,即H:\VM share\linux-3.6.6\drivers\watchdog\s3c2410_wdt.c;只需配置就可用了!
【1】在內核中配置看門狗驅動
在內核源代碼目錄執行:make menuconfig,進入內核配置主菜單,依次選擇進入如下子菜單:
Device Drivers --->
[*] Watchdog Timer Support --->
<*> S3C2410 Watchdog
/////////////////////////////////////////////////
在drivers/watchdog/s3c2410_wdt.c中進行修改:
- #define CONFIG_S3C2410_WATCHDOG_ATBOOT (1)
- #define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)
#define CONFIG_S3C2410_WATCHDOG_ATBOOT (1)
#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)
注:
- #define CONFIG_S3C2410_WATCHDOG_ATBOOT (0)//系統啓動時不開啓看門狗
- #define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)//復位時間
///////////////////////////////////////////////////////////////可以不必修改!
啓動顯示:
s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled
【2】關於打開和關閉看門狗
在看門狗驅動程序中,我們注意到有這樣一個函數,注意其中的藍色粗體部分字體:
#define PFX "s3c2410-wdt: "
#define CONFIG_S3C2410_WATCHDOG_ATBOOT (0)
//這裏表明看門狗的默認時間是15 秒,如果超過此時間系統將自行重啓
#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)
static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
/*
* Refresh the timer.
*/
if (len) {
if (!nowayout) {
size_t i;
/* In case it was set long ago */
expect_close = 0;
for (i = 0; i != len; i++) {
char c;
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
expect_close = 42;
}
}
s3c2410wdt_keepalive();
}
return len;
}
根據此代碼,我們判定可以在打開看門狗設備(/dev/watchdog)之後不斷的向看門狗隨便寫入寫入一些數據以實現餵狗操作,但是,當寫入“V“時,就可以關閉看門狗了。
原因分析:
open函數:
- static int s3c2410wdt_open(struct inode *inode, struct file *file)
- {
- if (test_and_set_bit(0, &open_lock))
- return -EBUSY;
- if (nowayout)
- __module_get(THIS_MODULE);
- expect_close = 0;
- /* start the timer */
- s3c2410wdt_start();
- return nonseekable_open(inode, file);
- }
static int s3c2410wdt_open(struct inode *inode, struct file *file)
{
if (test_and_set_bit(0, &open_lock))
return -EBUSY;
if (nowayout)
__module_get(THIS_MODULE);
expect_close = 0;
/* start the timer */
s3c2410wdt_start();
return nonseekable_open(inode, file);
}
release函數:
- static int s3c2410wdt_release(struct inode *inode, struct file *file)
- {
- /*
- * Shut off the timer.
- * Lock it in if it's a module and we set nowayout
- */
- if (expect_close == 42)
- s3c2410wdt_stop();
- else {
- dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");
- s3c2410wdt_keepalive();
- }
- expect_close = 0;
- clear_bit(0, &open_lock);
- return 0;
- }
static int s3c2410wdt_release(struct inode *inode, struct file *file)
{
/*
* Shut off the timer.
* Lock it in if it's a module and we set nowayout
*/
if (expect_close == 42)
s3c2410wdt_stop();
else {
dev_err(wdt_dev, "Unexpected close, not stopping watchdog\n");
s3c2410wdt_keepalive();
}
expect_close = 0;
clear_bit(0, &open_lock);
return 0;
}
write函數:
- static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
- size_t len, loff_t *ppos)
- {
- /*
- * Refresh the timer.
- */
- if (len) {
- if (!nowayout) {
- size_t i;
- /* In case it was set long ago */
- expect_close = 0;
- for (i = 0; i != len; i++) {
- char c;
- if (get_user(c, data + i))
- return -EFAULT;
- if (c == 'V')
- expect_close = 42;
- }
- }
- s3c2410wdt_keepalive();
- }
- return len;
- }
static ssize_t s3c2410wdt_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos)
{
/*
* Refresh the timer.
*/
if (len) {
if (!nowayout) {
size_t i;
/* In case it was set long ago */
expect_close = 0;
for (i = 0; i != len; i++) {
char c;
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
expect_close = 42;
}
}
s3c2410wdt_keepalive();
}
return len;
}
看門狗只能被一個進程打開,打開函數中先判斷了一下,然後啓動了看門狗;再看write函數,寫入的如果是V則允許關閉看門狗,如果不是V僅僅餵狗一次;最後是release函數,如果允許關閉則關閉看門狗,如果不允許關閉,打印"Unexpectedclose, not stopping watchdog",餵狗一次。此時看門狗並沒有關閉,所以系統會復位的,如果輸入V則看門狗被關閉,這樣系統就不復位了。
【3】測試看門狗
根據上面的分析,我們可以使用 echo 命令向/dev/watchdog 設備隨便寫入一些數據即可開啓看門狗,比如:echo 0 > /dev/watchdog,如下:
[root@zxj /]#echo 0 > /dev/watchdog
s3c2410-wdt s3c2410-wdt: Unexpected close, not stopping watchdog
[root@zxj /]#
此時,如果靜等 15 秒鐘,系統將會自動重啓,這樣就證實了看門狗已經被開啓了。如果 15 秒之內,我們不停地重複“餵狗”操作,也就是不停的使用echo 命令向看門狗寫入數據,那麼系統就不會重啓。那麼,如何停止看門狗呢?根據上面的分析,只要寫入“V”就可以了。需要知道的是,但我們使用echo 命令向/dev/watchdog 寫入數據的時候,同時也把“回車”給送進去了,因此可以這樣操作:echo -n V >/dev/watchdog這裏的“-n”意思是“去掉回車”,爲了測試,你可以先輸入:
echo 0 > /dev/watchdog
接着再輸入:
echo –n V > /dev/watchdog
然後接着靜等,過了好久,系統依然在正常運行,這就證明了看門狗已經被關閉了。
設置成系統啓動就啓動看門狗,並且看門狗到期時間爲15s。這樣系統復位後每15s系統就會復位一次,所以我們在用戶空間進行餵狗,驅動中的那個中斷函數是當看門狗作爲定時器時用的,所以沒有實現餵狗,所以只能在用戶程序中餵狗,下面是源碼:
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <linux/watchdog.h>
- int main(int argc, char **argv){
- int fd;
- fd = open("/dev/watchdog",O_RDONLY);
- if(fd < 0){
- perror("/dev/watchdog");
- return -1;
- }
- for(;;){
- ioctl(fd, WDIOC_KEEPALIVE);
- sleep(3);
- }
- close(fd);
- return 0;
- }
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/watchdog.h>
int main(int argc, char **argv){
int fd;
fd = open("/dev/watchdog",O_RDONLY);
if(fd < 0){
perror("/dev/watchdog");
return -1;
}
for(;;){
ioctl(fd, WDIOC_KEEPALIVE);
sleep(3);
}
close(fd);
return 0;
}
編譯:
- arm-linux-gcc wdt.c -o wdt
arm-linux-gcc -o Feed-watchdog Feed-watchdog.c
把Feed-watchdog拷貝到/bin/下,並修改root-2.6.38/etc/init.d/rcS文件,添加Feed-watchdog&這麼一句,讓系統啓動後這個應用程序在後臺運行。