Operating Systems Development Series
8253 Programmable Interval Timer
by Mike, 2007

8253 PIT Microcontroller with all pins labled

はじめに

ようこそ!:)

このチュートリアルでは、Intel 8253 Programmable Interval Timer (PIT) のシステムタイミングとプログラミングについて知りた いことすべてをカバーします。

8253 PITは長い歴史を持ち、ほぼすべてのx86 PCで重要な役割を担ってきました。これは「システムクロック」であり、PC内の多くの非常に重要な機能を担っています。この...この「チップ」は、もはや独立したチップとしてではなく(正確にはDIP(Dual Inline Package)として)、マザーボードのサウスブリッジチップセットに統合されて配布されています。

しかし、8253のすべてが残っている。そのため、8253の入出力設備、ハードウェア、そしてプログラミングの方法は変わりません。このDIPと古いDIPの間には(速度以外の)違いはないので、物事をシンプルにするために古い8253のDIPを見ることにします。

このチュートリアルの冒頭の写真は、私たちが見てプログラミングするものを示しています。

それではお楽しみください。)

プログラマブルインターバルタイマ

プログラマブルインターバルタイマ(PIT)は、プログラムされたカウントに達すると割り込みをトリガするカウンタです。8253と 8254マイコンは、i86アーキテクチャで使用できるPITで、i86互換システムのタイマとして使用されています。

これらのPICには3つのタイマーがあり、それぞれ異なる用途に使用されます。最初のタイマーは通常システムクロックとして使用され、タイマー2はRAMリフレッシュに使用され、タイマー3はPCスピーカーに接続されています。すべての接続を確認するのは少し後なので、今はあまり詳しく説明しません。

その代わりに、この有名なPITの一つを詳しく見てみましょう......。8253マイクロコントローラです。

8253のハードウェア

このため、まず8253のハードウェアを取り上げ、それがどのように動作し、PCの他の部分と接続されているかを学びます。 また、内部レジスタ、ピン配置、コマンドワードなど、ソフトウェア側で必要となる部分についても見ていきます。

8253のハードウェア説明

8253 PITはシンプルなインターフェースで、プログラミングはそれほど難しくありません。

これが私たちがプログラムするチップです。

ここに完全なピン配置があります。このチュートリアルでは、これらのピンを参照しますので、それらが何であるかを知っておくことが重要です。

  • D0...D7:8ビットデータ線。データバスに接続されており、コマンドの読み取りと送信を行うことができます。
  • CLK 0, CLK 1, CLK 2:クロック入力端子です。3つのカウンタに対応する3つのピンがあります
  • OUT 0, OUT 1, OUT2:出力データライン。3つのカウンタに対応する3つのピンがあります。
  • GATE 0、GATE 1、GATE 2:ゲートデータ線。3つのカウンタに3つのピンがあります。
  • GND:グランド
  • Vcc:入力電圧
  • WR:ライトイネーブル。この線がアクティブになると、8253にデータを書き込むことを知らせます。
  • RD:リード・イネーブル。このラインがアクティブのとき、8253にデータを読み出すことを知らせます。
  • CS:チップ・セレクト信号。チップ・セレクト信号
  • A0、A1:アドレス・ライン。どのレジスタにアクセスしているかを判断するために使用します。
悪くはないです。ここには、見ておかなければならない重要なピンがいくつかあります。

D0-D7ピンは、システムのデータ・バスに接続されています。これらのピンは、コントローラへのデータ送信やデータ読み出しの際に、データを伝送します。

Vccと GNDで回路が完成します(電圧入力、グラウンド出力)。

WRピンは、書き込み中であることをコントローラに伝えます(データピンの入力に期待)。このピンの信号が "Low "の場合、現在データを送信中です。RDピンは、これと非常によく似ていますが、代わりにデータを読み取ることをコントローラに知らせます。CSピンは、RDピンとWRピンに対するコントローラの動作を決定する特別なピンです。CSピンが "Low "であれば、コントローラはRDおよびWRピンに応答し、"Low "でなければ、RDおよびWRピンは無視されます。CSが "L "でない場合、それらは無視されます。WRと RDはシステム制御バスに接続します。CSピンは、ポートi/o操作のために、システム・アドレス・バスに接続します。

A0A1ピンは、システム・アドレス・バスに接続され、アクセスするレジスタを決定するために使用されます。これらのピンとWRRDの組み合わせにより、コントローラはレジスタへの読み出し、またはレジスタからの読み出しを判断することができます。

