1. 例外発生要因の確認
ソフトウェアの開発を進める中で、例外が発生しその要因が不明なケースがあるかと思います。
本記事では、例外が発生したらユーザー指定のハンドラーに飛ばし、かつその中で例外が発生した要因となる動作とアドレスを確認する方法について紹介します。
本記事は、以下の資料に記載されている内容をまとめたものになります。
📖 Nios® II Software Developer Handbook
9.6. The Nios II Instruction-Related Exception Handler
2. 設定
2-1. BSP エディターの設定
Main タブ内の Advanced ⇒ hal ⇒ enable_instruction_related_exceptions_api にチェックします。
※ 通常は割り込みルーチンに printf を実装することは推奨されませんが、この記事では説明の便宜上 printf を使用して確認しています。その際、以下にもチェックを入れることを推奨します。
Main タブ内の Common ⇒ hal ⇒ enable_reduced_device_drivers
デフォルトの JTAG_UART のドライバーは割り込みベースになっており、割り込みハンドラー内の printf は表示されないためです。こちらのチェックを入れるとポーリングベースになるため、割り込み内でも printf が表示されます。
2-2. 例外ハンドラーの登録と例外ハンドラー関数本体の作成
例外ハンドラーの登録と例外ハンドラー関数本体を含んだコード例になります。
(この記事に添付のファイル:test_exception.c )
例外ハンドラーの登録後、アライメント違反したアクセスを実行しています。
※ 今回のサンプルコードをそのまま使用して例外が発生するかを確認する際は、Platform Designer の Nios II の設定で以下にもチェックを入れてください。
Advanced Features タブ ⇒ Exception Checking ⇒ Misaligned memory access
今回のサンプルコードでは、アライメント違反したデータアクセスにて例外を発生させようとしていますが、Platform Designer のデフォルト設定では、アライメント違反が例外として検知されない状態になっています。そのため、上記設定にてアライメント違反が例外として処理されるよう設定する必要があります。
3. 動作確認
上記のコードを実行(あえてアライメント違反したアクセスを実行)すると、例外ハンドラーでは以下のような結果を出力します。
例外が発生した原因を cause = 0x6 で確認できます。
上記で紹介した Nios® II Software Developer Handbook に掲載のコード表(以下)を確認すると、アライメント違反したアドレスへアクセスしていることがわかり、実際のコードと一致していることがわかります。
また、どの命令で例外が発生したかを addr=0x241201f8 で確認できますが、コードの objdump を確認すると確かにアライメント違反したアドレスへアクセスしたアドレスを指していることがわかります。
例外発生に関連したデータのアドレスを bad_addr で確認できます。
今回の例では bad_addr=0x183 となっていて、objdump より buf のベースアドレスが 0x180 であることがわかります。
アライメント違反させているデータは buf[3] のためアドレスは 0x183 となり、確かにアライメント違反しているデータのアドレスになっていることがわかります。
今回の例では bad_addr が意味を持つ値でしたが、データによらず例外が発生することもあります。基本的には cause/addr のみでデバッグを進めることは可能かと思いますが、例外発生に関わるデータのアドレスが必要な場合は、alt_exception_cause_generated_bad_addr() にて bad_addr が意味のあるデータかを確認することができますので、こちらの API で確認後に bad_addr を使用してください。
おすすめページ
弊社では Nios® II に関する各種情報をまとめた「Nios® II まとめページ」をご用意しております。本記事以外にも有用な情報が満載ですのでこちらも併せてご確認ください。
添付サンプル
以下の添付ファイルは、例外ハンドラーの登録後、アライメント違反したアクセスを実行して例外が発生することを確認するためのサンプル・ソースコードです。