GIC(汎用割り込みコントローラ)

GIC(汎用割り込みコントローラ)

ARMプロセッサの割り込みについて復習します。ARMプロセッサ(Cortex-Mシリーズを除く)は、汎用的な例外として、IRQ割り込みとFIQ割り込みを使用します。2入力の割り込みでは、周辺回路からの複数の割り込み要求を優先度に応じてソフトウェア処理することは、割り込みの応答性が懸念されます。この問題を解決するために、GICを使用して割り込み処理の応答性を改善します。GICは、使用するプロセッサによってバージョンが異なります。

  • ①Generic Interrupt Controller Architecture(GIC-390)
  •  ・Cortex-A9 MPCore
  •  ・Cortex-A5 MPCore
  • ②Generic Interrupt Controller Architecture(GIC-400)
  •  ・Cortex-A15 MPCore
  •  ・Cortex-A7 MPCore

Cortex-Mシリーズに搭載されている、NVIC(統合ネスト型ベクタ割り込みコントローラ)との違いは、発生する割り込みに対して割り込みハンドラのアドレスを例外テーブルに記述することで、直接割り込みハンドラを実行することができます。GICは、割り込みハンドラ内で発生している割り込みID番号をレジスタから取得し、ソフトウェアで実行します。

GICブロック図

周辺回路からの複数の割り込みは、GICに接続され、プロセッサのIRQ/FIQ端子を制御します。IRQ割り込みが発生した場合、GICのICCIAR(割り込みアクノリッジレジスタ)に優先度が一番高い割り込みID番号をリードすることができ、その番号に従って割り込み処理を行います。割り込み終了時は、ICCIAR(割り込みアクノリッジレジスタ)の内容を、ICCEOIR(割り込み終了レジスタ)にライトします。

図1

割り込みID番号

GICを使用した場合、3種類の機能で構成されます。

名称 機能 ID 内容
SGI ソフトウェア生成割り込み 0~15 プロセッサ間で割り込みを発生させることができます。ICDSGIR(ソフトウェア生成割り込みレジスタ)に書き込むことで割り込みが発生します。割り込みを発生するプロセッサを選択することができます。
PPI プライベートペリフェラル割り込み 16~31 関連するプロセッサで利用することができます。
ID27:グローバルタイマ
ID28:nFIQ(レガシーFIQ信号)
ID29:プライベートタイマ
ID30:プライベートウオッチドッグ
ID31:nIRQ(レガシーIRQ信号)
SPI 共有ペリフェラル割り込み 254 どのコアからも識別できます。ICDIPTRn(割り込みプロセッサターゲットレジスタ)で選択したプロセッサで割り込みが発生します。

割り込み優先度

GICは、8ビット優先度フィールドを持ち、セキュアステート時は32レベル、ノンセキュアステート時は16レベルの優先度を持ちます。(セキュアステート・ノンセキュアステートについては、「第15回:TrustZone(セキュリティ拡張機能)」を参照ください)

割り込みマスクの設定は、ICCPMR(優先度マスクレジスタ)で行います。GICの割り込み優先度フィールドは、上位側から実装され、32レベルの優先度の場合は、Bit7からBit3で設定を行い、Bit2からBit0は0となります。

図2

【ICCPMR(優先度マスクレジスタ)】

図3

