Operating Systems Development Series
8259A PIC Microcontroller
by Mike, 2007

8259A PIC Microcontroller with all pins labled.

はじめに

ようこそ!:)

このチュートリアルでは、非常に重要なトピックを扱います。プログラマブルインタラプトコントローラです。このマイクロコントローラをIRQにマッピングして初期化する必要があります。これは、割り込みの設定や割り込み要求の処理に必要なものです。

これは最初のコントローラチュートリアルです。これらのコントローラチュートリアルは、各デバイスを扱うための実用的なインターフェイスを構築しながら、各デバイスについて非常に深く掘り下げています。保護モードであるため、何もガイドがないことを忘れないでください。一歩間違えれば、予想外の結果を招きかねません。そのため、各コントローラと直接やりとりすることになります。このため、このシリーズでは、ハードウェアプログラミングの概念を強調し、読者の皆様にハードウェアレベルのプログラミングをより深く理解していただけるようにしました。

このチュートリアルでは、これまで学んだことをすべて試してみます。8259Aマイクロコントローラ、またの名をPIC(Programmable Interrupt Controller)です。

準備はいいですか?

準備完了

これは、多くのマイクロコントローラプログラミングチュートリアルの私たちの最初のものです。我々はそれらをカバーするように、各マイクロコントローラのほぼすべての資産をカバーする予定です。このチュートリアルは、各マイクロコントローラのほぼすべての機能を網羅し、必要に応じて、メインシリーズで紹介していきます。

このチュートリアルはかなり複雑です。8259Aマイクロコントローラをハードウェアとソフトウェアの両面から取り上げ、PCとの接続と連動について正確に理解することになります。また、このマイクロコントローラのすべてのコマンド、レジスタ、およびパーツをカバーします。

歴史

*To do - このセクションはすぐに追加する予定です。

8259A PICはハードウェアの割り込みを扱うので、まず、割り込みとは何か、どのように動作するのか、基本的なことを理解しておく必要があります。

割り込み

インターラプトとは、ソフトウェアやハードウェアが注意を払う必要がある外部非同期信号のことです。現在のタスクを中断して、より重要なことを実行できるようにする方法です。

難しいことではありません。割り込みは、ゼロ除算のような問題を捕捉するのに役立つ方法を提供します。プロセッサが現在実行中のコードに問題を発見した場合、その問題を修正するために実行する代替コードをプロセッサに提供します。

他の割り込みは、ルーチンとしてソフトウェアをサービスする方法を提供するために使用されるかもしれません。これらの割り込みは、システム内の任意のソフトウェアから呼び出すことができます。これは、リング3アプリケーションにリング0レベルのルーチンを実行させる方法を提供するシステムAPIによく使われます。

割り込みは、特に非同期で状態を変える可能性のあるハードウェアから情報を受け取る方法として、多くの用途に使用されています。

割り込みの種類

割り込みには、ソフトウェア割り込みと ハードウェア割り込みの2種類があります。

ソフトウェア割込み

ソフトウェア割り込みは、ソフトウェアで実装され、トリガーされる割り込みです。通常、プロセッサの命令セットには、ソフトウェア割り込みを処理するための命令が用意されています。x86アーキテクチャの場合、これらは通常INT immと INT 3であり、IRETと IRETD命令も使用します。

例えば、以下のようにソフトウェア命令で割り込みを発生させます。

int 3 ; generates interrupt 3

これらの命令は、ソフトウェア割込みを発生させたり、ソフトウェアで割込みルーチン(IR)を実行するために使用することができます。

ここでは、ソフトウェア割り込みは取り上げません。PICマイクロコントローラ8259Aはハードウェア割り込みしかサービスしません。ソフトウェア割り込みについては、別のチュートリアルで取り上げます。

ハードウェア割り込み

ハードウェア割り込みは、ハードウェアデバイスによって引き起こされる割り込みです。ハードウェア割り込みハンドラは、このハードウェア要求を処理するために必要です。

スプリアス割り込み

割り込み線に電気的な干渉があったり、ハードウェアに欠陥があったりすることによって発生するハードウェア割り込みです。このような割り込みは発生させないようにしましょう。

割り込みモード

割り込みにはいくつかのモードとクラスがあり、それをカバーする必要があります。PICのプログラミングでは、モードを選択する必要があります。

注意:このセクションでは、8259A PICハードウェアのピン配置について、ある程度の知識が必要かもしれません。

レベルトリガ

レベルトリガ割り込みは、PICの割り込み要求(IR)線に電流(1)があるときに発生すると判断されます。デバイスは信号を送り(このラインをアクティブに設定する)、割り込みが処理されるまでその状態を維持します。

レベルトリガ割り込みは、回路がそれを処理するように設計されていれば、複数の割り込みで共有することができます。

このモードは、ラインの共有の仕方から、好ましいモードです。IRラインがアクティブになると、CPUは同じラインを共有しているすべてのデバイスを検索し、どのデバイスがその信号をアクティブにしているのかを見つけます。CPUは、その信号がアクティブになっている機器を見つけると、同じ回線を共有しているすべての機器を再度チェックし、他にサービスを必要としている機器がないことを確認します。

この方法の問題点は、サービスを必要とする優先度の高い割り込みがある場合、他の割り込みがサービスされるまで、他の割り込みが永久にブロックされることです。結局のところ、一度にアクティブにできるのは1つのラインだけなのです。

エッジトリガ

エッジトリガ割り込みは、PICの割り込み要求(IR)線に電流(1)があるときに発生すると決定されます。デバイスは1つのパルスを通して信号を送り(このラインをアクティブに設定)、ラインを以前の状態に戻す。

エッジトリガ割り込みは、回路がそれを処理できるように設計されていれば、複数の割り込みでラインを共有することができます。

パルスが短すぎて検出できない場合は、検出されません。

これらは割り込み要求を信号化する電流のパルスに過ぎないので、エッジトリガモードでは、レベルトリガがIRQラインを共有する場合のような問題は発生しません。

もちろん、1パルスの電流をIRQラインに流すだけなので、割り込みを見逃す可能性はあります。このため、初期のコンピュータでは、CPUがロックしてしまうことがありました。

しかし、最近では、このようなロックアップは時代とともに減少しています。

ハイブリッド

