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(割り込み終了レジスタ)にライトします。
割り込み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となります。
【ICCPMR(優先度マスクレジスタ)】
【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は、「割り込みコントローラ」と「割り込み分配器」で構成されており、リセット時は停止していますので、稼働状態に設定する必要があります。
ICDISERn(割り込みイネーブルセットレジスタ)
割り込みを使用する場合、ICDISERnに使用する割り込みID番号に割り込み許可設定が必要です。Cortex-A9 MPCoreに搭載されるGICの割り込みは、最大255個(ソフトウェア生成割り込み16個、プライベートペリフェラル割り込み16個、共有ペリフェラル割り込み224個)が、プライベートメモリ空間の先頭からオフセットアドレス0x1100番地から0x111C番地に配置されます。
ICDIPRn(割り込み優先度レジスタ)
割り込みの優先度は、8ビット単位でICDIPTRnに設定が必要です。ICDIPTRnは、プライベートメモリ空間の先頭から、オフセットアドレス0x1400番地から0x14FC番地に配置されます。
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]ついては、設定できません。
ICCICR (CPUインターフェース制御レジスタ)
ターゲットプロセッサへの割り込み信号を可能にします。
ICDDCR(分配器制御レジスタ)
CPUインターフェースへのペンディングの割り込みのフォワーディングを可能にします。
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の内容を書き込むことで、割り込み処理が終了します。
参考文献
GICの使用法を学ぶためには、次の3種類のマニュアルをお勧めします。
Generic Interrupt Controller(PL390) Technical Reference Manual
Arm Generic Interrupt Controller Architecture Specification
Cortex-A9 MPCore Revision: r4p1 Technical Reference Manual
こちらも是非
“もっと見る” Cortex-A編
初期化処理
リセット例外からmain()関数を呼び出すまでの初期化は、ユーザが作成する部分とArmコンパイラが実行する部分に分けることができます。コードのコピーや初期化変数/未初期化変数の初期化は、リンカのメモリ配置設定を処理系ライブラリが実行します。
PMU(パフォーマンス監視ユニット)
PMUに関連するレジスタは、ユーザモードでのアクセスは禁止されていますので、PMUSERENR(ユーザイネーブルレジスタ)を特権モードでユーザモードアクセス許可を設定します。PMUSERENRについては、 後述の該当項目を参照ください。
TrustZone(セキュリティ拡張機能)
TrustZoneはCortex-Aシリーズの拡張機能で、大規模OSやアプリケーションが動作するノーマルワールドとセキュリティ関連が動作するセキュアワールドを導入しています。TrustZoneでは、ノーマルワールドメモリ空間とセキュアワールドメモリ空間の分離が可能です。