1 =割り込みコントローラをマルチベクタ モードに設定する 0 =割り込みコントローラをシングルベクタ モードに設定するこれにより、マルチベクタ モードになっていると分かります。これは割込みが、種類により異なるスタートアドレスを持つモードです。
INTSTAT | 割り込みステータス レジスタ | この読み出し専用レジスタは、CPUに提示する割り込み優先度またはベクタのステータスを格納します。 |
IPTMR | 割り込み近接タイマレジス | このレジスタは、CPUに提示するまで割り込みを保持しておくタイミング ウィンドウを制 御します。 |
IFSx | 割り込みフラグ ステータス レジスタ | これらのレジスタは、各種割り込み要因のステータスを示すフラグを格納し、これらの割り込み要因のクリアも行います。 |
IECx | 割り込みイネーブル制御レジスタ | これらのレジスタは、割り込み要因によるCPU割り込みのトリガを有効または無効とするフラグを格納します。 |
IPCx | 割り込み優先度制御レジスタ | これらのレジスタは、各種割り込み要因の優先度と副優先度を制御します。 |
IRQはSYSCLKの立ち上がりエッジでサンプリングされ、対応するIFSxレジスタにラッチされます。 (これでIFSxのフラグビットが「1」の保留状態になる)
割り込みをサービスしている時、プロセッサコアはプログラム カウンタをCPU内の例外プログラム カ ウンタ(EPC:CP0の14番)レジスタにプッシュし、
CPU内の例外レベル(EXL)ビット(Status<1>)をセットします。
EXLビットがセットされると、アプリケーションが明示的にEXLビットをクリアするまで後続の割り込みは無効にされ、
CPUは提示されたベクタ番号から算出したベクタアドレスへ分岐します。
例外からの復帰(ERET)命令が実行されると、プロセッサは以前の状態に戻ります。ERET命令はEXLビットをクリアし、プログラム カウンタを復元します。
(なおERETの前に、割り込みの原因となったIFSxのフラグビットを明示的にクリアする必要があります。)
特殊機能レジスタ(SFR)のIPC0〜IPC10で、各割り込みベクタにグループ優先度と、副優先度を設定します。
一つのレジスタで、4 個の割り込みベクタのグループ優先度(3bit)と副優先度(2bit)が格納されます。
グループ優先度は、 1( 最低優先度 ) から 7( 最優先 ) の間で選択でき、より高い優先度の割り込みベクタから先に処理されます。
割り込み優先度をゼロに設定すると、その割り込みベクタは割り込み用としても復帰用としても無効になります。
割り込みを再度有効にする前に、RIPL<2:0>ビット(Cause<12:10>) の値を、
IPL<2:0>ビット(Status<12:10>)に転送する必要があります。
この操作は、割り込みサービスルーチン (ISR) が完了するまで、それよりも低優先度の全ての割り込みを無効にします。
各グループ優先度内で副優先度を割り当てる事ができます。
ある割り込みのサービス中に、優先度が同じで副優先度がより高い割り込みが発生しても、サービス中の副優先度の低い割り込みは保留されません。
しかし、同じ優先度を持つ2つの割り込みが保留中である場合、副優先度が高い方の割り込みが先に処理されます。
副優先度は 0( 最低優先度 ) から 3( 最優先 ) の間で選択できます。
同じグループ優先度と同じ副優先度を割り当てた場合、割り込みベクタの番号が小さいほど優先度が高くなります。
保留中のIRQに対応するIECxビット(割り込みイネーブル レジスタ内)がクリアされている場合、そのIRQに起因するその後の処理は行いません。 (IECxビットは、割り込みフラグをマスクする作用があります。)
INTSTATレジスタは、現在保留中の割り込みの割り込み要求アドレスと SRIPL<2:>ビット(INTSTAT<10:8>) を格納します。 これはコアを通常の動作から分岐させた割り込みとは異なる場合があります。
__ISR(v,ipl)これで、優先度ipl を持ち、ベクタ番号v の割込みベクタを定義します。
void __ISR(_CORE_TIMER_VECTOR, IPL7SOFT) CTInterruptHandler(void) { IFS0CLR = _IFS0_CTIF_MASK; // 割り込み要求フラグをクリア _RB15 = ! _RB15;// 出力を反転 _CP0_SET_COMPARE(2000000u);//この値までカウントしたら割り込む _CP0_SET_COUNT(0);//コアタイマを0にセット(CP0の9番レジスタ) }参考に上記のディスアセンブラ( disassembler「逆アセンブラ」)のコード例を示す。
271: void __ISR(_CORE_TIMER_VECTOR, IPL7SOFT) CTInterruptHandler(void)
272: {
9D00759C 415DE800 RDPGPR SP, SP
9D0075A0 401A7000 MFC0 K0, EPC
9D0075A4 401B6000 MFC0 K1, Status
9D0075A8 27BDFFE8 ADDIU SP, SP, -24
9D0075AC AFBB0014 SW K1, 20(SP)
9D0075B0 7C1B7844 INS K1, ZERO, 1, 15
9D0075B4 377B1C00 ORI K1, K1, 7168
9D0075B8 409B6000 MTC0 K1, Status
9D0075BC AFBF000C SW RA, 12(SP)
9D0075C0 AFA40008 SW A0, 8(SP)
9D0075C4 AFA30004 SW V1, 4(SP)
9D0075C8 AFA20000 SW V0, 0(SP)
273: IFS0CLR = _IFS0_CTIF_MASK; // 割り込み要求フラグをクリア
9D0075CC 24030001 ADDIU V1, ZERO, 1
9D0075D0 3C02BF88 LUI V0, -16504
9D0075D4 AC431034 SW V1, 4148(V0)
274: _RB15 = ! _RB15;// 出力を反転
9D0075D8 3C02BF88 LUI V0, -16504
9D0075DC 8C446120 LW A0, 24864(V0)
9D0075E0 38848000 XORI A0, A0, -32768
9D0075E4 7C8403C0 EXT A0, A0, 15, 1
9D0075E8 94436120 LHU V1, 24864(V0)
9D0075EC 7C837BC4 INS V1, A0, 15, 1
9D0075F0 A4436120 SH V1, 24864(V0)
275: _CP0_SET_COMPARE(2000000u);//この値までカウントしたら割り込む
9D0075F4 3C02001E LUI V0, 30
9D0075F8 34428480 ORI V0, V0, -31616
9D0075FC 40825800 MTC0 V0, Compare
9D007600 000000C0 EHB
276: _CP0_SET_COUNT(0);//コアタイマを0にセット(CP0の9番レジスタ)
9D007604 00001021 ADDU V0, ZERO, ZERO
9D007608 40824800 MTC0 V0, Count
9D00760C 000000C0 EHB
277: }
9D007610 8FBF000C LW RA, 12(SP)
これを呼び出すベクタは次のようになっていた。_CP0_GET_EBASE()が「9d03f000」の場合です。これで、割込みがあると、
上記9d00759cの位置に処理が移動します。
9d03f200 <__vector_dispatch_0>:
9d03f200: 0b401d67 j 9d00759c <.LFE957>
9d03f204: 00000000 nop