これらのモードには、長所と短所があります。多くのシステムは、この2つのモードのハイブリッドで実装されています。具体的には、CPUのNMI(Non Maskable Interrupt)ピンでエッジトリガとレベルトリガの両方の割り込みをチェックします。この目的は、NMIピンがシステムの大きな問題を知らせるために使われ、大きな問題やシステム全体の誤動作、場合によってはハードウェアの損傷を引き起こす可能性があるからです。

ノンマスカブル割り込みは、どのようなデバイスによっても無効化またはマスクオフすることができません。このため、NMIピンが設定されても、システムは大きな問題を起こすことなく静かに停止することができます。

メッセージシグナリング

このようなタイプのハードウェア割り込みは、物理的な割り込み線を使用しません。その代わり、システムバスなどの別の媒体を利用してメッセージを送ります。

このタイプの割り込みは、エッジトリガ割り込みと同様に、デバイスが媒体上に電流のパルスを送るだけとなるものです。

これらのタイプのシステムは、メッセージシグナルによる割り込み番号を示すコントロールバス上の特別な割り込みラインを使用することがあります。これらの番号は一連のビットとして媒体上に送信されるため、他の割り込みタイプのように1つの割り込み線に制限されることがありません。そのため、下位システムが許す限り多くの割り込みを管理することができます。

PCI Expressでは、このタイプの割り込みが多く使われています。

以上

さて、多くの情報がここにあります;)8259Aは、レベルトリガとエッジトリガ割り込みしかサポートしていません。このため、8259Aマイクロコントローラを使用する場合は、これらの割り込みに重点を置く必要があります。

割込みベクタテーブル

割り込みベクタテーブル(IVT)は、割り込みベクタのリストです。IVTには256の割り込みがあります。

割込みルーチン(IR)

インタラプトルーチン(IR)は、インタラプトリクエスト(IRQ)を処理するための特別な関数です。

プロセッサがINTなどの 割り込み命令を実行すると、IVT(Interrupt Vector Table)内のその位置にあるIR(Interrupt Routine)が実行されます。

つまり、私たちが定義したルーチンが実行されるだけです。難しいことではありませんね。この特別なルーチンは、AXレジスタの値に基づいて、通常実行すべきインタラプトファンクションを決定します。これにより、1つの割り込みコールで複数の関数を定義することができます。例えば、DOSのINT21h関数0x4c00のようなものです。

覚えておいてください。割り込みの実行は、作成した割り込みルーチンを実行するだけです。例えば、INT 2という命令を実行すると、IVTのインデックス2のIRが実行されます。クールでしょ?

IVTマップ

IVTは物理メモリの最初の1024バイト、アドレス0x0から0x3FFに配置されています。IVTの各エントリは4バイトで、次のような形式になっています。

  • Byte 0: Offset Low Address of the Interrupt Routine (IR)
  • Byte 1: Offset High Address of the IR
  • Byte 2: Segment Low Address of the IR
  • Byte 3: Segment High Address of the IR
IVTの各エントリには、呼び出すIRのアドレスが単純に含まれていることに注意してください。これにより、メモリ上の任意の場所(Our IR)に簡単な関数を作成することができます。IVTに関数のアドレスが含まれていれば、全て問題なく動作します。

では、IVTについて見ていきましょう。最初の数個の割り込みは予約されており、そのままです。

x86 Interrupt Vector Table (IVT)
Base Address Interrupt Number Description
0x000 0 Divide by 0
0x004 1 Single step (Debugger)
0x008 2 Non Maskable Interrupt (NMI) Pin
0x00C 3 Breakpoint (Debugger)
0x010 4 Overflow
0x014 5 Bounds check
0x018 6 Undefined Operation Code (OPCode) instruction
0x01C 7 No coprocessor
0x020 8 Double Fault
0x024 9 Coprocessor Segment Overrun
0x028 10 Invalid Task State Segment (TSS)
0x02C 11 Segment Not Present
0x030 12 Stack Segment Overrun
0x034 13 General Protection Fault (GPF)
0x038 14 Page Fault
0x03C 15 Unassigned
0x040 16 Coprocessor error
0x044 17 Alignment Check (486+ Only)
0x048 18 Machine Check (Pentium/586+ Only)
0x05C 19-31 Reserved exceptions
0x068 - 0x3FF 32-255 Interrupts free for software use

ハードではありません。これらの割り込みは、それぞれIVT内のベースアドレスに配置されています。

プロテクトモード(PMode)での割り込み処理

Protected Modeでは、各IVTエントリがInterrupt Descriptor Table(IDT)内で定義された割り込みルーチン(IR)を指すことが必要です。IDTについては、このチュートリアルとは直接関係ないので、別のチュートリアルでさらに説明します。

IDTは、実行する割込みルーチン(IR)のベースアドレスを記述するInterrupt Descriptorの配列で、保護レベルやセグメント情報などの特別な情報を含んでいます。PModeは使用するメモリマップを定義するGlobal Descriptor Table (GDT)を使用します。割り込みルーチンのほとんどは、GDTによってマップされたコードディスクリプタの中に入ります。これがPModeでIDTが必要とされる理由です。

今すぐ理解できなくても気にしないでください。とりあえず、IDTは256個の関数ポインタの配列で、IVTと同じように正確にマッピングされていると考えてください(通常、そうなっています)。

ハードウェア割り込み

割り込みには、ソフトウェアで発生するもの(INT、INT 3、BOUND、INTOなどの命令で使用)と、ハードウェアで発生するものの2種類があります。

ハードウェア割り込みは、PCにとって非常に重要です。他のハードウェアデバイスから、何かが起ころうとしていることをCPUに知らせることができるのです。例えば、キーボードのキーストロークや、内部タイマーの1クロック刻みなどです。

これらの割り込みが発生したときに、どのような割り込み要求(IRQ)を発生させるかをマッピングしておく必要があります。こうすることで、ハードウェアの変化を追跡することができます。

それでは、これらのハードウェア割り込みについて見ていきましょう。

