# 例外 (overview)

ここでは、ARM プロセッサによる例外が発生したときに TWL-SDK でその例外の情報を表示するための例外表示システムについて説明します。

## 例外の種類

ARM プロセッサには以下の例外が存在します。

例外タイプ | 正規ベクタアドレス | ハイベクタアドレス
--- | --- | ---
リセット | 0x00000000 | 0xFFFF0000
未定義命令 | 0x00000004 | 0xFFFF0004
ソフトウェア割り込み | 0x00000008 | 0xFFFF0008
プリフェッチアボート | 0x0000000C | 0xFFFF000C
データアボート | 0x00000010 | 0xFFFF0010
IRQ | 0x00000018 | 0xFFFF0018
FIQ | 0x0000001C | 0xFFFF001C

このうち、 リセット割り込みや FIQ 例外は、システムやデバッガで利用していますのでユーザは使用することは出来ません。

IRQ 例外は、割り込みとして利用しています。割り込みに関してはこちらを参照してください。→ 割り込み(概要)

未定義命令の中には、デバッガがブレイクポイントなどに使用しているものもあります。

例外が発生すると、上の表に記載されているベクタアドレスのアドレスに制御が移ります。通常はハイベクタアドレスを使用します。

## 例外ベクタの位置

ARM プロセッサの仕様で、例外ベクタのアドレスとして、0x00000000 〜 0x0000001C か 0xFFFF0000 〜 0xFFFF001C の何れかを選択できるようになっています。前者を「正規ベクタ」、後者を「ハイベクタ」と呼びます。

`OS_SetExceptionVectorLower()` で例外ベクタのアドレスを 0x0000000 〜 0x0000001C (正規ベクタ) にします。

`OS_SetExceptionVectorUpper()` で例外ベクタのアドレスを 0xFFFF0000 〜 0xFFFF001C ( ハイベクタ) にします。

TWL-SDK ではデフォルトではハイベクタを使用しています。特に理由がなければハイベクタを使用し、この設定は変更しないでください。

## 例外時のコンテキスト表示

TWL-SDK には例外発生時に、その時点のコンテキスト(レジスタやCPUステータスの内容) をデバッグウィンドウ(コンソール) へ表示する機構が用意されています。この例外表示機構の初期化は `OS_InitException()` で行われますが、その関数は `OS_Init()` から呼ばれていますので `OS_Init()` を使用するアプリケーションでは特に準備は必要はありません。

以下は表示例です。`OS_FPrintf()` のエラー出力を用いて出力します。

> `**** Exception Occurred ****
> R00=00000000 R01=12345678 R02=2000001F R03=02030340
> R04=200000D7 R05=0000000F R06=00000001 R07=00000002
> R08=02FFFFA8 R09=04000130 R10=00000001 R11=0201C25C
> R12=0200E240 SP =02FE3750 LR =02005130 PC =02005140
> CPSR=2000001F SPSR=00000000 CP15=0005707D`

なお、IS-TWL-DEBUGGER では例外発生した時にデバッガ自体がこの表示を行います。 (IS-TWL-DEBUGGER v1.06 以降で可能です)　 表示の形式は上のと異なります。以下は表示例です。

> `[[ 致命的エラー : ARM9CPU は "データアクセス例外" が発生したため実行を停止しました ]]
> Symbol: STATIC:0x02000C8C
> 02000C8C: E591B000 LDR R11, [R1]
> CPSR:6000001F
> R0:0000007B R1:00000000 R2:00000100 R3:000003E8
> R4:000007D0 R5:00000BB8 R6:00000FA0 R7:00001388
> R8:02000C84 R9:000000FF R10:000000EE R11:00000000
> R12:00000123 SP:027E3750 LR:02000C5C PC:02000C8C`

## ユーザハンドラの設定

IS-NITRO-DEBUGGER や、DS実機、TWL実機では、例外が発生したときに、ユーザが設定した例外ハンドラに制御を移すことが可能です。`OS_SetUserExceptionHandler()` でハンドラを登録してください。詳細はリファレンスを参照してください。

