2007年12月22日土曜日

NetBSDでWatchdog timerを使う(for ALIX) (4)

Watchdogタイマとして動かすためにsysmonフレームワークから呼び出される関数は、

  • int glxpcib_wdog_setmode(struct sysmon_wdog *smw);
  • int glxpcib_wdog_tickle(struct sysmon_wdog *smw);
の2つ。glxpcib_wdog_setmode()はWatchdogタイマのenable/disableや、最大時間を設定の際に呼び出される関数。glxpcib_wdog_tickle()は正常動作時に定期的に呼び出される関数だ。ちなみにsrc/sys/dev/sysmon/sysmon_wdog.cをみると、

/*
* sysmon_wdog_ktickle:
*
* Kernel watchdog tickle routine.
*/
void
sysmon_wdog_ktickle(void *arg)
{
[中略]
callout_reset(&sysmon_wdog_callout,
WDOG_PERIOD_TO_TICKS(smw->smw_period) / 2,
sysmon_wdog_ktickle, NULL);
}
mutex_exit(&sysmon_wdog_mtx);
}

と書いてあって、基本的には(カーネルモードのwatchdogの場合は)設定した時間の半分の周期でタイマを更新することになっていた。

今回はこれらの2つの関数を書くにあたって、共通的な要素を行う基本関数として
  • glxpcib_wdog_disable()
  • glxpcib_wdog_enable()
  • glxpcib_wdog_reset()
の3つを用意した。最初の2つはタイマーの動作を止めたり、動かしたり、カウンターが回りきったときのアクション(この場合はシステムリセット)を止めたり、動かしたりするために利用する。3つめカウンターを0にリセットするために利用する。これらを組み合わせると、
  • glxpcib_wdog_setmode()はdisable(), enable(),reset()の組み合わせとタイマ値の設定
  • glxpcib_wdog_tickle()はreset()を呼び出す
ことで実現できる。sysmon_wdogの時間しては秒単位で、カウンターに設定する値も秒単位なので特に変換のための計算も必要ない。参考までにglxpcib_wdog_setmode()をつけておく。

int
glxpcib_wdog_setmode(struct sysmon_wdog *smw)
{
struct glxpcib_softc *sc = smw->smw_cookie;

if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
mutex_enter(&sc->sc_mtx);
glxpcib_wdog_disable(sc);
mutex_exit(&sc->sc_mtx);
return 0;
}

if (smw->smw_period == WDOG_PERIOD_DEFAULT)
smw->smw_period = 32;
else if (smw->smw_period > 0xffff) /* too big */
return EINVAL;

mutex_enter(&sc->sc_mtx);
glxpcib_wdog_enable(sc);
glxpcib_wdog_reset(sc);
mutex_exit(&sc->sc_mtx);

return 0;
}

ここまでで、デバイスドライバ部分は全部できあがったのだが、ここではたと気がついたことがある。「これってどうやって正しく動いていることを検証すればいいんだろうか?」と。
Watchdogタイマはシステムが動かなかったときにリセットするために使われるわけだが、任意にシステムを止めたりする方法はあまりしらない(別のHWのデバイスドライバをごにょごにょすればできないこともないがめんどくさい)。しょうがないから、
  1. printfをいれて関数の呼び出し状態をみてみる
  2. ユーザランドで指定した値と独立してある特定の時間(10秒)までカウントが進めばリセットするカーネルを作ってみる
の2つで対処してみた。(1)で10秒と設定した場合に5秒ごとに_tickle()が呼び出されて、カウンタが0になっていることがわかる。また(2)では18秒と設定して9秒後に_tickle()が動けばリセットされないが、20秒と設定して10秒後まで_tickle()が動かないようにするとリセットがかかる、といったようにタイマが正しく動いていてかつリセット動作までつながる、ことを検証できる。