CLK、OUT、GATEピンの3つのグループに分かれていることに注目してください。8253/8254マイコンは、3つの独立したタイマーを備えているのです。

この仕組みについて詳しく見ていきましょう。

8253のハードウェアカウンタ

8253は、3つのカウンタで構成されています。カウンタ0、カウンタ1、カウンタ2です。各カウンターには、2つの入力ピンがあります。CLK(クロック入力)とGATE、そして出力用のピンが1つ--OUTです。

3つのカウンタがあるので、システム内で異なる目的で使用されます。各カウンタは、16ビットのダウンカウンタです。

一般的なコンピュータは、1つ目のタイマーのOUTピンをプログラマブル割り込みコントローラ(PIC)に接続し、クロックティックごとに割り込みを生成します。 これは通常、システムタイマーとして使用されます。2つ目のカウンタは、DRAMメモリをリフレッシュするためにメモリコントローラへのタイミング信号を生成するために使用されていた。3つ目のカウンタは、PCのスピーカーにトーンを発生させるために使用されています。

PITは、カウンタが0になるとOUTピンを使ってこれらのデバイスに信号を送ります。 PITのカウンタが0になると、単に折り返して再びスタートします。

CLKは、タイマーのクロック入力です。現在の動作モードにより、GATE端子と併用される場合があります。 GATEの電流が、Low、Rising、Highの場合による動作は、以下のとおりです。

GATE 入力端子動作
モード Low または Low になる 立ち上がり High
0 カウントを無効にする - カウントを有効にする
1 - カウントを開始し、次のCLKの後にOUTをリセットします。 -
2 カウントを無効化し、OUTをHighに設定します。 カウンタを再ロードし、カウントを開始します。 カウントをイネーブルにする
3 カウンタ無効、OUT=High カウント開始 カウント開始
4 カウント停止 - カウントを開始します。
5 - カウントを開始します。 -

8253のカウンターは、チャンネルとも呼ばれます。8253/8254 の PIT には 3 つのチャンネルがあるので、それぞれのチャンネルをもっと詳しく見てみましょう。

チャンネル0

チャンネル0は、8259 PICに接続され、割り込み要求(IRQ)を発生させることができます。PITのOUTピンは、PICのIR0ピンに接続されています。通常、BIOSはこのチャンネルを65536カウントで設定し、18.2065Hzの出力周波数を与えます。これは54.9254ミリ秒ごとにIRQ 0を発生させます。

ほとんどのx86マシンで使用される主要なタイマーです。クロックレート(カウンター0のCLKピンから信号)は1193181.6666...Hzで、NTSCの3分の1です。Hzで、NTSCのサブキャリア周波数の3分の1である。これは、旧来のCGA PCとの互換性を保つために必要なものです。

チャンネル0は通常、システムクロックとして動作するようにプログラムされていることが多い。これは、チャンネル0のOUTピンをPICのIR0ラインに間接的に接続することで可能になる。設定するモードによっては、タイマーを適切な周波数に設定し、一定速度でPICのIR0ラインを有効にすることができます。その後、自分自身をリセットして、もう一度やり直す。PICはハードウェア割り込みの処理に使うので、まずPICを再プログラミングする必要がある。

最も低い番号(IR0)の割り込みに接続されているため、他のすべてのハードウェア割り込みよりも高い優先度も持っています。

最低周波数は、古いDOSシステム(まだ残っているのでしょうか)のコンピュータで通常使用される約18.2Hzで、最高周波数はメガヘルツ強です。

リアルモードOSでは、BIOSは通常IRQ0が発生した回数を0000:046Cにインクリメントし、実行中のプログラムが読み取ることができるようにします。

チャンネル1

多くのビデオカードとBIOSは、独自の用途のために2番目のチャネルを再プログラムすることがあります。このチャンネルはもともと、メモリコントローラにDRAMメモリをリフレッシュさせるためのタイミングパルス信号を生成するために使われていました。現代では、リフレッシュはメモリコントローラによって行われるため、これは不要になりました。このため、どのような機器がこのカウンタを使用するかは保証されていません。

チャンネル2

このチャンネルは、PCスピーカーに接続して音を出します。PCスピーカーは通常、2レベルの出力で矩形波を出すことになっています。しかし、2段階の矩形波の間を行き来することが可能です。これをPWM(Pulse-Width Modulation)と呼びます。

このチャンネルは、モード3用にプログラムし、トーンの周波数レートを設定することで設定できます。