x86 Hardware Interrupts
8259A Input pin Interrupt Number Description
IRQ0 0x08 Timer
IRQ1 0x09 Keyboard
IRQ2 0x0A Cascade for 8259A Slave controller
IRQ3 0x0B Serial port 2
IRQ4 0x0C Serial port 1
IRQ5 0x0D AT systems: Parallel Port 2. PS/2 systems: reserved
IRQ6 0x0E Diskette drive
IRQ7 0x0F Parallel Port 1
IRQ8/IRQ0 0x70 CMOS Real time clock
IRQ9/IRQ1 0x71 CGA vertical retrace
IRQ10/IRQ2 0x72 Reserved
IRQ11/IRQ3 0x73 Reserved
IRQ12/IRQ4 0x74 AT systems: reserved. PS/2: auxiliary device
IRQ13/IRQ5 0x75 FPU
IRQ14/IRQ6 0x76 Hard disk controller
IRQ15/IRQ7 0x77 Reserved

各デバイスについては、まだあまり気にする必要はありません。8259A のピンについては、次のセクションで詳しく説明します。この表に記載されている割り込み番号は、これらのイベントが発生したときに実行されるデフォルトの DOS割り込み 要求(IRQ)です。

ほとんどの場合、新しい割り込みテーブルを再作成する必要があります。そのため、ほとんどのOSでは、PICが使用する割り込みを再マッピングして、IVT内の適切なIRQを呼び出すことを保証する必要があります。これは、リアルモードIVTのBIOSによって行われます。 このチュートリアルの後半で、これを行う方法についても説明します。

8259プログラマブルインタラプトコントローラ

8259マイクロコントローラファミリは、プログラマブル割り込みコントローラ(PIC)集積回路(IC)のセットです。チュートリアル7をもう一度振り返ってみてください。プロセッサ・アーキテクチャ」のセクションで、プロセッサが独自の内部PICマイクロコントローラを備えていることに注目してください。これは非常に重要なことです。

回路設計の制限により、PICは8つのIRQしかサポートしません。これは大きな制限です。追加デバイスが作られるにつれて、IBMはこの制限が非常に悪いものであることにすぐに気づきました。このため、ほとんどのマザーボードには、プロセッサ内のプライマリPICと連動するセカンダリ(スレーブ)PICマイクロコントローラが搭載されています。現在では、1つのPICを別のPICと「カスケード接続」(一緒に動作させること)することができます。これにより、追加のPICでより多くのIRQをサポートすることが可能になります。

サポートするPICが増えれば増えるほど、より多くのIRQを処理できるようになります。カスケード接続で最大64個のIRQをサポートすることができます。クールですか?

覚えておいてください。ほとんどのコンピュータは2つのPICを持っています、1つはプロセッサの中に、もう1つはマザーボード上に。システムによっては、これを搭載していないものもあります。
覚えておいてください。各PICは最大8つのIRQしかサポートできません。
覚えておいてください。各PICは互いに通信でき、PICの数に応じて最大64のIRQを使用できます。

難しくはありません :)

8259ハードウェア

マイクロコントローラがハードウェアレベルでどのように動作しているかを理解することは、ソフトウェア側の動作を理解するのに役立ちます。PICはハードウェア割り込みの時だけ使われることを覚えておいてください。

8259Aマイクロコントローラ

このチュートリアルの一番上に、実際の8259デュアルインラインパッケージ(DIP)の画像があり、すべての電子ピンがラベル付けされています。より理解しやすくするために、よりシンプルなグラフィックでコントローラを表現します。これらのグラフィックに表示されていないピンで8259が持っているのは、GND(グラウンド)とVcc(入力電圧)だけです。 これらのピンは、このチュートリアルの一番上の写真でラベル付けされているのが確認できます。

まず、これからプログラミングするものを見てみましょう。

それが、8259Aプログラマブル・インタラプト・コントローラです。

上の画像の各線は、コントローラの各電子ピンを示しています。これらの電子ピンは、コントローラとシステムの残りの部分を接続するものです。

これは、オペレーティングシステム内でIRQを処理するためにプログラムする必要があるチップです。各ピンを詳しく見てみましょう。重要なピンは太字にしてあります。

  • WR 端子:書き込みストローブ信号(Pentiumでは8本のうちの1本)に接続するピンです。
  • RD 端子:IOCR(Input Output Control Routine)信号に接続する。
  • INT 端子:マイクロプロセッサの INTR 端子に接続します。
  • INTA 端子:マイクロプロセッサの INTA 端子に接続します。
  • A0 端子:異なるコマンドワードを選択します。
  • CS 端子: プログラム制御が可能です。
  • SP/EN 端子 : スレーブプログラム(SP)/イネーブルバッファ(EN)。
    • スレーブプログラム (1=Master, 0=Slave)。
    • イネーブルバッファ (バッファモード時のデータバス転送を制御)
  • CAS0, CAS1, CAS2 端子。CAS0, CAS1, CAS2 端子: カスケード接続されたPICコントローラのマスターからスレーブへの出力端子です。
  • D0〜D7端子。8ビットのデータコネクタピンです。