【ICCPMR(割り込み優先度レジスタ)設定サンプルプログラム】

								ICCPMR_OFFSET  EQU  0x0104          ; ICCPMR(優先度マスクレジスタ)オフセット定義
								;
								; 関数形式: void gicc_set_priority_mask(unsigned int priority)
								; priorityは、0から31の範囲で設定
								gicc_set_priority_mask
								     MRC    p15,4,r1,c15,c0,0       ; プライベートメモリ空間の先頭アドレスをリード
								     AND    r0,r0,#0x1F             ; 割り込み設定レベルでマスク
								     MOV    r0,r0,LSL #3            ; マスク設定値を上位側に設定
								     STR    r0,[r1,#ICCPMR_OFFSET]  ; Priority Maskレジスタのライト
								     BX	    lr
								

レジスタ配置アドレス

GICを使用する制御レジスタは、プライベートメモリ空間に配置されます。「割り込みコントローラ」「割り込み分配器」のレジスタ設定が必要です。プライベートメモリ空間の先頭アドレスは、コプロセッサ15のコンフィギュレーションベースアドレスレジスタをリードします。

【プライベート空間に配置されるレジスタ一覧】
オフセットアドレス ペリフェラル名称
0x0000 スヌープ制御ユニット
0x0100 割り込みコントローラ
0x0200 グローバルタイマ
0x0600 プライベートタイマとウオッチドック
0x1000 割り込み分配器

【レジスタへのアクセス命令】

								MRC p15,4,<Rt>,c15,c0,0 ; コンフィギュレーションベースアドレスレジスタの読み込み
								MCR p15,4,<Rt>,c15,c0,0 ; コンフィギュレーションベースアドレスレジスタの書き込み
								

GICの初期化

周辺回路の割り込み設定とGICの初期設定が必要です。GICは、「割り込みコントローラ」と「割り込み分配器」で構成されており、リセット時は停止していますので、稼働状態に設定する必要があります。

図4

ICDISERn(割り込みイネーブルセットレジスタ)

割り込みを使用する場合、ICDISERnに使用する割り込みID番号に割り込み許可設定が必要です。Cortex-A9 MPCoreに搭載されるGICの割り込みは、最大255個(ソフトウェア生成割り込み16個、プライベートペリフェラル割り込み16個、共有ペリフェラル割り込み224個)が、プライベートメモリ空間の先頭からオフセットアドレス0x1100番地から0x111C番地に配置されます。

図5

ICDIPRn(割り込み優先度レジスタ)

割り込みの優先度は、8ビット単位でICDIPTRnに設定が必要です。ICDIPTRnは、プライベートメモリ空間の先頭から、オフセットアドレス0x1400番地から0x14FC番地に配置されます。

図6

ICDIPTRn(割り込みプロセッサターゲットレジスタ)

SPI(共有ペリフェラル割り込み)を使用する場合、割り込み処理を行うプロセッサを選択することができます。プロセッサの選択は、ICDIPTRnへの設定が必要で、8ビット単位で設定を行いますが、下位4ビットが有効となります。ICDIPTRnは、プライベートメモリ空間の先頭からオフセットアドレス0x1800番地から0x18FC番地に配置されます。

プロセッサの選択は、ビット単位で選択することができます。

  • ●Bit0/Bit8/Bit16/Bit24 =CPU0を選択
  • ●Bit1/Bit9/Bit17/Bit25 =CPU1を選択
  • ●Bit2/Bit10/Bit17/Bit25=CPU2を選択
  • ●Bit3/Bit11/Bit18/Bit26=CPU3を選択

SGI[15:0]とPPI[15:0]ついては、設定できません。

図7

ICCICR (CPUインターフェース制御レジスタ)

ターゲットプロセッサへの割り込み信号を可能にします。

ICDDCR(分配器制御レジスタ)

CPUインターフェースへのペンディングの割り込みのフォワーディングを可能にします。

図8

【ICCICR/ICDDCRのレジスタフォーマット】

GICを使用した割り込みハンドラ

IRQ割り込みハンドラでは、レジスタのスタックへの退避処理と復帰処理およびリターンアドレスの補正処理を行います。GICの処理は、C言語で作成されたirq_execution()関数で行います。割り込みハンドラについては、「第7回:例外と割り込み」を参照ください。

【IRQ割り込みハンドラ例】

								IRQ_Handler
								    PUSH {r0-r3,r12,lr}	; スタックにレジスタを退避
								    BL    irq_execution	; 割り込みコントローラ対応割り込み処理関数
								    POP  {r0-r3,r12,lr}	; スタックからレジスタを復帰
								    SUBS pc,lr,#4		; リターンアドレスを補正し例外処理から復帰
								

【割り込みコントローラ対応割り込み処理関数の記述例】

  • ①ICCIARをリードした場合、ペンディング状態の割り込みの中で、最も高い優先度の割り込みIDを返します。
  • ②割り込みIDから該当する、割り込み処理関数を実行します。
  • ③ICCEOIRにICCIARの内容をライトします。

GICは、以下の状態で割り込みの状態を管理します。

  • ●非アクティブ:割り込みが要求されていない状態
  • ●ペンディング:割り込みが要求されているが、プロセッサは受け付けていない状態
  • ●アクティブ :プロセッサが割り込みを受け付けている状態
								void irq_execution(void)
								{
								     int irq_req,irq_no;

								     // ICCIARをリード
								     irq_req = gicc_get_interrupt_acknowledge();
								    // 割り込みID番号を要求
								     irq_no = irq_req & 0x3ff;
								     switch(irq_no){
								      // 割り込みID番号単位で割り込み処理関数を追加
								     }
								     // ICCEOIRにライト
								     gicc_set_end_interrupt(irq_req);
								}
								

ICCIAR(割り込みアクノリッジレジスタ)

ペンディング状態の割り込みで、最も優先度の高い割り込みID番号が「割り込みID番号」に設定されます。CPUIDは、SGI(ソフトウェア生成割り込み)以外では、0となります。

ICCEOIR(割り込み終了レジスタ)

ICCIARの内容を書き込むことで、割り込み処理が終了します。

図9

【ICCIAR/ICCEOIRのレジスタフォーマット】

参考文献

GICの使用法を学ぶためには、次の3種類のマニュアルをお勧めします。