AVR32のINTC(Interrupt Controller)

ここではAVR32の例としてAT32UC3B0256で説明する。
ドキュメント「AT32UC3B Series Preliminary」(現在はRev.G)を参照のこと。



「15.2 Block Diagram」を見ると判るように、大雑把に3段構成になっている(NMIを除く)。
1段目で各IRQ信号(IRR0〜nレジスタで参照可能)を、論理ORでグループ化する(interrupt group、割込グループ、信号GrpReg0〜N)。
2段目では、「Request masking」がGrpReg信号をIPRレジスタのINTLEVEL(2bit値)でINT0〜3へ変換する。そして、CPUのマスク信号(I3M〜I0MとGM)によりマスクされる(ブロック図との差異は後述)。
3段目でPrioritizerが、NMIも含め、最も優先度の高い割込を判定し、その割込グループのレベルINTLEVELとベクタAUTOVECTOR(IRPのAUTOVECTORのことで、自動ベクタ生成機能がある訳ではない。ややこしい)がCPUの割込ハンドラとコンテキスト・スイッチへ転送される。
結果的に、個々の割込に対するマスク(レベル)やハンドラは明示できず、割込グループのハンドラにジャンプした後、該当割込グループのIRRを参照して、割込要因を確認する必要がある(確認した上で、割込要求を該当周辺モジュールのレジスタでクリアする)。
ICR0〜3レジスタのCAUSEを読めば割込要因が判るが、このレジスタは割込レベル別である。多重割込への対応だろうが、割込レベルが変われば参照するレジスタも変える必要があり、バグの温床となりやすい(IRPにでも入れればいいのに)。現在の割込レベルを毎回取得するか、初期化登録時とハンドラ参照時で同じレベルで処理するようマクロ化などの配慮が必要である。
NMIのIRPは存在せず、当然AUTOVECTOR情報も無く、AVR32アーキテクチャの例外ベクタで固定されている。

注意:Request maskingはI3M〜I0Mでレベルによるマスクのため、IRPのINTLEVEL情報が必要である。この点でブロック図は誤りがあり、IRPのINTLEVELがRequest maskingへ入力されるべきだ。



実際の割込グループと各割込(ブロック図のINT)の関係は、Table 11-3. Interrupt Request Signal Mapに載っている。ブロック図のINTはこの表の「Line」に該当し、他社CPUのような割込要求信号ピンのことではない。AVR32ではEIC(External Interrupts Controller)のEXTINT端子が他社CPUのINT端子に該当する(NMIも同様)。EXTINT端子は、多重機能ピンで切り替えられるため、パッケージのピン情報ではなく、「11.8 Peripheral Multiplexing on I/O lines」を参照すること(これも他社のマニュアルと違うところだ)。

一度割込グループのハンドラに飛び、割込要因を確認した上で、本当の割込処理へ飛ぶ必要があるというのは、割り込み応答速度の低下になり、スピード命のような組み込みでは嫌だなぁ。
利点としては、割り込みベクタ・テーブルを小さくできることぐらいだが、これもFlushROMを使い切った経験がないので有り難みがない。
有効性があるとしたら、オペレーティング・システム、それもドライバ等のパーツが高度にモジュール化されている場合だろうか?
割り込みベクタ・テーブルを削った分、OSで利用できるし、DLLのハンドラを間接的に呼び出すときは良いかもしれない。
2009/11/08 追記
上記の話は誤り。EVBAはException Vector Base Addressの略なので、H8やSHのようなベクタ・テーブル(C言語的に言えば関数ポインタ配列)と勘違いして「EVBAはベクタ・テーブルを指す」というようなことを書いているが、正しくは「EVBAは例外ハンドラのベース・アドレス」であり、例えばNMIのハンドラ本体がEVBA+0x10に配置されている。次のハンドラ(Instruction Address)がEVBA+0x14 から始まるので、領域は僅か4バイトしかない。それなりの処理を記述するなら、別アドレスへジャンプすることになる。
あれ?そうすると、例外ハンドラ(割込ハンドラを除く)はアセンブラで記述するということか?まあ私はそのつもりなんだけど。

2009/11/04 追記
CPUがINTCから割込を受け取ったときの話が抜けていた。

CPUが割込要求を受け取ったとき、その他の例外が保留になっていないかチェックする。
もし優先度の高い例外が保留されていなければ、割込ハンドラが開始される。割込ハンドラを開始したとき、SRレジスタの対応する割込マスク・ビットが同等以下のレベルに対し自動的にセットされる(例えば割込レベル3なら、SRレジスタのI3M〜I0Mがすべてセットされる)。割込ハンドラ・オフセットは、AUTOVECTORとEVBAから計算され、このアドレスへ処理フローが変更される。
割込ハンドラが返る前に、割込要因の割込要求をクリアすることが、割込ハンドラ・ソフトの責務である。もし割込要因の条件がクリアされないと、割込要求がアクティブのまま残る(再度割込が発生する)。
対応する周辺モジュール・レジスタへの書き込みにより割込要求のクリアは実行され、それから対応するNMIREQ/IREQ信号をクリアする。
割込要求をクリアする奨励手順は、周辺レジスタを制御するstore命令の後に、同一レジスタからのダミーload命令を続ける。これはパイプライン・ストールを引き起こし、割込要求がクリアされる前に割込マスクがクリアされ割込ハンドラが返るようなケースにおいて、偶然に再度割込が発生することを防止する。