ARMには7種類の割り込みがある。
リセット、未定義命令、ソフトウェア割り込み、プリフェッチアボート、データアボート、IRQ、FastIRQ
割り込みハンドラは割り込みベクタにアドレスを設定する。
割り込みベクタは通常は0x00000000に、上位ベクタ機能を有効にした場合は0xFFFF0000にある
ARM v7 Architecture Reference Manualの54ページA2.6 例外
割り込みからの復帰はlrレジスタを使う。しかし割り込みの種類によって復帰命令が異なる
以下の表に割り込みの一覧と復帰命令を記載する
■割り込みベクタ
割り込み | オフセット | 復帰命令 | 説明 |
---|---|---|---|
リセット | 0 | なし | CPUリセット時に実行される |
未定義命令 | 4 | movs pc, lr | CPUがサポートしていない不正な命令を実行しようとした場合に呼び出される |
ソフトウェア割り込み | 8 | movs pc, lr | ソフトウェア割り込み命令SWIを実行した場合に呼び出される。大方の場合カーネルサービス呼び出しに使用する |
プリフェッチアボート | 12 | subs pc, lr, #4 | 命令コードをフェッチしようとしたときにコードを読み出そうとしたアドレスからメモリ読み出しが出来なかったときに呼び出される。MMUが有効化していて仮想アドレスのエントリが不在となっている場合に発生する |
データアボート | 16 | subs pc, lr, #8 | 読み出そうとしたアドレスからメモリ読み出しが出来なかったときに呼び出される。MMUが有効化していて仮想アドレスのエントリが不在となっている場合に発生する |
未使用 | 20 | 未使用の割り込みエントリ | |
IRQ | 24 | subs pc, lr, #4 | ハードウェアからIRQが発生したときに呼び出される。 |
FastIRQ | 28 | subs pc, lr, #4 | ハードウェアからIRQが発生したときに呼び出される。 |
■割り込みベクタ設定例
アセンブラ命令で割り込みベクタの各エントリに割り込みハンドラへのジャンプ命令を設定する。
割り込みベクタ先頭をinterrupt_vector_startとすると以下のように記述する
interrupt_vector_start:
ldr pc, =_reset;
ldr pc, =_invalid_opcode;
ldr pc, =_service;
ldr pc, =_prefetch_abort;
ldr pc, =_data_abort;
nop;
ldr pc, =_irq;
ldr pc, =_fast_irq;
■上位ベクタ
通常の割り込みベクタアドレスは0x00000000だが、これを上位アドレス0xFFFF0000に移すことができる。上位ベクタ機能はCP15 C1 Control RegisterのVビットを1にセットすることで有効化できる
当然のことながらMMUを有効化して0xFFFF0000の仮想アドレスに対するメモリを設定しておく必要がある。
31 30 29 28 27 26 25 24 13 12 11 10 2 1 0
+---------------------------------------------------------------------+
| 0 | TE | AFE | TRE | NMFI | 0 | EE | 0 | V | I | Z | 0 | C | A | M |
+---------------------------------------------------------------------+
■上位ベクタ有効化
unsigned long value;
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(value));
value |= (1 << 13);
asm("mcr p15, 0, %0, c1, c0, 0;" : : "r"(value));