ベクタテーブル
ベクタテーブルとは
例外が発生した際に、処理を開始するプログラム(一般的には、「例外ハンドラ」と呼ぶ)を実行するための命令や、アドレスを保存するテーブルをベクタテーブルと呼んでいます。
Armプロセッサのベクタテーブルとは
Armプロセッサのベクタテーブルは、0x00000000番地に配置されますが、CP15システムコントロールレジスタのV-bit(bit 13)、またはVINITHI端子で、上位ベクタアドレス(0xFFFF0000番地)に移動させることができます。セキュリティ拡張が行われており、上位ベクタアドレスを選択していない場合は、VBAR(ベクタベースアドレスレジスタ)でベクタアドレスを変更することが可能です。
ベクタテーブルには、Arm命令(32ビット)の分岐命令を記述しますが、FIQ割り込みはベクタテーブルの最終アドレスに配置されますので、分岐命令を使用せずに、直接割り込みハンドラを記述することが可能です。
FIQ割り込みは専用レジスタが多く用意されており、割り込み処理時のスタックへのレジスタ退避復帰時間が短縮されるため、高速に処理を行うことができます。レジスタセットについては、「第4回:レジスタ」を参照ください。
ノーマルベクタオフセット | 上位ベクタアドレス | 例外要因 | |
---|---|---|---|
0x00 | 0xFFFF0000 | リセット | |
0x04 | 0xFFFF0004 | 未定義命令例外 | |
0x08 | 0xFFFF0008 | スーパーバイザコール(SVC) | |
0x0C | 0xFFFF000C | プリフェッチアボート | |
0x10 | 0xFFFF0010 | データアボート | |
0x14 | 0xFFFF0014 | 予約 | |
0x18 | 0xFFFF0018 | IRQ割り込み | |
0x1C | 0xFFFF001C | FIQ割り込み | |
…. |
ベクタテーブルの記述方法
割り込みベクタテーブルを作成する場合、2つの方法があります。LDR命令(リテラルプール)を使用する方法とB命令(PC相対分岐命令)を使用する方法です。B命令は、±32Mbyteの範囲内に例外ハンドラを記述することで、LDR命令よりも、高速に実行することができます。
【LDR命令(リテラルプール)を使用したベクタテーブル】
PRESERVE8 ; 8バイト境界で境界調整されたスタックを保持 AREA VECTORS,CODE,READONLY ; VECTORS領域としてセクションを定義 Vectors_Table LDR PC,Reset_Addr ; リセット例外 LDR PC,Undefined_Addr ; 未定義命令例外 LDR PC,SVC_Addr ; ソフトウェア割り込み LDR PC,Prefetch_Addr ; プリフェッチアボート例外 LDR PC,Abort_Addr ; データアボート例外 B . ; 予約ベクタテーブル LDR PC,IRQ_Addr ; IRQ割り込み LDR PC,FIQ_Addr ; FIQ割り込み ; ; 実行開始処理アドレス定義 ; Reset_Addr DCD Reset_Handler ; 例外ハンドラ先頭アドレス定義 Undefined_Addr DCD Undefined_Handler ; 未定義命令例外ハンドラ先頭アドレス定義 SVC_Addr DCD SVC_Handler ; ソフトウェア割り込みハンドラ先頭アドレス定義 Prefetch_Addr DCD Prefetch_Handler ; プリフェッチアボート例外ハンドラ先頭アドレス定義 Abort_Addr DCD Abort_Handler ; データアボート例外ハンドラ先頭アドレス定義 IRQ_Addr DCD IRQ_Handler ; IRQ割り込みハンドラ先頭アドレス定義 FIQ_Addr DCD FIQ_Handler ; FIQ割り込みハンドラ先頭アドレス定義
【B命令(PC相対分岐命令)を使用したベクタテーブル】
PRESERVE8 ; 8バイト境界で境界調整されたスタックを保持 AREA VECTORS,CODE,READONLY ; VECTORS領域としてセクションを定義 Vectors_Table B Reset_Handler ; リセット例外ハンドラ B Undefined_Handler ; 未定義命令例外ハンドラ B SVC_Handler ; ソフトウェア割り込みハンドラ B Prefetch_Handler ; プリフェッチアボート例外ハンドラ B Abort_Handler ; データアボート例外ハンドラ B . ; 予約ベクタテーブル B IRQ_Handler ; IRQ割り込み B FIQ_Handler ; FIQ割り込み
ベクタテーブルの配置方法
ターゲットのメモリ配置設定(ROM/RAMなどの設定)は、Armコンパイラの場合、スキャッタローディングと呼ばれる方法で設定を行います。ベクタを記述したアセンブリソースファイル「vector.s」を、セクション名「VECTORS」として設定します。詳しくは、「Armコンパイラ armlinkユーザガイド」を参照ください。
【スキャッタローディングファイル例】
LOAD 0x00000000 0x20000000 ; 256Mbyteメモリに配置 { VECTORS 0x00000000 { vector.o(VECTORS,+FIRST) ; ベクタテーブルは、0x00000000先頭から配置 *(+RO) ; 他のオブジェクトを配置 } … … }
スキャッタローディングファイルでは、ベクタテーブルをFIRST属性に設定し、VECTORSセクションをイメージの先頭に配置します。この設定方法で、ベクタテーブルは、0x00000000番地から配置されます。他のオブジェクトは、リンカ配置ルールに従って配置されます。
例外
例外発生時のプロセッサの動作
- 例外が発生した場合、実行中のアセンブラ命令終了後、cpsr(カレントプログラムステータスレジスタ)を該当モードのspsr(保存プログラムステータスレジスタ)に、リターンアドレスは該当モードのr14に保存されます。
- プロセッサモードを変更し、例外発生要因に応じた例外が禁止されます。
- ベクタテーブルの命令に従って、例外ハンドラを呼び出します。
- 必要に応じて、レジスタをスタックに退避します。
- 例外ハンドラを実行します。
- スタックに退避したレジスタを復帰します。
- 例外発生要因に応じた復帰処理を行います。
例外の優先度とは
例外には優先度が設定されており、複数の例外が同時に発生する場合は、優先度に従って処理を行います。リセット例外の優先度が一番高く、どの様な状況でも実行できます。
例外要因と動作モード
例外の発生で、プロセッサの動作モードが決定すると同時に、例外禁止設定も決定されます。IRQ/FIQ割り込みは、禁止/許可の設定ができますが、他の例外は行うことができません。Armコンパイラは、IRQ/FIQ割り込み制御の組み込み関数が用意されているので、C/C++言語から利用できます。
例外要因 | 動作モード | 発生要因 | 例外禁止 | |
---|---|---|---|---|
FIQ | IRQ | |||
リセット例外 | スーパーバイザ | リセット入力後でリセット例外を実行します。リセット例外は最も優先度が高い例外で、例外禁止を実行できません。 | × | × |
未定義命令例外 | 未定義 | 未定義命令を実行した場合に発生します。 | — | × |
SVC(スーパーバイザコール) | スーパーバイザ | SVC命令を実行した場合に発生します。 | — | × |
プリフェッチアボート | アボート | 無効なアドレスからの命令フェッチを実行した場合に発生します。 | — | × |
データアボート | アボート | 無効なアドレスからのデータのリード・ライトを実行した場合に発生します。 | — | × |
IRQ割り込み | IRQ | IRQ入力された場合に発生します。 | — | × |
FIQ割り込み | IRQ | IRQ入力された場合に発生します。 | × | × |
例外動作時のレジスタセットの動作
IRQ割り込みが発生した場合のレジスタセットの動作について説明します。
- r13とr14がIRQ割り込み専用に切り替わります。
- cpsrがIRQモード用のspsrに保存されます。
- RQ割り込みが禁止になります。
例外からの復帰方法
例外が発生した場合、例外要因に従って動作モードのリンクレジスタに戻りアドレスが設定されます。例外から復帰する場合は、発生している例外要因に従って、リンクレジスタr14を補正しなければなりません。
【リンクレジスタ補正値一覧表】
例外要因 | 補正値 | 復帰先 |
---|---|---|
SVC | 0 | 次の命令 |
未定義命令例外 | 0 | 次の命令 |
プリフェッチアボート | -4 | アボートを発生させた命令 |
データアボート | -8 | アボートを発生させた命令(正確なアボートの場合) |
FIQ割り込み | -4 | 次の命令 |
IRQ割り込み | -4 | 次の命令 |
例外復帰を行う場合は、次の動作をアトミック(*1)に行うことが必要です。
- リンクレジスタr14を必要に応じて補正し、プログラムカウンタr15をコピーします。
- spsrからcpsrにコピーします。
(*1)アトミックとは、複数の操作を組み合わせた場合、システムの他の部分から見て、一つの操作になることです。
こちらも是非
“もっと見る” Cortex-A編
初期化処理
リセット例外からmain()関数を呼び出すまでの初期化は、ユーザが作成する部分とArmコンパイラが実行する部分に分けることができます。コードのコピーや初期化変数/未初期化変数の初期化は、リンカのメモリ配置設定を処理系ライブラリが実行します。
PMU(パフォーマンス監視ユニット)
PMUに関連するレジスタは、ユーザモードでのアクセスは禁止されていますので、PMUSERENR(ユーザイネーブルレジスタ)を特権モードでユーザモードアクセス許可を設定します。PMUSERENRについては、 後述の該当項目を参照ください。
TrustZone(セキュリティ拡張機能)
TrustZoneはCortex-Aシリーズの拡張機能で、大規模OSやアプリケーションが動作するノーマルワールドとセキュリティ関連が動作するセキュアワールドを導入しています。TrustZoneでは、ノーマルワールドメモリ空間とセキュアワールドメモリ空間の分離が可能です。