また、PCスピーカを直接プログラムすることもできます。チュートリアル7を見ると、PCスピーカはポート0x61にマッピングされていることがわかります。このポートは、スピーカーの動作方法を定義しています。

  • ビット0:設定(1)すると、スピーカーの状態はビット1に従います。
  • ビット1:セット(1)すると、スピーカーは PIT を使用します。セット(0)しない場合、スピーカーは PIT への接続を無効にします。
ビット0が設定されている場合、バイトの残りの部分には、音の周波数を表すビットのパターンが含まれています。スピーカーから最大8ビットの音を発生させることができます。これはちょっとクールですが、トリッキーなことです。

また、デバイスがPITを使用しないようにすることもできることに気づくはずです。起動時にBIOSは、スピーカーがPITチャンネル2を使用するように設定し、モード3で動作させます。タイミングに問題があるため、スピーカーは PIT を使用するように設定することを推奨します。

以下はその例です。

; disables the speaker, and stop using channel 2 mov dx, 0x61 out dx, 0 ; generates tone from speaker out dx, 11111101b

まとめ

一度カウンターを設定すると、別の制御ワードで変更されるまで、その状態が維持されます。

これらのカウンタを使って、いくつかクールなことができそうですね。チャンネル1はもう使われていないので、安全だと判断して使うことはできません。このため、チャネル0と2に固執することをお勧めします。

チャンネル0は、割り込みハンドラを起動するのに使うことができます。割り込みハンドラは、カーネルが使用するカウンタをインクリメントすることができます。この特別な小さなカウンタ変数は、システムで非常に重要な役割を果たします。システムタイマです。この辺はすぐにわかると思いますので、ご心配なく;)

さて、ピンの構成と、異なるデバイスがタイミングをとるために使用する3つのタイマーを見てきました。次は何でしょうか?

これらのタイマーをプログラムするとき、初期化しなければなりません。各チャンネルは6つの異なるモードをサポートしていることを忘れないでください。これらのモードの中にはとても便利なものがあります。他のモードはそうではありません。これらのモードを理解するために、それぞれのモードを見てみましょう。 少し詳しくなりますが、あなたはすでに知っていたか、それを期待していたと思いますので、注意してください :)

8253チャンネルモード

各カウンタは、6つのモードのうち1つでプログラムできることを忘れないでください。これは、初期化制御語(ICW)をコントローラに送信することで行われます。このコマンドワードのフォーマットについては、後ほど説明します。とりあえず、各モードについて見てみましょう。

モード0:端子カウントによる割り込み

このモードでは、カウンタは初期値COUNTにプログラムされ、その後、入力クロック周波数(CLK信号)に応じた速度でカウントダウンします。COUNTが0の時、コントロールワードが書き込まれた後、カウンタはOUTピンを有効にし(ラインをハイにする)、接続されたデバイスに信号を送ります。カウントはCOUNTがプログラムされた1クロック後に開始されます。OUTラインは、カウンタが新しい値または同じ値で再ロードされるか、別の制御ワードがコントローラに書き込まれるまで、ハイのままです。

このモードは基本的に、0までカウントダウンするタイマーを設定するもので、その後、新しいカウント数を再ロードするか、新しい制御ワードを入力してカウンターを再初期化する必要がある。

モード1:ハードウェアトリガーワンショット

このモードでは、カウンタはあるクロック数ごとに出力パルスを与えるようにプログラムされています。OUTラインは、コントロール・ワードが書き込まれるとすぐにハイ・レベルに設定されます。COUNTが書き込まれた後、カウンタはGATE入力の立ち上がりエッジまで待ちます。パルス出力中にトリガが発生した場合、8253は再びトリガされます。GATEの立ち上がりエッジが検出されてから1クロック後に、OUTはLOWとなり、COUNTが0になるまでLOWのままです。 その後、次のトリガまでOUTはHighとなり、再びGATE入力の立ち上がりエッジが検出されるまで待ちます。

モード2:レート・ジェネレータ

このモードは、一般的にリアルタイムシステムクロックの生成に使用される"divide by n "カウンタとして設定されます。

カウンタは初期COUNT値にプログラムされます。カウントは次のクロックサイクルで開始されます。OUTはCOUNTが1になるまでHighのままです。その後、OUTは1クロックパルスの間、LOWになります。その後、OUTはハイに戻され、COUNTは初期値にリセットされます。このプロセスは、新しい制御ワードがコントローラに送信されるまで繰り返されます。

ハイパルスの間隔はCOUNTの現在値に依存し、以下の式で計算されます。

COUNT = input (Hz) / Frequency of output

COUNTは0になることはなく、nから1までしか変化しません(nはCOUNTの初期値)。

