例外
例外と割り込みの違い
例外とは、プログラムがある処理を実行している途中で、突如として別の仕事(タスク)を要求される処理のことを言います。例外の中で、用途が決まっていない汎用的な例外のことを割り込みと呼んでいます。Armプロセッサ(Cortex-Mシリーズを除く)では、IRQ/FIQを割り込みとして利用することができます。
Cortex-Aシリーズで発生する例外について、発生要因や制御方法を含めて説明します。
リセット例外
すべてのプロセッサにはリセット入力があり、リセット後に直ちにリセット例外を実行します。リセットは最も優先度が高い例外で禁止できません。
未定義命令例外
次の場合に未定義命令例外が発生します。
- コアが本当に定義されていない命令でオペコードの実行を試みた場合
- 適切なコプロセッサがシステムに存在しない場合
- 適切なコプロセッサが存在するが、イネーブルされていない場合
- NEON/VFP(Vector Floating Point)のアクセス権が適切に設定されてない場合
- NEON/VFPが停止状態でNEON/VFP命令を実行した場合
- 非特権モードで、特権命令の実行をした場合
SVC(スーパーバイザコール)例外
ユーザーモードから特権モード状態で実行する命令を呼び出す場合、SVC命令を使用してSVC例外を発生します。SVC例外を使用する場合、SVC命令とSVC番号を使用しますが、命令フォーマットによってSVC番号の設定範囲が異なります。
【Thumb命令では、8ビットSVC番号を含んでいます】
【Arm命令では、24ビットSVC番号を含んでいます】
SVC番号を示すレジスタはありません。SVC例外ハンドラで、SVC命令のアドレスを求め、命令フォーマットに従いSVC番号を求めなければなりません。
プリフェッチアボート例外
「命令フェッチの失敗」が発生した場合、プリフェッチアボート例外が発生します。IFSR(命令フォールトステータスレジスタ)で発生要因、IFAR(命令フォールトアドレスレジスタ)で発生したアドレスを確認することができます。
【IFSR】
IFSRには、最後の命令フォールトに関するステータス情報が保持されます。32ビットのレジスタとして定義され、特権モードのみでのアクセスが可能です。セキュリティ拡張機能が実装されている場合は、バンクレジスタとなります。
【レジスタフォーマット】
ビット | 名称 | 内容 |
---|---|---|
12 | Ext | 外部アボートタイプ 外部データアボートの実装定義の分類を提供するために使用可能です。 外部アボート以外のアボートでは、このビットは常に0を返します。 |
10,3:0 | FS | フォルトスタータスビット 「Armアーキテクチャリファレンスマニュアル Armv7-AおよびArmv7-Rエディション VMSA(仮想メモリシステムアーキテクチャ)VMSAv7 IFSRのエンコード」を参照ください。 |
【レジスタへのアクセス命令】
MRC p15,0,<Rt>,c5,c0,1 ; IFSRの読み込み。 MCR p15,0,<Rt>,c5,c0,1 ; IFSRへの書き込み。
データアボート例外
「データアクセスの失敗」が発生およびデータボート例外が発生した場合、DFSR(データフォールトステータスレジスタ)で発生要因がわかります。
【DFSR】
DFSRには、最後のデータフォールトに関するステータス情報が保持されます。32ビットレジスタとして定義され、特権モードのみでのアクセスが可能です。セキュリティ拡張機能が実装されている場合は、バンクレジスタとなります。
【レジスタフォーマット】
ビット | 名称 | 内容 |
---|---|---|
12 | Ext | 外部アボートタイプ 外部データアボートの実装定義の分類を提供するために使用可能です。外部アボート以外のアボートでは、このビットは常に0を返します。 |
11 | WnR | アボート発生時のアクセス 0:読み込みアクセスで引き起こされたアボートです。 1:書き込みアクセスで引き起こされたアボートです。 |
10,3:0 | FS | フォルトスタータスビット 「Armアーキテクチャリファレンスマニュアル Armv7-AおよびArmv7-Rエディション VMSA(仮想メモリシステムアーキテクチャ)VMSAv7 DFSRのエンコード」を参照ください。 |
7:4 | ドメイン | フォールトアドレスのドメイン |
【レジスタへのアクセス命令】
MRC p15,0,<Rt>,c5,c0,0 ; DFSRの読み込み。 MCR p15,0,<Rt>,c5,c0,0 ; DFSRへの書き込み。
割り込み
IRQ割り込み
cpsr(カレントプログラムステータスレジスタ)のIビットが0およびIRQ端子が有効になった場合、IRQ割り込み例外が発生します。IRQ割り込みの禁止・許可はソフトウェアで設定可能です。
コンパイラ組み込み関数を使用してのIRQ割り込み制御方法
Armコンパイラでは、組み込み関数でIRQ割り込みの許可・禁止を設定できます。
関数名 | 動作概要 |
---|---|
int __disable_irq(void) | IRQ割り込みを禁止にし、設定前のIRQ割り込み設定値を返します。 |
void __disable_irq(void) | IRQ割り込みを禁止します。 |
void __enable_irq(void) | IRQ割り込みを許可します。 |
全アーキテクチャで動作可能なIRQ割り込み制御プログラム例
cpsrのリード・モディファイ・ライト動作を行いますので、アトミック(*1)な操作ではありません。
I_Bit EQU 0x80 ; IRQビットを定義。 ; IRQ割り込みを許可。 ; 関数型式:void enable_irq(void) enable_irq MSR r0,CPSR ; cpsrをr0レジスタに読み込み。 BIC r0,#I_Bit ; Iビットを0に設定。 MRS CPSR_c,r0 ; cpsrにr0レジスタを書き込み。 BX lr ; 関数をリターン。 ; IRQ割り込みを禁止。 ; 関数型式:void disable_irq(void) disable_irq MSR r0,CPSR ; cpsrをr0レジスタに読み込み。 ORR r0,#I_Bit ; Iビットを1に設定。 MRS CPSR_c,r0 ; cpsrにr0レジスタを書き込み。 BX lr ; 関数をリターン。
(*1)アトミックとは、複数の操作を組み合わせた場合、システムの他の部分から見て、一つの操作になることです。
Arm v6以降で動作可能なIRQ割り込み制御プログラム例
Cortex-Aシリーズでは、Arm v6以降で使用できる、IRQ割り込み許可・禁止命令を使用可能です。
; IRQ割り込みを許可。 ; 関数型式:void enable_irq(void) enable_irq CPSIE I ; IRQ割り込みを許可。 BX lr ; 関数をリターン。 ; IRQ割り込みを禁止。 ; 関数型式:void disable_irq(void) disable_irq CPSID I ; IRQ割り込みを禁止。 BX lr ; 関数をリターン。
FIQ割り込み
cpsrのFビットが0およびFIQ端子が有効になった場合、FIQ割り込み例外が発生します。FIQ割り込みの禁止・許可はソフトウェアで設定可能です。
コンパイラ組み込み関数を使用してのFIQ割り込み制御方法
Armコンパイラでは、組み込み関数でFIQ割り込みの許可・禁止を設定できます。
関数名 | 動作概要 |
---|---|
int __disable_fiq(void) | FIQ割り込みを禁止にし、設定前のFIQ割り込み設定値を返します。 |
void __disable_fiq(void) | FIQ割り込みを禁止します。 |
void __enable_fiq(void) | FIQ割り込みを許可します。 |
全アーキテクチャで動作可能なFIQ割り込み制御プログラム例
cpsrのリード・モディファイ・ライト動作を行いますので、アトミックな操作ではありません。
F_Bit EQU 0x40 ; FIQビットを定義。 ; FIQ割り込みを許可。 ; 関数型式:void enable_fiq(void) enable_fiq MSR r0,CPSR ; cpsrをr0レジスタに読み込み。 BIC r0,#F_bit ; Fビットを0に設定。 MRS CPSR_c,r0 ; cpsrにr0レジスタを書き込み。 BX lr ; 関数をリターン。 ; FIQ割り込みを禁止。 ; 関数型式:void disable_fiq(void) disable_fiq MSR r0,CPSR ; cpsrをr0レジスタに読み込み。 ORR r0,#F_bit ; Fビットを1に設定。 MRS CPSR_c,r0 ; cpsrにr0レジスタを書き込み。 BX lr ; 関数をリターン。
Arm v6以降で動作可能なFIQ割り込み制御プログラム例
Cortex-Aシリーズでは、Arm v6以降で使用できる、FIQ割り込み許可・禁止命令を使用可能です。
; IRQ割り込みを許可。 ; 関数型式:void enable_fiq(void) enable_fiq CPSIE F ; FIQ割り込みを許可。 BX lr ; 関数をリターン。 ; IRQ割り込みを禁止。 ; 関数型式:void disable_fiq(void) disable_fiq CPSID F ; FIQ割り込みを禁止。 BX lr ; 関数をリターン。
IRQ割り込み処理ハンドラの記述例
Cortex-Aシリーズで割り込みハンドラを記述する場合、アセンブリ言語で記述することが一般的です。以下の手順で、割り込みハンドラを作成します。
- r0からr3,r12,r14(lr)の各レジスタをスタックに退避。
- irq_handler()関数を呼び出して、割り込み処理を実行。
- スタックから、r0からr3,r12,r14(lr)の各レジスタを復帰。
- r14(lr)を補正し復帰。
IRQ割り込みハンドラ例
IRQ_Handler PUSH {r0-r3,r12,lr} ; スタックにレジスタを退避。 BL irq_handler ; 割り込みハンドラを呼び出し。 POP {r0-r3,r12,lr} ; スタックからレジスタを復帰。 SUBS pc,lr,#4 ; リターンアドレスを補正し、例外処理から復帰。
なぜ、r0からr3,r12,r14(lr)の各レジスタをスタックに退避するのでしょうか?「AAPCS(Armアーキテクチャのプロシージャコール標準)」にヒントがあります。
- r4からr11の各レジスタを使用する場合、スタックに退避するので、割り込みハンドラで退避しません。
- r0からr3、r12の各レジスタを使用する場合、スタックに退避しないので、割り込みハンドラでスタックに退避します。
- r14(lr)レジスタは、irq_handler()関数の呼び出しで使用しますので、スタックに退避します。
こちらも是非
“もっと見る” Cortex-A編
初期化処理
リセット例外からmain()関数を呼び出すまでの初期化は、ユーザが作成する部分とArmコンパイラが実行する部分に分けることができます。コードのコピーや初期化変数/未初期化変数の初期化は、リンカのメモリ配置設定を処理系ライブラリが実行します。
PMU(パフォーマンス監視ユニット)
PMUに関連するレジスタは、ユーザモードでのアクセスは禁止されていますので、PMUSERENR(ユーザイネーブルレジスタ)を特権モードでユーザモードアクセス許可を設定します。PMUSERENRについては、 後述の該当項目を参照ください。
TrustZone(セキュリティ拡張機能)
TrustZoneはCortex-Aシリーズの拡張機能で、大規模OSやアプリケーションが動作するノーマルワールドとセキュリティ関連が動作するセキュアワールドを導入しています。TrustZoneでは、ノーマルワールドメモリ空間とセキュアワールドメモリ空間の分離が可能です。