というわけで、CS5536のMFGPTをつかってWatchdogタイマを動かすデバイスドライバは書けて、正しく動いているっぽいことが分かった。最後に、NetBSDでWatchdogタイマを使うように設定する方法を書いておく。
使うコマンドは、
  • wdogctl
である。詳しいオプションはman wdogctlで見ることをお勧めするが、

# wdogctl
Available watchdog timers:
cs5536wdt, 32 second period
# wdogctl -k -p 10 cs5536wdt
# wdogctl
Available watchdog timers:
cs5536wdt, 10 second period [armed, kernel tickle]
# wdogctl -d
# wdogctl
Available watchdog timers:
cs5536wdt, 10 second period

のように使う。引数なしでwdogctlを呼ぶと使えるタイマの名前とwatchdogが起動する長さが表示される。2行目は10秒でwatchdogがかかるようにkernelがタイマを更新するモードでcs5536wdt(今回つくったタイマ)を用いてwatchdogを実行するように指示する。もう一度引数なしwdogctlを呼ぶと、設定が反映されて動いていることがわかる。
途中でwatchdogタイマを止めたいときは-dオプションをつけてwdogctlを実行すればよい。

もし、起動時に設定したい場合は/etc/rc.confにwdogctl=YES wdogctl_flags="-k -p 10 cs5536wdt"などとと書いておけば動く。wdogctl_flagsの中身はwdogctlに渡す引数と同じでよい。

というわけで、PC EnginesのALIXボードが届いてから、2日ほど楽しくカーネル遊びをする時間をとれた。いままでGPIOとかWatchdogとかを使ったことがなかったが、動くようにするために結構深い理解ができたような気がする。でも、次にこの知識が役にたつのはいつだろう(とちょっとだけ不安)。

さて、次は一番ほしい機能であるI2Cバスのサポートに手をつけたいなーと思っている。
が、まだ何もやっていないので本当にできるのか?いつになるかは?は不明。とりあえずこの3連休は手元にI2Cデバイスもロジックアナライザもないので難しそうだ。

1 件のコメント:

sexy11 さんのコメント...

情趣用品,情趣用品,情趣用品,情趣用品,情趣用品,情趣用品,情趣,情趣,情趣,情趣,情趣,情趣,情趣用品,情趣用品,情趣,情趣,A片,A片,情色,A片,A片,情色,A片,A片,情趣用品,A片,情趣用品,A片,情趣用品,a片,情趣用品

A片,A片,AV女優,色情,成人,做愛,情色,AIO,視訊聊天室,SEX,聊天室,自拍,AV,情色,成人,情色,aio,sex,成人,情色

免費A片,美女視訊,情色交友,免費AV,色情網站,辣妹視訊,美女交友,色情影片,成人影片,成人網站,H漫,18成人,成人圖片,成人漫畫,情色網,日本A片,免費A片下載,性愛

情色文學,色情A片,A片下載,色情遊戲,色情影片,色情聊天室,情色電影,免費視訊,免費視訊聊天,免費視訊聊天室,一葉情貼圖片區,情色視訊,免費成人影片,視訊交友,視訊聊天,言情小說,愛情小說,AV片,A漫,AVDVD,情色論壇,視訊美女,AV成人網,成人交友,成人電影,成人貼圖,成人小說,成人文章,成人圖片區,成人遊戲,愛情公寓,情色貼圖,色情小說,情色小說,成人論壇


免費A片,日本A片,A片下載,線上A片,成人電影,嘟嘟成人網,成人貼圖,成人交友,成人圖片,18成人,成人小說,成人圖片區,微風成人區,成人文章,成人影城

A片,A片,A片下載,做愛,成人電影,.18成人,日本A片,情色小說,情色電影,成人影城,自拍,情色論壇,成人論壇,情色貼圖,情色,免費A片,成人,成人網站,成人圖片,AV女優,成人光碟,色情,色情影片,免費A片下載,SEX,AV,色情網站,本土自拍,性愛,成人影片,情色文學,成人文章,成人圖片區,成人貼圖