数多くの記事を読みながら、組み込みシステムで監視デバイスを正しく設定する方法を研究してきましたが、解決策はありません。私は読んだ:
- BIOS Watch Dog用のDebian watchdogデーモンを正しく設定する方法は?
- 「ウォッチドッグリセット」とは何ですか?
- 組み込みLinuxデバイスのウォッチドッグをリセットする方法
- ウォッチドッグを有効にするには?
深く見ました。
しかし今、この瞬間には後退はありません。
したがって、まず私のハードウェア/ソフトウェアを説明し、私が何を達成しようとしているのかを説明し、次に私がしたことと結果が何であるかを説明します。あなたの一人が私に正しい方向を教えてくれることを願っています。
ハワーデール:
Vortex86DX CPU(A9111 @ 933Mhz)に組み込まれているDMPについては、次のアドレスの一部の文書を参照してください。
- http://www.dmp.com.tw/tech/vortex86dx/#feature2
- http://www.dmp.com.tw/tech/vortex86dx/img/Vortex86DX_block_internal.jpg
2つの監視タイマー(16C550シリアルポート1、GPIOポート4)の強力なサポートを提供し、ALI(Acer Labs)M6117監視ハードウェア、24ビットカウンタを備えた32.768KHzクロックが付属しています。タイマー範囲は30.5u秒〜512秒、分解能は30.5u秒です。タイマーの有効期限が切れると、システムリセットが発生し、NMIまたはIRQが発生する可能性があります。
バイオス:
米国メガトレンドAMIBIOS(62-0100-000001-00101111-110309-A9100-1ADSV000-Y2KC)、BIOS日付2011年8月3日
オペレーティングシステム:
Linux カーネル 3.2.0-0.bpo.4-486 を使用した Debian 6.0 squeeze(#uname -r)
ドライバー:
ALI M6117 Watchdog v0.2は私のカーネルで動作し、Federico Bareillesの元のLinux 2.4.xドライバに基づいているとメーカーによって直接私に提供されました(http://www.iar.unlp.edu.ar/~fede/ali_m6117.html)
私の目標:
私が住んでいる場所から遠く離れた場所に機械が設置されていたので、時々止まってハードウェアリセットのために強制的にそこに運転していかなければなりませんでした。
システムが停止したら、デバイスを自動的にリセットするように設定したいと思います。
私がしたこと:
上記のドライバをコンパイル(make clean、make)してインストール(make install)しました。モジュールはカーネルパスの下の「extra」フォルダに正しくあります。
/etc/watchdog.conf
ファイルを編集して/dev/watchdog
ウォッチドッグを有効にするために、その行のコメントを削除しました(他はありません。コメントを削除したり、追加の行を追加したりしません)。
/lib/modules/3.2.0-0.bpo.4-486/extraフォルダに移動し、モジュールをロードしました。insmod alim6117_wdt.ko
モジュールがロードされたことを確認するlsmod
と
Module alim6117_wdt, size 12565, used by 0
(BIOSでウォッチドッグを有効にすると、値は1になります)
マシンを再起動してBIOSに入り、watchdog 0、watchdog 0タイマー512秒、watchdog 0信号を有効にして「リセット」を選択します。
私には何がありますか?
システムは正常に起動し、ウォッチドッグの有効化/ロードに関するメッセージが表示されますが、しばらくすると次のメッセージで再起動されます。
alim6117_wdt unexpected close, not stopping watchdog
実行すればdmesg | watchdog
得られますが、[0.017827] NMI watchdog disabled (cpu0): hardware events not enabled
必要なのはハードウェアリセットだけなので重要ではないと思います。
/etc/watchdog.conf
成功せずにファイルに次の行を追加して追加のテストを実行しました。
ping = 127.00.0.1
interface = lan0
lan0
ifconfig
コマンドで取得したイーサネットインターフェイスの正しい名前です。それともインターフェイスをlo
pingしようとしているので、インターフェイスとして使用する必要がありますか?loopback
システムブートが完了すると表示される最後のメッセージは次のとおりです。
stopping watchdog keepalive daemon....
stargint watchdog daemon....
startpar: service(s) returnet failure: rc.local ... failed!
開始シーケンスのある時点で、ウォッチドッグキープアライブデーモンが開始され、ウォッチドッグデーモンが起動した直後に停止します。これは奇妙なことですか?それとも正常ですか? wd_keepaliveは常にオンにする必要がありますか、または監視デーモンが起動したときにオフにする必要がありますか? (これについて調査をちょっとやってみると理解すれば正常だと思って少し混乱します。)
これが私の脇腹にとげになっている。私は何が間違っていましたか?誰もが正しい方向に私を指すことができますか?
以下はドライバのソースコードです。
/**
* ALi M6117 Watchdog timer driver.
*
* (c) Copyright 2003 Federico Bareilles <[email protected]>,
* Instituto Argentino de Radio Astronomia (IAR).
*
* 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.
*
* The author does NOT admit liability nor provide warranty for any
* of this software. This material is provided "AS-IS" in the hope
* that it may be useful for others.
*
* Based on alim1535_wdt.c by Alan Cox and other WDT by several
* authors...
*
* ALi (Acer Labs) M6117 is an i386 that has the watchdog timer
* built in. Watchdog uses a 32.768KHz clock with a 24 bits
* counter. The timer ranges is from 30.5u sec to 512 sec with
* resolution 30.5u sec. When the timer times out; a system reset,
* NMI or IRQ may happen. This can be decided by the user's
* programming.
**/
#define ALI_WDT_VERSION "0.2.0"
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#define OUR_NAME "alim6117_wdt"
/* Port definitions: */
#define M6117_PORT_INDEX 0x22
#define M6117_PORT_DATA 0x23
/* YES, the two unused ports of 8259:
* 0020-003f : pic1
*
* The 8259 Interrup Controller uses four port addresses (0x20 through
* 0x23). Although IBM documentation indicates that these four port
* addresses are reserved for the 8259, only the two lower ports (0x20
* and 0x21) ar documented as usable by programers. The two ports
* (0x22 and 0x23) are used only when reprogramming the 8259 for
* special dedicated systems that operate in modes which are not
* compatible with normal IBM PC operation (this case).
**/
/* Index for ALI M6117: */
#define ALI_LOCK_REGISTER 0x13
#define ALI_WDT 0x37
#define ALI_WDT_SELECT 0x38
#define ALI_WDT_DATA0 0x39
#define ALI_WDT_DATA1 0x3a
#define ALI_WDT_DATA2 0x3b
#define ALI_WDT_CTRL 0x3c
/* Time out generates signal select: */
#define WDT_SIGNAL_IRQ3 0x10
#define WDT_SIGNAL_IRQ4 0x20
#define WDT_SIGNAL_IRQ5 0x30
#define WDT_SIGNAL_IRQ6 0x40
#define WDT_SIGNAL_IRQ7 0x50
#define WDT_SIGNAL_IRQ9 0x60
#define WDT_SIGNAL_IRQ10 0x70
#define WDT_SIGNAL_IRQ11 0x80
#define WDT_SIGNAL_IRQ12 0x90
#define WDT_SIGNAL_IRQ14 0xa0
#define WDT_SIGNAL_IRQ15 0xb0
#define WDT_SIGNAL_NMI 0xc0
#define WDT_SIGNAL_SRSET 0xd0
/* set signal to use: */
#define WDT_SIGNAL WDT_SIGNAL_SRSET
/* ALI_WD_TIME_FACTOR is 1000000/30.5 */
#define ALI_WD_TIME_FACTOR 32787 /* (from seconds to ALi counter) */
static unsigned long wdt_is_open;
static char ali_expect_close;
static int wdt_run = 0;
static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
"(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static unsigned wdt_timeout = 60;
module_param(wdt_timeout, int, 0);
MODULE_PARM_DESC(wdt_timeout, "initial watchdog timeout (in seconds)");
static int alim6117_read(int index)
{
outb(index, M6117_PORT_INDEX);
return inb(M6117_PORT_DATA);
}
static void alim6117_write(int index, int data)
{
outb(index, M6117_PORT_INDEX);
outb(data, M6117_PORT_DATA);
}
static void alim6117_ulock_conf_register(void)
{
alim6117_write(ALI_LOCK_REGISTER, 0xc5);
}
static void alim6117_lock_conf_register(void)
{
alim6117_write(ALI_LOCK_REGISTER, 0x00);
}
static void alim6117_set_timeout(int time)
{
u32 timeout_bits;
timeout_bits = time * ALI_WD_TIME_FACTOR;
alim6117_write(ALI_WDT_DATA0, timeout_bits & 0xff);
alim6117_write(ALI_WDT_DATA1, (timeout_bits & 0xff00) >> 8);
alim6117_write(ALI_WDT_DATA2, (timeout_bits & 0xff0000) >> 16);
return;
}
static void alim6117_wdt_disable(void)
{
int val = alim6117_read(ALI_WDT);
val &= 0xbf; /* 1011|1111 */
alim6117_write(ALI_WDT, val);
}
static void alim6117_wdt_enable(void)
{
int val = alim6117_read(ALI_WDT);
val |= 0x40; /* 0100|0000 */
alim6117_write(ALI_WDT, val);
}
static void alim6117_wdt_signal_select(int signal)
{
int val = alim6117_read(ALI_WDT_SELECT);
val &= 0xf0;
val |= signal;
alim6117_write(ALI_WDT_SELECT, val);
}
static void ali_wdt_ping(void)
{
int val;
/* if no run, no ping; wdt start when ping it. */
if (wdt_run) {
alim6117_ulock_conf_register();
val = alim6117_read(ALI_WDT);
val &= ~0x40; /* 0100|0000 */
alim6117_write(ALI_WDT, val);
val |= 0x40; /* 0100|0000 */
alim6117_write(ALI_WDT, val);
alim6117_lock_conf_register();
/*
printk(KERN_INFO OUR_NAME ": WDT ping...\n");
*/
} else {
printk(KERN_WARNING OUR_NAME ": WDT is stopped\n");
}
}
static void ali_wdt_start(void)
{
alim6117_ulock_conf_register();
alim6117_wdt_disable();
alim6117_set_timeout(wdt_timeout);
alim6117_wdt_signal_select(WDT_SIGNAL);
alim6117_wdt_enable();
alim6117_lock_conf_register();
wdt_run = 1;
}
static void ali_wdt_stop(void)
{
int val;
if ( wdt_run ) {
alim6117_ulock_conf_register();
val = alim6117_read(ALI_WDT);
val &= ~0x40; /* 0100|0000 */
alim6117_write(ALI_WDT, val);
alim6117_lock_conf_register();
wdt_run = 0;
/*
printk(KERN_INFO OUR_NAME ": WDT stop...\n");
*/
}
}
/**
* ali_wdt_notify_sys:
* @this: our notifier block
* @code: the event being reported
* @unused: unused
*
* Our notifier is called on system shutdowns. We want to turn the timer
* off at reboot otherwise the machine will reboot again during memory
* test or worse yet during the following fsck.
*
*/
static int ali_wdt_notify_sys(struct notifier_block *this,
unsigned long code, void *unused)
{
if (code == SYS_DOWN || code == SYS_HALT) {
/* Turn the timer off */
ali_wdt_stop();
}
return NOTIFY_DONE;
}
/**
* ali_write - writes to ALi watchdog
* @file: file handle to the watchdog
* @data: user address of data
* @len: length of data
* @ppos: pointer to the file offset
*
* Handle a write to the ALi watchdog. Writing to the file pings
* the watchdog and resets it. Writing the magic 'V' sequence allows
* the next close to turn off the watchdog.
*/
static ssize_t ali_write(struct file *file, const char *data,
size_t len, loff_t * ppos)
{
/* Can't seek (pwrite) on this device */
if (ppos != &file->f_pos)
return -ESPIPE;
/* Check if we've got the magic character 'V' and reload the timer */
if (len) {
size_t i;
ali_expect_close = 0;
/* scan to see whether or not we got the magic character */
for (i = 0; i != len; i++) {
u8 c;
if (get_user(c, data + i))
return -EFAULT;
if (c == 'V')
ali_expect_close = 42;
}
ali_wdt_ping();
return 1;
}
return 0;
}
/**
* ali_ioctl - handle watchdog ioctls
* @inode: inode of the device
* @file: file handle to the device
* @cmd: watchdog command
* @arg: argument pointer
*
* Handle the watchdog ioctls supported by the ALi driver.
*/
static long ali_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
int options;
static struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
.firmware_version = 0,
.identity = "ALi M6117 WDT",
};
switch (cmd) {
case WDIOC_KEEPALIVE:
ali_wdt_ping();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(options, (int *) arg))
return -EFAULT;
if (options < 1 || options > 512)
return -EFAULT;
wdt_timeout = options;
ali_wdt_start();
case WDIOC_GETTIMEOUT:
return put_user(wdt_timeout, (int *) arg);
case WDIOC_GETSUPPORT:
if (copy_to_user
((struct watchdog_info *) arg, &ident, sizeof(ident)))
return -EFAULT;
return 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
return put_user(0, (int *) arg);
case WDIOC_SETOPTIONS:
if (get_user(options, (int *) arg))
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
ali_wdt_stop();
return 0;
}
if (options & WDIOS_ENABLECARD) {
ali_wdt_start();
return 0;
}
return -EINVAL;
default:
return -ENOTTY;
}
}
/**
* ali_open - handle open of ali watchdog
* @inode: inode of device
* @file: file handle to device
*
* Open the ALi watchdog device. Ensure only one person opens it
* at a time. Also start the watchdog running.
*/
static int ali_open(struct inode *inode, struct file *file)
{
if(test_and_set_bit(0, &wdt_is_open))
return -EBUSY;
ali_wdt_start();
return 0;
}
/**
* ali_release - close an ALi watchdog
* @inode: inode from VFS
* @file: file from VFS
*
* Close the ALi watchdog device. Actual shutdown of the timer
* only occurs if the magic sequence has been set or nowayout is
* disabled.
*/
static int ali_release(struct inode *inode, struct file *file)
{
if (ali_expect_close == 42 && !nowayout) {
ali_wdt_stop();
} else {
printk(KERN_CRIT OUR_NAME
": Unexpected close, not stopping watchdog!\n");
}
ali_expect_close = 0;
clear_bit(0, &wdt_is_open);
return 0;
}
static struct file_operations ali_fops = {
.owner = THIS_MODULE,
.write = ali_write,
.unlocked_ioctl = ali_ioctl,
.open = ali_open,
.release = ali_release,
};
static struct miscdevice ali_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &ali_fops,
};
/*
* The WDT needs to learn about soft shutdowns in order to turn the
* timebomb registers off.
*/
static struct notifier_block ali_notifier = {
.notifier_call = ali_wdt_notify_sys,
.next = NULL,
.priority = 0
};
static int __init alim6117_init(void)
{
if (wdt_timeout < 1 || wdt_timeout > 512){
printk(KERN_ERR OUR_NAME
": Timeout out of range (0 < wdt_timeout <= 512)\n");
return -EIO;
}
if (misc_register(&ali_miscdev) != 0) {
printk(KERN_ERR OUR_NAME
": cannot register watchdog device node.\n");
return -EIO;
}
register_reboot_notifier(&ali_notifier);
printk(KERN_INFO "WDT driver for ALi M6117 v("
ALI_WDT_VERSION ") initialising.\n");
return 0;
}
static void __exit alim6117_exit(void)
{
misc_deregister(&ali_miscdev);
unregister_reboot_notifier(&ali_notifier);
ali_wdt_stop(); /* Stop the timer */
}
module_init(alim6117_init);
module_exit(alim6117_exit);
MODULE_AUTHOR("Federico Bareilles <[email protected]>");
MODULE_DESCRIPTION("Driver for watchdog timer in ALi M6117 chip.");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("watchdog");