ここには、いくつかの重要なピンがあります。D0-D7ピンは、外部デバイスがPICと通信するためのものです。 これは小さなデータバスのようなもので、PICにデータを送信する方法を提供します(例:割り込み番号、、、?

PIC同士を接続できることを忘れないでください。これにより、最大64個のIR番号をサポートすることができます。言い換えれば、64個のハードウェア割り込みです。CAS0、CAS1、CAS2ピンは、これらのPICの間で信号を送信する方法を提供します。

INTピンとINTAピンを見てください。プロセッサの観点のセクションで、プロセッサ自身のINTとINTAピンがPICのこれらのピンに接続されていることを思い出してください。割り込みを実行しようとすると、プロセッサはFLAGSレジスタから割り込み(IF)とトラップフラグ(TF)をクリアし、INTRピンをディセーブルにすることを思い出してください。PICのINTピンは、プロセッサのINTRピンに接続されています。

つまり、プロセッサは割り込みを実行すると、実質的にPICのINTピンをディセーブルにします。

これにより、ピンIR0-IR7は他のPICに流すことができます。これらの8本のピンは、実行される8ビット割り込み番号を表します。 8ビット値であるため、最大256のハードウェア割り込みが可能であることに注意してください。 これらのラインは、別のPICコントローラに割り込み番号を送信する方法を提供し、そのコントローラは代わりにそれを処理することができます。

重要なのは、複数のPICを組み合わせることで、より多くの割り込みルーチン番号をサポートできることです。IRラインは他のPICのデータラインに接続し、データを転送する。8本(8ビット)しかないので、最大8個のPICを接続することができ、最大64個の割り込みルーチンをサポートすることができます。

なるほど...盛りだくさんでしょう?プロセッサがプライマリPICに接続する方法と、PICが他のPICと結合してPICのチェーンを作る方法について説明しました。

これは素晴らしいことですが、全く役に立ちません。ハードウェアを通してどのように割り込みが実行されるのでしょうか?このコントローラを「プログラマブル」にするのは何なのか?私たちのニーズに合わせてPICをプログラムするにはどうしたらいいのでしょうか?

PICのプログラミングは、PICが持つ8ビットのデータラインを通じてコマンドバイトを送信することを中心に展開されます。この8ビットのコマンドバイトは、PICが何をすべきかを記述する特定のフォーマットに従っています。PICをプログラムするためには、これらのコマンドを知る必要があります。これについては後で説明します。

PICがどのように動くのか、もう少し詳しく見てみましょう。これは、8259Aのピンと、割り込み信号がどのように送られるかをよりよく理解するのに役立ちます。

8259Aの接続

注:このセクションは、デジタルロジック電子工学の知識が必要かもしれません。

さて...ここまで、8259A PICのピンを見てきました。これらのピンを別の視点から見て、典型的なコンピュータの中でどのように見えるかを見てみましょう。

PICをプロセッサに接続する

まず、今日のほとんどのコンピュータは2つの8259A PICを持っていると言ったのを覚えていますか?これは半分だけ真実です。プロセッサー・アーキテクチャーで、主要なPICがプロセッサーに統合されていることを思い出してください。これには理由があるのですが、すぐにわかると思います。

物事を簡単にするために、私たちがいるシステムには実際に2つのPICコントローラがあり、両方とも直接マザーボード上にあると想像してみましょう(いずれもプロセッサと統合されていません)。

これを図式化すると、このようになります。

なるほど...ここにはたくさんのことが起こっています。これは、IOサブシステムとISAバスの一部と、8259Aコントローラが共通の16L8を介してどのようにシステムバスに接続されているかを示しています。

デジタルロジック電子工学はこのシリーズの前提条件ではないので、これが理解できなくても全く心配ありません ;) この画像も同様に詳細が欠落しています。

上の画像を見て、いくつかの重要な注意点があります。

スレーブコントローラーがプライマリーコントローラーにどのように接続されているかに注目してください。

プライマリPICだけがプロセッサと直接接続する必要があることに注意してください。このように密接に統合されているため、最近のコンピュータでは、この依存関係をなくすために、プライマリPICをプロセッサの内部に直接組み込んでいるのが一般的です。

また、CAS0-CAS2ピンが2番目のPICに直接接続されていることに注目してください。これにより、1次側PICは2次側PICにコマンドを送信することができる。

そして、ご存知のようにIRラインは、そのラインを制御する他のコントローラに接続されています。例えば、ハードウェア割り込み0は、タイマ割り込みを表しています。8254プログラマブルインターバルタイマ(PIT)コントローラは、一次側PICと直接接続されているので、IR0ラインを通じて信号を送ります。この信号は、割り込みが処理されるまでアクティブな状態を保つ電流か、一定時間保持される単一パルスのどちらかになります。PICに何を監視させたいかを制御することができます。これについては、後で詳しく説明します。

さて...これで完成です :)悪名高き8259A PICマイクロコントローラです。

ハードウェア割り込みの実行方法

マイクロプロセッサの裏側には、コネクタがあります。このコネクタは平らなものと、マザーボードに接続するためのピン状のものがあります。このうち、INTRピンとNMIピンの2つがあります。これと一緒に、割り込みの完了を確認するためのピン、INTAもあります。

ソフトウェア割り込みは、ハードウェア割り込みとは扱いが異なります。この2つの割り込みは、いずれもメモリ上のアドレス0〜0x3ffにあるInterrupt Vector Tableの中に入っています。

覚えておいてください。ハードウェア割り込みは、プログラマブル割り込みコントローラを通してのみ処理されます。

割り込みの発生

デバイスコントローラが割り込みを発生させる必要がある場合、何らかの方法でPICに信号を送る必要があります。 議論の便宜上、このデバイスを割り込み線0を使用するタイマとします。

  1. タイマコントローラはIR0ラインをアクティブにすることによってPICに信号を送ります。これは、その状態を0(電源なし)から1(電源がラインを通っている)に変更します。
  2. PICは割り込み要求レジスタ(IRR)内のIRQを表すビットを設定します。この例では、ビット0が1に設定されます。
  3. PICは割り込みマスクレジスタ(IMR)を調べて、割り込みが処理可能かどうかを確認します。
    • PICは、割り込みがサービス可能かどうかを確認するために、割り込みマスクレジスタ(IMR)を調べます。 割り込みがサービス可能な場合、PICは、サービス待ちのより高い優先度の割り込みがあるかどうかを判断します。
    • 割り込みが処理可能で、より高い優先順位の割り込みがない場合、PICは次のステップに進みます。
  4. PICは、INTAピンを通してプロセッサに信号を送り、割り込みが発生したことを知らせます。

プロセッサはこれで、割り込みが発生したことを知ることができます。

プロセッサは割り込みを認識する

  1. CPUは現在の命令の実行を完了する。
  2. CPUはRFLAGSの中のInterrupt Flag (IF)をチェックします。
    • IFがセットされている場合、CPUは割り込み要求をINTRピンを通してPICに送り返します。
    • IFがクリアされると、割り込み要求は無視されます。
  3. PICはINTR端子から割込み信号を受信します。
  4. PICは割り込みベクター番号をD0-D7ピンに入力します。
    • この割り込みベクター番号は、PICの初期化時に初期化制御語(ICW)2から取得されます。これについては後で説明します。
  5. PICはまた、IRQ番号をD0-D7に配置します。
  6. PICはインサービスレジスタ(ISR)内の正しいビットを設定します。この場合、それはビット0です。これは、割り込み0が現在サービス中であることを示しています。

これでプロセッサは実行するIRQ番号と割り込みベクタ番号を手に入れました。