さて、ちょっと立ち止まってみましょう。カウンタ0がPICに接続されているのを覚えていますか?カウンタ0のOUTラインは間接的にPICのIR0ラインに接続されている。それを知っていれば、IR0ラインがLowの時、PICは我々が定義したIRQ 0ハンドラーを呼び出すだろう。

カウンターをモード2に設定すれば、一定速度で割り込みを発生させるタイマーを設定することができる。あとは、上記の式からCOUNTの値を決定するだけです。これは、オペレーティングシステムのシステムタイマーを設定する際によく使用されます。結局、IRQ 0は、定義した周波数で、クロックティックごとに呼び出されることになります。

そう、Mode 2は実に重要なモードなのです。

モード3:矩形波ジェネレータ

このモードは、モード2とよく似ている。COUNTが奇数の場合、OUTは(n+1)/2カウントの間、HIGHになります。COUNTが偶数の場合、OUTは(n-1)/2カウントの間、LOWとなります。

その他は、Mode 2と同じです。COUNTの初期値を設定するために、Mode 2の計算式を使う必要があります。

スピーカーがPITを使用するように設定されている場合、通常使用するチャンネルはこのモードを使用するように設定する必要があります。

モード4:ソフトウェア・トリガ・ストロボ

カウンタには初期値としてCOUNTが設定されています。カウントは次のクロックサイクルで開始されます。OUTは COUNTが0になるまでHighのままです。その後、カウンタは1クロックの間OUTをLowにします。その後、OUTを再びHighにリセットします。

モード5:ハードウェアトリガーストローブ

カウンターは初期値COUNTにプログラムされています。OUTは、コントローラがGATE入力の立ち上がりエッジを検出するまでハイのままです。このとき、カウントが開始されます。COUNTが0になると、OUTは1クロックの間LOWになります。その後、OUTは再びHighになります。このサイクルは、コントローラが次のGATEの立ち上がりエッジを検出すると繰り返されます。

8253のレジスタ

8253には、アクセス可能ないくつかのレジスタがあります。これらのレジスタのほとんどは、互いに非常によく似ているので、わかりやすくするために、同じ表で説明します。この表は、各レジスタと、8253の対応するラインがアクティブになったときの機能を示しています。RDラインとWRラインが、読み取りと書き込みの動作を決定していることに注目してください。また、A0ラインとA1ラインが、どのレジスタにアクセスしているのかを決定していることにも注目してください。

チュートリアル7のポート表を見ると、システムタイマはBIOSによってポート0x40-0x4Fにマッピングされていることがわかります。各ポートアドレスは1バイトの大きさです。

8253 PIT Internal Registers
Register Name Port Address RD line WR line A0 line A1 line Function
Counter 0 0x40 1 0 0 0 Load Counter 0
0 1 0 0 Reads Counter 0
Counter 1 0x41 1 0 0 1 Load Counter 1
0 1 0 1 Reads Counter 1
Counter 2 0x42 1 0 1 0 Load Counter 2
0 1 1 0 Reads Counter 2
Control Word 0x43 1 0 1 1 Write Control Word
NA 0 1 1 1 No Operation

0x44-0x4fの他のポートアドレスは全て未定義です。

実行する操作に応じて、システムが正しいラインをアクティブにします。カウンタレジスタを設定する場合、まずコントローラにどのようにロードするのかを知らせる必要があります。これは、最初にコントロールワードを設定することで行われます。それでは、これらのレジスタを詳しく見ていきましょう。

カウンタレジスタ

各カウンタレジスタには、PITがカウントダウンに使用するCOUNT値が格納されます。レジスタへの書き込み、読み出しは、まずPITにコントロールワードを送る必要があります。なぜ直接できないのかと思われるかもしれません。これには理由があり、データのサイズに関係しています。PITのデータラインは8本(D0-D7ピン)しかありません。しかし、カウンタレジスタはすべて16ビットで、8ビットではありません。

PITは、カウンタレジスタに書き込むデータをどのようにして知ることができるのでしょうか?カウンター・レジスタの16ビットのうち、どのバイトを設定しているのか、どうやって知ることができるのでしょうか?そうではありません。コマンドワードを送信することで、PITにデータが来ることを知らせ、そのデータをどう処理するかを知ることができます。これについては、次に説明します。

コントロールワードレジスタ

この点が重要になります。

このレジスタは、コントローラの動作モードを決定し、設定するために使用される重要なレジスタです。RD、A0、A1ラインをイネーブルにすることで、このレジスタにアクセスできます。このレジスタは書き込みのみ可能で、読み出しはできません。

