PIT 8254のページ †
- PITは「Programmable Interval Timer」の略
- 8253と8254がある
- 8253にはリードバックコマンドがない(それ以外は同じ)
- AT互換機に1個(8254)、TOWNSには2個(8253)、PC-9801には1個(8253)
- PC(IBM 5150)やXTでは8253で、ATで8254になったという説や、ATも8253で、8254になったのはPS/2という説もある
- AT互換機ではPITに1.19318MHzのクロックが与えられている。
- TOWNSではPITに307.2KHz(ch0-2)と1.2288MHz(ch4)のクロックが与えられている。
- さらに上位機種には1.00MHzのインターバルタイマ2がある(註:これは8253/8254系ではない)
- PC-9801はPITに2.4576MHz(システムクロック5MHz系時)もしくは1.9968MHz(システムクロック8MHz系時)のクロックが与えられている。
関係するI/Oポート †
AT互換機 †
- 0x0040 (8bit, R/W):カウンタ0 (IRQ0用)
- 0x0041 (8bit, R/W):カウンタ1 (メインメモリ・リフレッシュ用)
- 通常はモード2でカウント0x18を設定 --- メモリやチップセットやBIOSによっては違う
- 0x0042 (8bit, R/W):カウンタ2 (BEEP用)
- 通常はモード3 --- モード2でも多分音は出るけど、音色は変わるでしょう(このカウンタをモード3以外に設定することがハード的に可能なのかも分かりませんが)
- 0x0043 (8bit, W):コントールレジスタ
- 0x0061 (8bit, R):システムポート
- bit0:カウンタ2のGATEピンの状態
- bit1:スピーカイネーブルピンの状態
- これとカウンタ2のOUT値のANDがスピーカに接続されている
- bit2:ライト時のbit2の値が読める
- bit3:ライト時のbit3の値が読める
- bit4:(メモリリフレッシュが行われるたびに値が反転)
- bit5:カウンタ2のOUTピンの状態
- bit6:(ISAのIOCHK信号がアサートされてNMIが発生すると1になる)
- bit7:(メモリパリティエラーが発生すると1になる)
- 0x0061 (8bit, W):システムポート
- bit0:カウンタ2のGATEピンへの出力値
- bit1:スピーカイネーブルピンへの出力値(1でBEEP-ON)
- bit2:(1にすると、メモリパリティエラーを検出したときにNMIが発生)
- bit3:(1にすると、ISAのIOCHK信号でNMIが発生)
- bit4-7:リザーブ(0にするのを推奨)
TOWNS †
- 上位機種は合計で8カウンタをもち、そのうちの3つがIRQ0の発生要因として使用可能
- この他にもFM音源部にタイマ割り込みがある
- とくに1.00MHzのインターバルタイマ2とフリーランタイマレジスタは非常に有用である(8254系ではないので使いやすい)
- IRQがレベルトリガになっていることも含めて、ここまでタイマ周りが優秀なハードウェアは他にはないと思われる
- 0x0040 (8bit, R/W):カウンタ0 (IRQ0用 - インターバルタイマ用)
- 0x0042 (8bit, R/W):カウンタ1 (IRQ0用 - I/O制御用)
- 0x0044 (8bit, R/W):カウンタ2 (BEEP用)
- 通常はモード3 --- モード2でも多分音は出るけど、音色は変わるでしょう(このカウンタをモード3以外に設定することがハード的に可能なのかも分かりませんが)
- 0x0046 (8bit, W):コントールレジスタ(ch0-2用)
- 0x0050 (8bit, R/W):カウンタ3 (リザーブ)
- 0x0052 (8bit, R/W):カウンタ4 (RS-232Cのボーレート用)
- 0x0054 (8bit, R/W):カウンタ5 (リザーブ)
- 0x0056 (8bit, W):コントールレジスタ(ch3-5用)
- 0x0060 (8bit, W):割込み制御レジスタ
- bit0:ch0のタイムアウト割り込み許可(0でマスク、1で許可)
- bit1:ch1のタイムアウト割り込み許可(0でマスク、1で許可)
- bit2:BEEP出力制御(1でBEEP-ON)
- bit3-6:リザーブ(0で書き込むことを強く推奨)
- bit7:1でch0のタイムアウトフラグをクリア
- 0に戻す必要はない。書き込み時に1だと、そのときにタイムアウトフラグクリア動作が行われる、ということにすぎない。0だとその動作が起きないだけ。
- TOWNSの割り込みは全てレベルトリガであり、この動作でタイムアウトフラグを下げないと、IRQ0がかかりっぱなしになる(もちろん、ch0の割り込みそのものが不要なら、bit0を0にすればよい)。
- なお、ch1にはタイムアウトフラグを下げるためのコマンドビットはない。新しいカウントを書き込むと、自動的にタイムアウトフラグが下がる。これはch1は非周期的な割り込みを扱うために用意されたものであって、毎回カウンタの書き換えが必要だろうという設計思想に基づいている(すばらしい)。カウンタを書き換える際には、カウンタだけではなく、コマンドレジスタ、カウンタ、(カウンタ)、の順にアクセスすることをおすすめする。
- 0x0060 (8bit, R):割込み要因レジスタ
- bit0:ch0のタイムアウトフラグ(1でタイムアウトしたことを示す、0はカウント中)
- bit1:ch1のタイムアウトフラグ(1でタイムアウトしたことを示す、0はカウント中)
- bit2:ch0のタイムアウト割り込み許可、の設定値が読める
- bit3:ch1のタイムアウト割り込み許可、の設定値が読める
- bit4:BEEP出力制御、の設定値が読める
- 0x0026 (16bit, R):フリーランタイマレジスタ
- bit0-15:カウント値
- これは1マイクロ秒ごとに1ずつカウントアップされるレジスタで、たとえばある処理を挟んで2回読みとって差を求めることで、65ms以内の経過時間を測定するなどができる。非常に有用であるが、HG、HR、UG以降でしか利用できない。
- 0x0068 (8bit, W):インターバルタイマ2制御レジスタ
- このレジスタは非常に有用であるが10F以降でしか利用できない
- bit0-6:リザーブ(0で書き込むことを強く推奨)
- bit7:インターバルタイマ2のタイムアウト割り込みマスク(0で許可、1でマスク)
- 0x0068 (8bit, R):インターバルタイマ2制御レジスタ
- このレジスタは非常に有用であるが10F以降でしか利用できない
- bit0-4:リザーブ
- bit5:タイムアウトフラグが0になっていないときにさらにタイムアウトすると1になる(オーバフラグ)
- bit6:タイムアウトフラグ(1でタイムアウトあり)
- bit7:インターバルタイマ2のタイムアウト割り込みマスク、の設定値が読める
- このレジスタをリードすると、リード直後にタイムアウトフラグとオーバフラグは0クリアされる
- 0x006a (16bit, R/W):インターバルタイマ2周期レジスタ
- bit0-15:割り込み周期設定値(マイクロ秒単位で設定)
- このレジスタは非常に有用であるが10F以降でしか利用できない
- 0x006c (8bit, W):1マイクロ秒WAITレジスタ
- このレジスタは非常に有用であるが10F以降でしか利用できない
- bit0-7:リザーブ(0で書き込むことを強く推奨)
- このレジスタへの書き込み動作で、1マイクロ秒のwaitがかかる
- 0x006c (8bit, R):1マイクロ秒WAITレジスタ
- このレジスタは非常に有用であるが10F以降でしか利用できない
- bit0-6:リザーブ
- bit7:常に0(ここが1だと10Fより前のモデルであることを意味する)
PC-9801 †
- 0x0071 (8bit, R/W):カウンタ0 (IRQ0用)
- 0x0073 (8bit, R/W):カウンタ1 (メインメモリ・リフレッシュ用の機種と、BEEP用の機種とがある)
- BEEP音程が変わらない元祖/E/F/Mは前者、VF/VM/XL以降は後者。U/XAは不明
- モード3で使用。
- 0x0075 (8bit, R/W):カウンタ2 (BEEP用)
- 0x0077 (8bit, W):コントールレジスタ
- 0x3fdb (8bit, R/W):カウンタ1 (多くの機種のノーマルモードでは、こちらでないとアクセスできない。BEEP用)
- 0x3fdf (8bit, W):コントールレジスタ
- ここにライトすることと0x0077にライトすることは全く同じ
8254の基礎 †
- 8524は内部に16bitのカウンタを3つ持っている。それぞれに外部からクロックが与えられ(でもたいていは同一クロックを与えているようだけど)、またそれぞれを別々のモードで駆動させることができる。
- カウントは原則としてデクリメントであり、周期的なモードではカウントが0になった瞬間に設定値が再ロードされる(つまり、カウント値0という値は読み出せない)。
- ハードウェア的には、以下の3つの信号ピンが関係している(これらはカウンタの個数だけある)。
- CLK:クロック(カウンタをデクリメントするためのクロック)
- GATE:ゲート(カウンタを始動させたり一時停止させたり再開させたりするためのピン)
- OUT:アウト(カウント値によって制御されるPITの出力ピン、これがIRQのトリガになったりBEEP出力になったりしている)
- カウントは、2進数カウントモードと、BCDカウントモードがある。純粋な8254にはBCDモードがあるが、PCのチップセットに集積されたものについては、BCDモードが省略されている可能性があるのでお勧めできない。
- 8254は、現在のカウント値をラッチによって読み取ることができるが、設定値を読取る方法はない。設定値を知りたければ、カウンタを何度もリードして監視して、最大値を取得するしかない。
- リードバックコマンドを使って、少ないサンプリング数で正確な設定値を推測するテクニックもある。
- コントロールレジスタの各ビットの意味は次の通り。
- bit0:カウントモード
- bit1-3:カウントモード
- 000:モード0(ターミナルカウント)
- 001:モード1(プログラマブルワンショット)
- x10:モード2(レートジェネレータ)
- x11:モード3(方形波レートジェネレータ)
- 100:モード4(ソフトウェアトリガストローブ)
- 101:モード5(ハードウェアトリガストローブ)
- bit4-5:カウンタアクセスモード
- 11:16bitリードロード(下位8bit、上位8bitの順)
- 10:上位8bitのリードロード
- 01:下位8bitのリードロード
- 00:カウント値ラッチ
- bit6-7:カウンタチャンネル指定
- 00:カウンタ0
- 01:カウンタ1
- 10:カウンタ2
- 11:リードバックコマンド(後述)
- カウント値を設定するには、一般に以下の手順で行なう。
- コントールレジスタに設定したいチャンネルのモードを設定。直前と同じモードであっても、これを設定しないとうまく動作しないことがある。
- そして、目的のカウンタに値をセット。8bitモードなら1回のアクセスになるし、16ビットモードなら、下位8bit、上位8bitの順に書き込む。
- モード設定から、カウント値の設定完了までの間に、他のチャンネルのモード設定をしたり他のチャンネルのカウンタへ読み書きすると、設定も挙動も不定となる。
- カウント値を読み取るには、一般に次の手順で行なう。
- コントールレジスタを使って、読み取りたいチャンネルに対してラッチを実施。
- 読み取りのカウンタアクセスモードは、書き込み時のモードと同じになる。
ものぐさなひとのために †
- ぶちゃっけ、読者の多くはAT互換機でタイマーとBEEPの設定をすると思うので、そこだけをぱぱっと説明。
- IRQ0の割り込み周期変更:
- AL = 0x34; OUT(0x43, AL);
- AL = 割り込み周期の下位8bit; OUT(0x40, AL);
- AL = 割り込み周期の上位8bit; OUT(0x40, AL);
- これでおしまい。
- 割り込み周期に0を指定すると65536を指定したとみなされる。実際の割り込み頻度は、クロック/設定カウント値。つまり、1000を指定すれば、1.19318KHz。10000なら119.318Hz、といった具合。例えば11932を設定すれば、約100Hzになって、10msごとに割り込むようになるわけだ。
- BEEP音の制御:
- 音程操作:
- AL = 0xb6; OUT(0x43, AL);
- AL = 設定値の下位8bit; OUT(0x42, AL);
- AL = 設定値の上位8bit; OUT(0x42, AL);
- 設定値0は、65536として扱われる。
- これで発振される音程は、クロック/設定カウント値。つまり、1000を指定すれば、1.19318KHz。10000なら119.318Hz、といった具合。例えば2712を設定すれば、約440Hzになる。
- BEEPのON/OFF:
- これはI/Oポート0x61を使う。
- ON: IN(AL, 0x61); AL |= 0x03; AL &= 0x0f; OUT(0x61, AL);
- OFF: IN(AL, 0x61); AL &= 0xd; OUT(0x61, AL);
6つのモード †
こめんと欄 †
- ここにKさんが書いてくださった内容を参考にしてMonaのpic.cpp内のタイマの設定はかかれる予定です。 -- ひげぽん? 2004-01-09 (金) 21:55:07
- 少しは役に立ったようでうれしいです。 -- K 2004-01-10 (土) 00:16:17
void setTimerInterval(dword ms) {
dword timerCounter = ms * 1193.18;
outportb(0x43, 0x34);
outportb(0x40, timerCounter & 0xff);
outportb(0x40, timerCounter >> 8);
}
- タイマ割込み周期設定関数を作ってみました。引数はmsです。 -- ひげぽん? 2004-01-11 (日) 03:51:43
- Monaで上記の関数をテストしましたがきちんと動いているようです。 -- ひげぽん? 2004-01-11 (日) 17:26:52
- 実機でテストしたところカーネルが起動中に止まってしまったので現在調査中です。 -- ひげぽん? 2004-01-11 (日) 21:05:49
- 確かPC-9801VX辺りのハードウェアマニュアルにもi8254搭載と書いてあったと思います。全機種通して保証されてるのがi8253というだけで、多分多くの機種がi8254相当搭載なんだと思います。ただ判別方法が無さそうなんですよね……。 -- 通りすがり 2010-11-15 (月) 14:27:17
- PC-98の場合、アーキテクチャとして保証されてるのが8253の機能というだけで、実際には8254互換だったりするようですね。確かPC-9801VXのマニュアルには8254相当と書いてあったと思います。 -- 名無しさん 2012-03-11 (日) 04:20:03
story - Lu register -0x3fdb (8bit and R/W): The counter 1 (unless this way it is, it cannot access with the normal mode of many types. The for BEEP) -- you use with mode 3. -0x3fdf (8bit and W): The short story - the Lu register -- here especially and the 0x0077 which the light/write are done as for the light/write doing completely the same * the foundation of 8254 as for -8524 3 it has the counter of the 16bit inside. Respectively, it can give the clock from outside and (with mostly, as given the identical clock, but, it is possible in addition to drive each one with separate mode. - Count as a general rule is decrement, with periodic mode command is reloaded instantaneously count has become 0 (to be plugged every single count value 0 value cannot read out). - Hardware, three signal pins below are related, (as for these there is just a quantity of the counter). --CLK: The clock (the clock in order decrement to do the counter) the --GATE: The pin in order the gate (you make the counter start and/or make stop and/or at one time to reopen) the --OUT: The output pin of the PIT which is controlled out (by count value, the り which has become the り cBeep output where this had become the trigger of the IRQ has done) - count, is a binary count mode and a BCD count mode. There is a BCD mode in pure 8254 being to be a possibility BCD mode being abbreviated, but concerning those which were accumulated to the tip/chip set of the PC, we cannot recommend. As for -8254, it can grasp present count value with latch, but there is no method of grasping command. We probably would like to know command, the counter leading/reading many degrees, watching, there is no other choice but to acquire maximum value. -- using lead/read back command, there is also a technique which at the little presumes accurate command number of samplings. - Meaning of each bit is of control register as follows. --bit0: Count mode ---0: Binary count ---1: BCD count --bit1-3: Count mode ---000: Mode 0 (terminal count) ---001: Mode 1 (programmable one shot) ---x10: Mode 2 (rate generator) ---x11: Mode 3 (square wave rate generator) ---100: Mode 4 (software trigger strobe) ---101: Mode 5 (hardware trigger strobe) --bit4-5: Counter access mode ---11: 16bit lead/read load (order of subordinate 8bit and superior 8bit) ---10: Lead/read load of superior 8bit ---01: Lead/read load of subordinate 8bit ---00: Count value latch --bit6-7: Counter channel appointment ---00: Counter 0 ---01: Counter 1 ---10: Counter 2 ---11: Lead/read back command (later description) - count value is set, it does generally with procedure below. -- the short story - it sets the mode of the channel which would like to set to the Lu register. Being the same mode as immediately before, it does not set this you question, there are times which it sows and does not operate. You set value to -- and the intended counter. If 8bit mode it becomes the access of 1 time if and, 16 bit mode, you write to the order of the subordinate 8bit and the superior 8bit. When -- from mode setting, during to completion of setting of count value, it does the mode setting of the other channel and/or reads and writes to the counter of the other channel, setting and behavior become uncertainty. - To grasp count value, it does generally with the following procedure. -- the short story - using the Lu register, it executes latch vis-a-vis the channel which we would like to grasp. -- counter access mode of reading becomes same as the mode when writing in. The *** thing ぐ because - the spotted ゃ っ け, you think many of the reader because of one, it sets the timer and the BEEP with the AT compatible machine, just there the ぱ suddenly explanation. -IRQ0 interruption periodic modification: --AL = 0x34; OUT (0x43, AL); --AL = it interrupts, the subordinate 8bit of period; OUT (0x40, AL); --AL = it interrupts, the superior 8bit of period; OUT (0x40, AL); -- with this end. When -- 0 is appointed to interruption period, it is regarded 65536 was appointed. As for actually interruption frequency, clock / setting count value. In other words, if it appoints 1000, the 1.19318kHz. If 10000 the 119.318hz, with the condition which was said. For example if 11932 is set, becoming approximately 100Hz, it is the case that it reaches the point where it interrupts every 10ms. -BEEP control of sound: -- musical interval operation: ---AL = 0xb6; OUT (0x43, AL); Subordinate 8bit of ---AL = command; OUT (0x42, AL); Superior 8bit of ---AL = command; OUT (0x42, AL); --- command 0 is handled as 65536. --- as for the musical interval which oscillates with this, clock / setting count value. In other words, if it appoints 1000, the 1.19318kHz. If 10000 the 119.318hz, with the condition which was said. For example if 2712 is set, it becomes approximately 440Hz. The ON/OFF of --BEEP: --- this uses the I/O port 0x61. ---ON: IN (AL and 0x61); AL |= 0x03; AL &= 0x0f; OUT (0x61, AL); ---OFF: IN (AL and 0x61); AL &= 0xd; OUT (0x61, AL); * Six modes * it is to include with the column - with the contents the K writing here as a reference [ [ as for setting of the timer inside the pic.cpp of the Mona ] ] it is the schedule which can be caught. -- [ [ [ [ the self-depreciation ぽ it is ] ] ] ] the SIZE (10) { 2004-01-09 (the gold) 21:55:07 } - a little as is useful, it is delightful, is. -- [ [ K ] ] SIZE (10) { 2004-01-10 (Saturday) 00:16:17 } void setTimerInterval (dword ms) { dword timerCounter = ms * 1193.18; Outportb (0x43, 0x34); Outportb (0x40, timerCounter & 0xff); Outportb (0x40, timerCounter >> 8); } - You tried making timer interruption periodic setting function. Argument is the ms. -- [ [ [ [ the self-depreciation ぽ is ] ] ] ] the SIZE (10) { 2004-01-11 (day) 03:51:43 } - [ [ above-mentioned function was tested with the Mona ] ], but it seems that is moving securely. -- [ [ [ [ the self-depreciation ぽ it is ] ] ] ] the SIZE (10) { 2004-01-11 (day) 17:26:52 } - when it tests with the apparatus it meaning that the kernel stops while starting, presently it is in the midst of investigating. -- [ [ [ [ the self-depreciation ぽ it is ] ] ] ] the SIZE (10) { 2004-01-11 (day) 21:05:49 }