割り込み

  1. プロセッサは現在の処理に割り込みます。EFLAGS、CS、EIPをスタックにプッシュします。
  2. プロセッサは割り込みベクター番号(PICから与えられる)を使用します。
    • リアルモードでは、CPUはIVTにオフセットします。プロテクトモードでは、プロセッサはIDTにオフセットします。
    • リアルモード。
      • CPUはIVTの正しいエントリにオフセットします。
      • CPUは呼び出す割り込みのベースアドレスをCS:IPにロードします。
      • 割り込みが制御されます。
    • プロテクトモード。
      • CPUはロードされたIDTを使用して、CS:IPにオフセットします。
      • ゲートディスクリプタのセレクタフィールドがCSセグメントセレクタにロードされる。
      • ゲートディスクリプタのオフセットフィールドは、EIPにロードされる。
      • ページングが有効な場合、このアドレスはリニアアドレスから物理アドレスに変換されます。
      • さて、CPUは現在の状態について、アーキテクチャ固有のセキュリティ・チェックを行います。
      • これで、割り込みルーチンは、ゲートディスクリプタ+CS:EIPから制御を受けることができるようになりました。

割り込みサービスルーチン

現在、ISRはハードウェア割り込みを処理するために実行されています。例えば、デバイスへのデータの読み書き、ステータス・レジスタの読み出し、コマンドの送信など、特定のデバイスにサービスを提供するために必要なあらゆるアクションを実行することができます。

この間、すべての割り込みはIMR(Interrupt Mask Register)によりマスクされます。つまり、割り込みの終了要求があるまで、すべてのハードウェア割り込みが禁止されます。このため、PICにEOI(End of Interrupt)コマンドを送信する必要があります。

EOI信号がプライマリPICのコマンドレジスタを通してPICに送られた後、PICはインサービスレジスタ(IRR)のappropriseビットをクリアし、新しい割り込みに対応できる状態になります。

割り込みサービスルーチンは、次にIRETD命令を実行し、割り込みが発生したときにプロセッサによってプッシュされたEFLAGS、CS、EIPレジスタをポップさせる。

これにより、制御が初期タスクに戻されます。

8259A レジスタ

8259Aは、プロセッサと同様に、いくつかの内部レジスタを持っています。

コマンドレジスタ

これは書き込み専用のレジスタで、マイクロコントローラにコマンドを送信するために使用されます。送信できるコマンドはたくさんあります。他のレジスタから読み出すコマンドもあれば、EOI(End of Interrupt)のような初期化やデータ送信に使うコマンドもあります。これらのコマンドについては、後ほど説明します。

ステータスレジスタ

このレジスタは、PICの状態を決定するためにアクセスすることができる読み取り専用レジスタです。

割り込み要求レジスタ (IRR)

このレジスタは、どの割り込みが肯定応答を保留しているかを指定します。

注:このレジスタは内部レジスタであり、直接アクセスすることはできません。

Interrupt Request Register (IRR)
Bit Number IRQ Number (Primary controller) IRQ Number (Slave controller)
0 IRQ0 IRQ8
1 IRQ1 IRQ9
2 IRQ2 IRQ10
3 IRQ3 IRQ11
4 IRQ4 IRQ12
5 IRQ5 IRQ13
6 IRQ6 IRQ14
7 IRQ7 IRQ15

ビットがセットされている場合、デバイスから割り込みが信号化され、PICはCPUに信号を送りましたが、CPUから割り込みの実行を確認するのを待っている状態です。

イン・デバイス・レジスタ(ISR)

EOI信号は割り込みの終了を決定するため、非常に重要です。

注意:8259Aに割り込みを認識させるために、割り込みの完了時にEOI信号を送る必要があります。 これをしないと、未定義の動作や誤動作が発生します。これについては後で詳しく説明します。

注:このレジスタは内部レジスタであり、直接アクセスすることはできません。

In Service Register (ISR)
Bit Number IRQ Number (Primary controller) IRQ Number (Slave controller)
0 IRQ0 IRQ8
1 IRQ1 IRQ9
2 IRQ2 IRQ10
3 IRQ3 IRQ11
4 IRQ4 IRQ12
5 IRQ5 IRQ13
6 IRQ6 IRQ14
7 IRQ7 IRQ15

ビットがセットされている場合、現在のIRQはCPUによって先に実行を開始するように認識されています。PICはこのレジスタを使用して、現在実行中のIRQが何であるかを判断します。

インタラプトマスクレジスタ(IMR)

このレジスタで指定された割り込みを実行する前に、より重要な特定の割り込みの実行に集中することができます。

これは8ビットのレジスタで、各ビットが割り込みが無効かどうかを決定します。ビットが0の場合は有効で、1の場合は割り込みデバイスが無効となります。

Interrupt Mask Register (IMR)
Bit Number IRQ Number (Primary controller) IRQ Number (Slave controller)
0 IRQ0 IRQ8
1 IRQ1 IRQ9
2 IRQ2 IRQ10
3 IRQ3 IRQ11
4 IRQ4 IRQ12
5 IRQ5 IRQ13
6 IRQ6 IRQ14
7 IRQ7 IRQ15

このレジスタは、特定のデバイスからの割り込みを有効にしたり無効にしたりすることができる重要なレジスタです。これらのIRQはそれぞれ、上記のx86ハードウェア割り込みの表に記載されているデバイスを表しています。

例えば、COM1(シリアルポート1)を有効にするとします。そこで、COM1割り込みを有効にするには、プライマリPICの割り込みマスクレジスタのIRQ4ビットを設定するだけでよい。このレジスタはソフトウェアポート番号0x21にマッピングされているので(後で説明します)、このポート位置に書き込むことでビットを設定すればよいのです。

in al, 0x21 ; read in the primary PIC Interrupt Mask Register (IMR) and al, 0xEF ; 0xEF => 11101111b. This sets the IRQ4 bit (Bit 5) in AL out 0x21, al ; write the value back into IMR

ハードウェア割り込みが発生すると、8259Aは割り込み終了(EOI)信号を受信するまで、他のすべての割り込みをマスクします。割り込みが完了したら、EOIを送信する必要があります。これについては後ほど説明します。

8259A ソフトウェア・ポート・マッピング

すべてのハードウェアコントローラと同様に、BIOS POSTは、ソフトウェアポートの特定の領域を使用するように各コントローラをマッピングします。このため、PICコントローラーと通信するためには、ソフトウェアポートを使用する必要があります。

