(H8移植編その2第2回)タイマをキュー管理する

2010/04/04

あなたは 人目のお客様です.

前回のタイマの実装の最後にちょろっと書いたのだけど,通常のシステムでは タイマは有限の資源である.どういうことかというと,たとえばH8/3069Fは 8ビットタイマを4チャネル,16ビットタイマを3チャネルもっているので 合計7つのタイマ資源を利用できる.

しかしこれを各サービスが専用で利用してしまうと,7つまでしかタイマは利用 できないことになる.たとえばあるスレッドが1秒間スリープしようとして ひとつのタイマを利用したとしよう.この場合,そのタイマはそのスレッドが 利用しているので他のスレッドは利用できない.ということは7つのスレッドが スリープしようとした場合,8個目のスレッドは利用できるタイマが無いので スリープできない,ということになる.

これでは困るのでどうするかというと,タイマ要求をキュー管理して, とりあえずタイマには一番近い時刻をセットする.で,そのタイマがかかったら そのタイマをかけたスレッドに通知し,さらに次のタイマをセットする, というようにタイマのチェインにして次々にタイマをかけるという方法が思いつく.

ただこの方法だと,正確な時刻でのタイマ発生は難しい.チェインによる処理のため 誤差が蓄積していくからだ.あとキュー検索が必要になるので,リアルタイム制御には 向かない.ということで厳密な時刻でのタイマが必要な場合にはタイマ資源を直接 利用して(ただしこっちには資源の数に上限がある),なんとなく1秒くらい待てば いいや的な精度はどーでもいいタイマには,キュー管理のサービスを提供するという 区分けをすればよいことになる.

で,キュー管理を実装してみた.以下,修正したソース. なおブートローダーは前回と同じ.

タイマをキュー管理するサービスとして「タイマ・ドライバ・スレッド」を timerdrv.c として実装した.タイマ・ドライバ・スレッドにメッセージを送信すると タイマをかけ,指定した時間が経過するとメッセージを返してくるという実装に なっている.

具体的には struct timerreq という構造体を利用して MSGBOX_ID_TIMDRIVE という メッセージボックスにメッセージを投げると,指定時間経過後にメッセージが 返ってくるという動作になっている. struct timerreq にはタイマ時間と,あとタイマ発生時にメッセージを投げてほしい メッセージボックスのIDを指定する.

MSGBOX_ID_TIMDRIVE へのタイマ要求は timerdrv.c で実装されている タイマ・ドライバ・スレッドが受ける. タイマ・ドライバ・スレッドは要求をキュー管理し,もっとも近い時間の要求を CPUのタイマにセットする.タイマ割り込みが発生したら タイマ・ドライバ・スレッドに通知し,さらにタイマ・ドライバ・スレッドで キューの先頭にあるタイマ要求が満了したと判断して,そのタイマ要求で指定されて いるメッセージボックス宛にメッセージを返す.

この手のタイマ処理は,タイマを設定する直前に前回設定したタイマが発生して しまうなどの「すれ違い」を考慮する必要がある.まあ timerdrv.c はすれ違いを 多少意識して書いてはあるのだけど,厳密な確認はしていないので, たとえば現在設定されているタイマが満了する直前に新しいタイマ要求が 発行されたりすると,もしかしたらへんな動作になるかもしんない. まあこのへんはそのうちきちんと検証しよう.

実際に動作させてみよう.今回はブートローダーには手を入れていないので, ブートローダーは前回のままでよし.いつもどおりの手順でOSをロードして実行する. 以下,実行結果.

kzload> run
starting from entry point: ffc020
kozos boot succeed!
command> timerready.
ready.

timer start.
command> expired.
command> ready.
timerready.

timer start.
command> expired.
command> ready.
timerready.

timer start.
command> ready.
expired.
command> ready.
timer
timer start.
command> ready.
expired.
command> timerready.

timer start.
command> expired.
command> ready.
ready.
3秒おきに「ready.」のメッセージが出力され,「timer」と入力すると 1秒後に「expired.」のメッセージが出力されている.まあまあちゃんと動作して いるみたいだ.

さて,なぜ最近タイマの実装を行ったかというと,TCP/IPを実装するという目論見が あるからだ.TCP/IPの実装のためには,一定時間経過したら再送するというような, タイマ動作が必要になってくる.ということでまずはタイマサービスを実装して, 次に内蔵RAMだけでetherのパケット処理をするのはきついのでDRAMを動くように して,さらにLANコントローラを動かして,TCP/IPを実装する,という順番で実装 していこうかな,と.ブログで書いたようにarduinoもやりたいのだけど, arduinoがまだ到着していないので,とりあえずH8のほうの開発を進めているという 感じ.arduinoが入手できたあとにどっちを進めるかは気分次第かな.

で,簡易なTCP/IPを実装してwebサーバとか動かして,さらにGDB対応して デバッガも利用できるようにして,さらにROM化して電源ONでそのままブートできる ようにする,というとこまで持っていきたい(もちろんすべてスクラッチ開発で). ここまでをフルスクラッチで作り上げてさらに3000行程度におさめることができれば, 組み込みOS初心者向けの教材として,なかなか面白いんではないかと.


メールは kozos(アットマーク)kozos.jp まで