## 例外時コンテキスト表示やユーザ例外ハンドラの呼び出しの可能な環境

動作環境別に、例外発生時にデバッグウィンドウ(コンソール)へコンテキスト表示が行えるかどうかと、ユーザの例外ハンドラに制御を移すことが出来るかを示します。

表中の「例外発生時のコンテキスト表示」は、「例外時のコンテキスト表示」で示したように、IS-NITRO-DEBUGGER ではSDKが行い、IS-TWL-DEBUGGER では デバッガが行います。SDK が表示を行う場合、表示に使っている `OS_FPrintf()` が FINALROMビルドでは使用できないので、「OK (SDKが表示)」となっているものは、FINALROM ビルドではコンテキスト表示は出来ません。「OK (デバッガが表示)」となっているものは、デバッガが表示を行いますので、FINALROMビルドであっても表示することが出来ます。

また、表中の「ユーザの例外ハンドラの呼び出し」は、FINALROM ビルドかどうかというビルド種類には依存しません。

この表は動作環境で切り分けられていることにご注意ください。例えば、 HYBRID ROM を NITRO モードで動作させる場合、IS-TWL-DEBUGGER 上なら例外発生時のコンテキスト表示は行えませんが、同じ ROM を 同じモードで動作させても IS-NITRO-DEBUGGER 上なら表示可能です。

NITRO モードの場合
動作環境 | 例外発生時の `コンテキスト表示` | ユーザの例外ハンドラの 呼び出し
--- | --- | ---
DS実機 | N/A (コンソールが存在しない) | OK
TWL実機 | N/A (コンソールが存在しない) | OK
IS-NITRO-DEBUGGER | OK (SDKが表示) | OK
ENSATA EMULATOR | ??? | ???
IS-TWL-DEBUGGER　(一般開発用: ARM9) | OK (デバッガが表示) | N/A
IS-TWL-DEBUGGER　(コンポーネント開発用　ARM9 + ARM7) | OK (デバッガが表示) | N/A
TWL モードの場合
動作環境 | 例外発生時の `コンテキスト表示` | ユーザの例外ハンドラの 呼び出し
TWL実機 | N/A (コンソールが存在しない) | OK
IS-TWL-DEBUGGER　(一般開発用: ARM9) | OK (デバッガが表示) | N/A
IS-TWL-DEBUGGER　(コンポーネント開発用　ARM9 + ARM7) | OK (デバッガが表示) | N/A

## 例外発生の流れ

以下の例外発生の流れは、IS-NITRO-DEBUGGER や、DS実機、TWL実機 のものです。IS-TWL-DEBUGGER では例外が発生するとその時点で CPU の動作が止まり、デバッガに制御が移りますので図のような動作にはなりません。

IS-NITRO-DEBUGGER 、DS実機、TWL実機では、例外が発生すると例外ベクタの領域にジャンプします。例外ベクタは前述の通り、通常はハイベクタとなりますので、例えばデータアボート例外ならば 0xFFFFFF10 に制御が移ります。

次にシステム領域内の HW_EXCP_VECTOR_MAIN (0x2FFFFD9C) に格納されているアドレスに制御が移ります。 (ARM7 では専用ワークRAM のオフセット 0x7FDC の位置となります。) 　ここにはTWL-SDK の例外ハンドラのアドレスがセットされています。

TWL-SDK の例外ハンドラでは、例外時コンテキスト表示を行った後、あれば `OS_SetUserExceptionHandler()` で登録したユーザハンドラを 呼び出します。

そしてプログラムを停止します。

## 参照

`OS関数一覧(例外)
`

## 履歴

2009/07/01 環境による動作の違いを記述
2008/04/18 例外時コンテキスト表示環境の表追加など
2005/03/08 用語統一 [割込み] → [割り込み]
2004/12/14 用語や語尾など修正
2004/11/16 初版