8259Aソフトウェア・ポート・マップ
ポートアドレス 説明
0x20 プライマリPICコマンドおよびステータス・レジスタ
0x21 プライマリPIC割り込みマスクレジスタおよびデータレジスタ
0xA0 セカンダリ(スレーブ)PICコマンドステータスレジスタ
0xA1 セカンダリ(スレーブ)PICの割り込みマスク・レジスタとデータ・レジスタ

プライマリPICの割り込みマスクレジスタはポート0x21にマッピングされていることに注意してください。これは以前にも見たことがありますね。

コマンド・レジスタと ステータス・レジスタは、同じポート番号を持つ別のレジスタにマッピングされます。 コマンド・レジスタは書き込み専用で、ステータス・レジスタは読み出し専用です。これは重要な違いであり、PICは書き込み線と読み出し線のどちらを設定するかによって、アクセスするレジスタを決定します。

個々のデバイスのレジスタと通信し、PICを制御するために、これらのポートに書き込むことができる必要があります。 それでは、PICのコマンドを見てみましょう。

8259Aコマンド

PICのセットアップは非常に複雑です。初期化および動作に使用するさまざまな状態を含むビットパターンである、一連のCommand Wowrdsを通じて行われます。これは少し複雑に見えるかもしれませんが、それほど難しいことではありません。

このため、まずPICコントローラを初期化する方法、次にPICを操作・制御する方法を見ていきましょう。

初期化制御語(ICW)

PICを初期化する目的は、PICのIRQ番号を私たち自身のものに再マップすることです。

PICを初期化するためには、PICコマンドレジスタにコマンドバイト(初期化制御語(ICW)として知られている)を送信する必要があります。これはICW 1です。

最大4つの初期化コントロールワードがあります。これらは必須ではありませんが、しばしば必要とされます。それでは見ていきましょう。

注:システム内に複数のPICがあり、互いにカスケード接続されている場合、両方のPICにICWを送信する必要があります。

ICW 1

これはPICを初期化するために使用される主制御語です。これは7ビットの値で、主PICコマンドレジスタに入れる必要があります。これがその形式です。

初期化制御語(ICW)1
ビット番号 説明
0 IC4 セット(1)されると、PICは初期化中にIC4を受信することを期待します。
1 SNGL セット(1)されると、システム内でPICは1つだけです。クリアされた場合、PICはスレーブPICとカスケード接続され、ICW3はコントローラに送信される必要があります。
2 ADI セット(1)されると、CALLアドレス間隔は4、さもなくば8。これは通常、x86では無視され、デフォルトは0である。
3 LTIM 設定されている場合(1),レベルトリガモードで動作する。設定しない場合(0),エッジトリガモードで動作する。
4 1 初期化ビット。PICを初期化する場合、1 を設定する。
5 0 MCS-80/85: 割り込みベクターアドレス。0でなければならない
6 0 MCS-80/85: 割り込みベクターアドレス。0でなければならない
7 0 MCS-80/85: 割り込みベクターアドレス。0でなければならない

このように、いろいろなことが起こっています。これらのいくつかは、以前にも見たことがあります。これらのビットのほとんどはx86プラットフォームでは使用されないので、思ったほど難しくありません。

プライマリPICを初期化するために必要なのは、初期化ICWを作成し、適切なビットを設定することです。それでは...

  • ビ ッ ト 0- ICW 4 を送信で き る よ う 、 1 に設定 し ます。
  • ビット1- PICカスケードビット。x86アーキテクチャは2つのPICを持っているので、プライマリPICはスレーブとカスケードされる必要があります。0のままにしておく。
  • Bit2- CALLアドレス間隔。x86では無視され、8を維持するため、0を維持する。
  • Bit3- エッジトリガー/レベルトリガーモードビット。デフォルトではエッジトリガになっているので、0のままにしておきます。
  • Bit4- 初期化ビット。1に設定
  • Bit5...7- x86では未使用、0にセット。
上記を見ると、最終的なビットパターンは00010001、つまり0x11になる。つまり、PICを初期化するには、ポート0x20にマッピングされたプライマリPICコントローラ・レジスタに0x11を送る...。
; Setup to initialize the primary PIC. Send ICW 1 mov al, 0x11 out 0x20, al ; Remember that we have 2 PICs. Because we are cascading with this second PIC, send ICW 1 to second PIC command register out 0xA0, al ; slave PIC command register
カスケードを有効にしているので、ICW 3もコントローラに送る必要があります。また、ビット0を設定したので、ICW 4も送信する必要があります。 これらの詳細については後ほど説明します。とりあえず、ICW 2 を見てみましょう。

ICW 2

この制御語は、PICが使用するIVTのベースアドレスをマップするために使用されます。これは重要です

初期化制御語(ICW)2
ビット番号 説明
0-2 A8/A9/A10 MCS-80/85モード時のIVT用アドレスビットA8~A10。
3-7 A11(T3)/A12(T4)/A13(T5)/A14(T6)/A15(T7) MCS-80/85 モード時の IVT 用アドレスビット A11-A15 です。80x86 モードでは、割り込みベクタのアドレスを指定します。x86モードでは0に設定してもよい。

初期化時に、ICW2をPICに送って、使用するIRQのベースアドレスを伝える必要があります。もしICW1がPICに送られたなら(初期化ビットが設定された状態で)、次にICW2を送らなければなりません。そうしないと、未定義の結果になることがあります。ほとんどの場合、不正な割り込みハンドラが実行されます。

ICW1はPICのデータレジスタに格納されますが、ICW2はデータレジスタに送られ、プライマリPICではソフトウェアポート0x21、セカンダリPICではポート0xA1として送られます。(PICソフトウェアポートの完全なリストについては、8259Aソフトウェアポートマップテーブルを参照してください)。

さて、先ほど両方のPICにICW 1を送ったと仮定して(上記のセクションを参照)、両方のPICにICW 2を送ろうとします。これで両方のPICにベースIRQアドレスがマッピングされます。

これは非常に簡単ですが、PICをどこにマッピングするかに注意する必要があります。最初の31個の割り込み(0x0~0x1F)は予約されていることを忘れないでください(上記のx86割り込みベクターテーブル(IVT)表を参照してください)。そのため、これらのIRQ番号を使用しないことを保証する必要があります。

