12日目はタイマーです。
タイマーとは?その必要性は?
- タイマーがないと定期的に or 何秒後にXXするという処理を作りにくい
- タイマーがなくても一応実現できる。
- ただしCPUのクロックに依存したコードを書く必要がある
- 各命令や関数が何クロックで終わるのか注意する必要がある
- HLT命令のような終了するクロック数が分からない命令がそもそも使えなくなる
- HLT命令はCPUをHALT状態にして割り込みなどが発生するまで休ませる命令。
PIT
- PCでタイマーを使うにはPIT(Programmable Interval Timer)というハードを使う
- PITはIRQの0番に繋がっている
- PIT自身もクロックを持っている1,193,182Hz
- この本の内容だと周期は2Byte(65536)までしか設定できない。
- 正確に1秒を測れない
- 本の例では100Hzにするための周期として11932(0x2E9C)を設定:1193182 / 11932=99.9984914516≒100HZ
- EAX(32bit)とかを使えばできるのかな?
- Linuxのリポジトリを検索してみたところ1193182という値は使われている
- やはり本書に書かれていない何らかの方法で正確な1秒を測れる?
- この本の内容だと周期は2Byte(65536)までしか設定できない。
- あとはIDTやタイマーをシートのように資源として管理する構造体を作るだけなので省略
Beepを鳴らすプログラム(失敗)
このページ
http://oswiki.osask.jp/?(PIT)8254
を参考にビープを鳴らすプログラムを書いてみましたがうんともすんとも言わず。 前回(BIOSからメモリ容量を取得するアセンブリ)と違ってOSをぶっ壊すような自体にはならなかったが、音は鳴らない。QEMU側やCPUに何か追加の設定がいるのか、プログラムが間違っているかのどちらかだと思う
void beep(void) { io_out8(PIT_CTRL, 0x43); /*0x0a98=2712の周期を設定する(440Hz)*/ io_out8(PIT_CNT0, 0x98); io_out8(PIT_CNT0, 0x0a); beep_on(); return; }
;BeepをONにする。: IN(AL, 0x61); AL |= 0x03; AL &= 0x0f; OUT(0x61, AL);のつもり。 _beep_on: IN AL,0x61 OR AL,0x03 AND AL,0x0f OUT 0x61,AL
感想
本書のタイマーのプログラムを動かしていみましたが、1分で1秒以上ずれました。 原因は今の私にはわかりません。qemuがリアルタイムではないかもしれない、と思っていますが 「qemu realtime」などでググってもめぼしい情報はなし。
13日目もタイマーをやります