コントロールワードレジスタは、シンプルな形式を採用しています。最初は表を使おうと思っていたのですが、リスト形式の方が簡単かもしれないので、ここに書いておきます。

  • ビット0:(BCP)バイナリ・カウンタ
    • 0:バイナリ
    • 1:2進数(BCD)
  • ビット1~3:(M0、M1、M2)動作モード。それぞれの説明は、上記のセクションを参照してください。
    • 000:モード0:割込みまたは端子カウント
    • 001:モード 1: プログラマブルワンショット
    • 010:モード 2: レートジェネレータ
    • 011:モード3:方形波発生器
    • 100:Mode 4: ソフトウェアトリガー ストロボ
    • 101:Mode 5: ハードウェアトリガー ストロボ
    • 110:未定義、使用しないでください。
    • 111:未定義、使用せず
  • 第4-5ビット:(RL0, RL1)リード/ロード・モード。カウンタ・レジスタへのデータの読み出し、または送信を行います
    • 00:カウンタ値はI/Oライト動作時に内部コントロールレジスタにラッチされます。
    • 01:最下位バイト(LSB)のみをリードまたはロードします。
    • 10: 最上位バイト(MSB)のみ読み出し/読み出し
    • 11:LSBを先に読み出し、その後MSBを読み出す。
  • ビット6-7:(SC0-SC1)セレクトカウンタ。それぞれの説明は、上記のセクションを参照してください。
    • 00: Counter 0
    • 01: Counter 1
    • 10: Counter 2
    • 11: Illegal value
さて、それでは、ちょっとだけ、いろいろなことをやってみましょうか?あとは、コントロール・ワード・レジスタに書き込んで、コントロール・ワードを構築し、コントローラを初期化すればいいわけですね?もちろん!ちょっとだけ...

基本的には、ある特定の目的のためにカウンタを初期化したい。そのため、カウンタ、カウンタのカウントモード、動作モードを設定するための制御ワードを構築する必要があります。次に、カウンタそのものを初期化します。一度初期化すれば、カウンターはそれ自体で動作することができますので、この作業は一度だけ行えばよいのです。

例として、すべてをまとめてみましょう。

すでにPICが初期化され、割り込み0ハンドラを持っていると仮定しましょう。IRQ 0を100Hz毎(10ミリ秒毎)に発生させるタイマーをセットアップしたいと思います。PITのチャンネル0がPICのIR0ラインに接続されていることは分かっているので、チャンネル0にこのようにプログラムすることができます。

; COUNT = input hz / frequency mov dx, 1193180 / 100 ; 100hz, or 10 milliseconds ; FIRST send the command word to the PIT. Sets binary counting, ; Mode 3, Read or Load LSB first then MSB, Channel 0 mov al, 110110b out 0x43, al ; Now we can write to channel 0. Because we set the "Load LSB first then MSB" bit, that is ; the way we send it mov ax, dx out 0x40, al ;LSB xchg ah, al out 0x40, al ;MSB
まずコントロールワードをセットアップし、次にカウンタ0レジスタに書き込んでいることに注目してください。

これだけですか!?そうです。これでカウンタ0が10ミリ秒ごとにIRQ0を発生させるようにプログラムされました。

まとめ

8253と8254のPITは、非常に便利な小型チップです。様々なデバイスに使用することができ、様々な目的に使用することができます。

私たちのニーズでは、PCのスピーカーから信号を出力することと、最新のシステムソフトウェアで非常に重要なシステムタイマーを作ることの両方が可能です。さらに、スピーカーを直接操作し、PITとの接続を無効にする別の方法についても検討しましたが、これには利点と欠点があります。システムソフトウェアの設計者が、システムを開発する際に、異なる無限の可能性の長所と短所を判断し、優劣をつけるのは、その人次第です。

ここまで、標準的なx86ベースのPCマザーボードにおけるPITのピン配置とその接続について、詳しく見てきました。PIT自体は、最近のコンピュータでは、通常、マザーボードのサウスブリッジと統合されています。

私は、チップ自体にさらに追加することを計画しており、典型的なコンピュータシステムでどのように接続するかを正確に説明します。 もしかしたら、分解することもできるかもしれませんね。

チュートリアル16:カーネルタイミングと例外処理では8259A PICとこのチュートリアルのすべてを一緒にします。このチュートリアルでは、両方のデバイスのインターフェイスを実装し、作成します。もうちょっとだけ...

カーネルランドへようこそ