最初の8つのIRQはプライマリPICによって処理されるので、プライマリPICを0x20(32進数)のベースアドレスに、セカンダリPICを0x28(40進数)のベースアドレスにマップする。各PICには8つのIRQがあることを忘れないでください。

; send ICW 2 to primary PIC mov al, 0x20 ; Primary PIC handled IRQ 0..7. IRQ 0 is now mapped to interrupt number 0x20 out 0x21, al ; send ICW 2 to secondary controller mov al, 0x28 ; Secondary PIC handles IRQ's 8..15. IRQ 8 is now mapped to use interrupt 0x28 out 0xA1, al
簡単でしょう?次です。

ICW 3

これは重要なコマンドワードです。PICが互いに通信するときに、どのIRQラインを使用するかを知らせるために使用されます。

ICW 3 プライマリPICのコマンドワード

初期化制御語(ICW)3 - 一次側PIC
ビット番号 説明
0-7 S0-S7 スレーブPICに接続されている割り込み要求(IRQ)を指定します。

ICW 3 セカンダリPIC用コマンドワード

初期化制御ワード(ICW)3 - 二次側PIC
ビット番号 ビット番号 値 説明
0-2 ID0 マスターPICが接続に使用するIRQ番号(2進数表記)
3-7 0 予約済み、0でなければならない

ICW1内のカスケードを有効にするたびにICW3を送信する必要があります。これにより、どのIRQを使用して互いに通信するかを設定できます。8259Aマイコンは他のPICデバイスと接続するためにIR0-IR7ピンに依存していることを思い出してください。 これによって、CAS0-CAS2ピンを使って互いに通信することができるのです。

各PICに互いのことを知らせ、どのように接続されているかを知る必要があります。これは、マスターと関連するPICの両方でどのIRQラインを使用するかを含むICW 3を両方のPICに送信することによって行います。

覚えておいてください。80x86アーキテクチャでは、IRQライン2を使用してマスターPICとスレーブPICを接続します。

これを知っていて、両方のPICのデータレジスタにこれを書き込む必要があることを思い出し、上記のフォーマットに従う必要があります。

なお、プライマリPICのICW3では、各ビットが割り込み要求を表している。つまり...

IRQ Lines for ICW 2 (Primary PIC)
Bit Number IRQ Line
0 IR0
1 IR1
2 IR2
3 IR3
4 IR4
5 IR5
6 IR6
7 IR7

IRQ2はICW3のビット2であることに注意してください。 つまり、IRQ2を設定するには、ビット2(バイナリ0100、または0x4です)を設定する必要があります。

以下は、ICW 3をプライマリPICに送信する例です。

; Send ICW 3 to primary PIC mov al, 0x4 ; 0x4 = 0100 Second bit (IR Line 2) out 0x21, al ; write to data register of primary PIC

これを2次側PICに送るには、2進数で送らなければならないことを忘れてはいけません。上の表を参照してください。ビット0~2だけがIRQラインを表現するために使用されていることに注意してください。2進数表記を使うことで、8つのIRQラインから選択できるように参照することができます。

IRQ Lines for ICW 2 (Secondary PIC)
Binary IRQ Line
000 IR0
001 IR1
010 IR2
011 IR3
100 IR4
101 IR5
110 IR6
111 IR7

十分シンプルですね。上の表では、2進数<->10進数の変換にしたがっているだけであることに注意してください。

IRQライン2で接続されているので、ビット1(上図)を使用する必要があります。

以下は、ICW 2をプライマリとセカンダリのPICコントローラの両方に送信する完全な例です。

; Send ICW 3 to primary PIC mov al, 0x4 ; 0x04 => 0100, second bit (IR line 2) out 0x21, al ; write to data register of primary PIC ; Send ICW 3 to secondary PIC mov al, 0x2 ; 010=> IR line 2 out 0xA1, al ; write to data register of secondary PIC
これで全部です ;)

さて、これで両方のPICがIRライン2を使って通信するように接続されました。また、両方のPICが使用するベース割り込み番号も設定しました。

これは素晴らしいことですが、まだ終わりではありません。ICW 1を構築するとき、ビット0がセットされていると、PICはICW 4を送ることを期待していることを思い出してください。 そのため、最終的なICWであるICW 4をPICに送信する必要があります。

ICW 4

イェーイ!これは最終的な初期化制御語です。これは、すべてがどのように動作するかを制御します。

初期化制御語(ICW)4
ビット番号 説明
0 uPM セット(1)の場合、80x86モード。MCS-80/86モードであればクリアされる。
1 AEOI 設定されている場合、最後の割り込みアクノリッジパルスで、コントローラは自動的に割り込みの終了(EOI)操作を実行します。
2 M/S BUFが設定されている場合のみ使用します。設定(1)の場合、バッファマスタを選択します。バッファスレーブの場合はクリアされます。
3 BUF 設定された場合,コントローラはバッファードモードで動作します。
4 SFNM Special Fully Nested Mode(スペシャル・フルネスト・モード)。カスケード接続された大量のコントローラーを持つシステムで使用されます。
5-7 0 予約済み、0でなければならない

これはかなり強力な機能です。5-7ビットは常に0なので、他のビットに注目しましょう(ダジャレです ;)。

PICはもともと、80x86が存在する以前から、汎用のマイクロコントローラとして設計されました。そのため、さまざまなシステム向けに設計されたさまざまな動作モードが含まれています。これらのモードの1つに、特殊なフルネストモードがあります。

x86ファミリーはこのモードをサポートしていないので、ビット4を0に設定することで安全に動作させることができます。

ビット3は、バッファードモードに使用されます。ビット2はビット3がセットされているときのみ使用されますので、0にセットします。 これで、ビット1もほとんど使用されません。

このため、ビット0を設定するだけで、PICを80x86モードで使用できるようになります。

簡単ですね。というわけで、ICW 4を送るには、次のようにすればよいのです。

mov al, 1 ; bit 0 enables 80x86 mode ; send ICW 4 to both primary and secondary PICs out 0x21, al out 0xA1, al
これはおそらくこのチュートリアルの中で最も簡単なコード・スニップレットです。それが持続している間、それをブレークしてください!:)

PICを初期化する - まとめてみる

信じられないかもしれませんが、これはすでに説明したとおりです。PICを初期化する際に必要なのは、正しいICWをPICに送信することです。

前のセクションのすべてをまとめて、PICを初期化することで、すべてがどのように組み合わされているかをよりよく理解することができます。

;************************************************************************ ; Map the 8259A PIC to use interrupts 32-47 within our interrupt table ;************************************************************************ %define ICW_1 0x11 ; 00010001 binary. Enables initialization mode and we are sending ICW 4 %define PIC_1_CTRL 0x20 ; Primary PIC control register %define PIC_2_CTRL 0xA0 ; Secondary PIC control register %define PIC_1_DATA 0x21 ; Primary PIC data register %define PIC_2_DATA 0xA1 ; Secondary PIC data register %define IRQ_0 0x20 ; IRQs 0-7 mapped to use interrupts 0x20-0x27 %define IRQ_8 0x28 ; IRQs 8-15 mapped to use interrupts 0x28-0x36 MapPIC: ; Send ICW 1 - Begin initialization ------------------------- ; Setup to initialize the primary PIC. Send ICW 1 mov al, ICW_1 out PIC_1_CTRL, al ; Send ICW 2 - Map IRQ base interrupt numbers --------------- ; Remember that we have 2 PICs. Because we are cascading with this second PIC, send ICW 1 to second PIC command register out PIC_2_CTRL, al ; send ICW 2 to primary PIC mov al, IRQ_0 out PIC_1_DATA, al ; send ICW 2 to secondary controller mov al, IRQ_8 out PIC_2_DATA, al ; Send ICW 3 - Set the IR line to connect both PICs --------- ; Send ICW 3 to primary PIC mov al, 0x4 ; 0x04 => 0100, second bit (IR line 2) out PIC_1_DATA, al ; write to data register of primary PIC ; Send ICW 3 to secondary PIC mov al, 0x2 ; 010=> IR line 2 out PIC_2_DATA, al ; write to data register of secondary PIC ; Send ICW 4 - Set x86 mode -------------------------------- mov al, 1 ; bit 0 enables 80x86 mode ; send ICW 4 to both primary and secondary PICs out PIC_1_DATA, al out PIC_2_DATA, al ; All done. Null out the data registers mov al, 0 out PIC_1_DATA, al out PIC_2_DATA, al
それほど難しいことではありませんでしたか?このコードですべてをカバーしました。

これでPICは初期化されました。ハードウェア割り込みが発生すると、あらかじめ割り込みベクターテーブル(IVT)のどこかに定義しておいた32~47の割り込みが呼び出されます。これにより、ハードウェア割り込みを追跡することができます。クールでしょう?

オペレーションコマンドワード(OCW)

やったー!さて、醜い初期化が終わったので、ようやくPICの標準的な制御と操作に集中できます。これは、オペレーションコントロールワード(OCW)を通して様々なレジスタを書いたり読んだりすることで行われます。

OCW 1

OCW 1は、割り込みマスクレジスタ(IMR)内の値を表します。現在のOCW 1を得るために必要なことは、IMRから読み出すことです。

IMR はステータス・レジスタと同じポートにマッピングされていることに注意してください。ステータス・レジスタは読み取り専用なので、PICはこれが読み取り操作か書き込み操作かに基づいて、アクセスするレジスタを決定することができます。

PICのレジスタについて説明したときに、IMRレジスタについても見ています。

OCW 2

これはPICを制御するために使用される主要な制御語です。それでは、見ていきましょう...

オペレーションコマンドワード(OCW)2
ビット番号 説明
0-2 L0/L1/L2 コントローラが反応しなければならない割り込みレベル
3-4 0 予約済み,0でなければならない
5 EOI エンドオブインタラプト(EOI)要求
6 SL 選択
7 R 回転オプション

OK then!0-2ビットは現在の割り込みのレベルを表します。3-4ビットは予約済みです。 5-7ビットが興味深いビットです。これらのビットの組み合わせを見てみましょう。

OCW2コマンド
Rビット SLビット EOIビット 説明
0 0 0 自動EOIモード(CLEAR)での回転
0 0 1 非特定EOIコマンド
0 1 0 動作なし
0 1 1 特定の EOI コマンド
1 0 0 自動EOIモード(SET)での回転
1 0 1 非特定EOIでローテート
1 1 0 優先命令設定
1 1 1 特定のEOIで回転させる

さて...この表、今のままでは分かりにくいと思いませんか?上記のコマンドの多くはかなり高度なものです。 では、何ができるのか見てみましょう。

割り込みの終了(EOI)を送信する

ご存知のように、ハードウェア割り込みが発生すると、EOI信号がプライマリコントローラに送信されるまで、他のすべての割り込みは割り込みマスクレジスタの内部でマスクされます。つまり、割り込みルーチン(IR)の最後に、すべてのハードウェア割り込みが有効になるようにEOIを送信する必要があります。

上の表を見ると、特定のEOIコマンドを送信することで、コントローラにEOIを通知することができます。EOIビットはOCW2内のビット5なので、ビット5(100000 binary = 0x20)をセットすればよいのです。

; send EOI to primary PIC mov al, 0x20 ; set bit 4 of OCW 2 out 0x20, al ; write to primary PIC command register

まとめ

PICはプログラミングが複雑なマイクロコントローラです。このチュートリアルでは多くのことを説明しましたが、これからもっと難しくなっていきます!

このチュートリアルで多くのことを学びました。OS Development Seriesのプライマリチュートリアルシリーズは、このチュートリアルの中のすべてをあるべきところに収めてくれます。これは割り込みの設定、割り込み処理、ハードウェア割り込みの間の接着剤になります ;)

このチュートリアルは、より多くの内容を提供し、8259Aマイクロコントローラに関するすべての詳細を説明するために拡張することを計画しています。

このチュートリアルは、本編で使用するサイドチュートリアルです。そのため、このチュートリアルのデモはありません。しかし、このチュートリアルのためにデモを作成する可能性があります。しかし、その場合、IDTや割り込み処理について詳しく説明する必要があります。とにかく、直接的には関係ありません。

このチュートリアルが、PICをプログラミングする際の多くの疑問に答え、フードの内側で実際に何が起こっているかを理解する助けになることを願っています。