実機テストの前に複雑な状況をデバッグする方法
IAR Embedded WorkbenchのデバッガであるC-SPYには、デバッグプロセスの自動化と周辺機器のシミュレーションを可能にする便利なマクロ機能が含まれています。マクロは、複雑なブレークポイントや割込みシミュレーションと組み合わせて使用することで、ホストPC上にあるターゲットメモリやファイルとの間での読出しや書込み、リセット、文字列操作、JTAGコマンドなど、さまざまなタスクを実行することができます。これにより、実機テストの前に複雑な状況を再現させ、先行してデバッグを行うことが可能です。
この記事ではマクロの基本について解説し、その使用例を示します。
C-SPYマクロの構文
マクロの構文はC言語と似ており、以下のものがあります。
- マクロ文:C言語の文によく似ています。
- マクロ関数:パラメータと戻り値の有無を定義できます。
- 定義済み組込みシステムマクロ:C言語のライブラリ関数に似ており、ファイルのオープンとクローズ、ブレークポイントの設定、割込みシミュレーションの定義といった便利なタスクを実行します。
- マクロ変数:グローバルまたはローカルを選択可能で、C-SPYの式に使用できます。
- マクロ文字列:定義済みシステムマクロを使って操作できます。
デバッガでのマクロの使用方法
C-SPYのマクロは、特定の時点で呼び出したり、手動あるいはブレークポイントにより実行したりすることができます。
セットアップマクロ
セットアップマクロは既定の名前が付いたマクロで、ターゲットのリセット毎など、あらかじめ決められたタイミングで呼び出されます。これらのマクロは、例えばアプリケーションをダウンロードする前に一部のメモリ領域をクリアしたり特定の値で埋めたりするなど、次に検証したいステップへ移る前のデバイスの準備に使用することができます。
このマクロが有用な例としては、アプリケーションを正しく動作させるのに特定のデータを必要とするシステムで、ブートプロセスの開発が完了していない場合が挙げられます。このような場合でも、開発者によるブートプロセスの開発完了を待たずに、アプリケーションをテストすることができます。例えば、ファイルなどからメモリをロードするマクロをアプリケーションのロード前に実行すれば、テスト対象のコードを変更する必要もありません。
マクロの実行による効率的なデバッグ
マクロはこれ以外にも、手動で実行したり、ブレークポイントを使って実行したりすることができます。ブレークポイントは、マクロ実行時の条件に応じて、別のマクロによって設定できます。これは、イベント駆動型システムのネスト化された一連のイベントをデバッグする際に非常に便利で、特定の条件でイベントが発生するまではシステムの実行を止めずに動かし続けることができます。一例として、10秒と0.1秒の2つのタイマ割込みを持つシステムを考えます。今、低速のイベントが2回トリガされた後に高速のイベントがトリガされた場合、最初に何が起こるかを確認したいものとします。低速イベントにはブレークポイントが設定されており、このブレークポイントは呼び出されたのが2回目かをチェックするマクロを呼び出します。2回目の場合、マクロは高速イベントにもブレークポイントを設定します。
このマクロの実装例を下に示します。マクロにはマクロ変数としてカウンタSlowInterruptCountが含まれており、低速タイマが実行されるごとに値が加算されます。このカウンタが2になると、マクロは高速タイマ割込みハンドラの入口にコードブレークポイントを設定します。
SetBreakpoint(){
if (SlowInterruptCount++ == 2)
{
brk = __setCodeBreak("Fast_Interrupt_Handler", 0, "1", "TRUE", "");
}
}
マクロの使用例
デバッグセッションでC-SPYマクロを使用するには、事前に登録する必要があります。最も簡単な方法は、デバッガのプロジェクトオプションを使って、C-SPYマクロを定義したテキストファイルを追加することです。
下に示すセットアップマクロ関数はデバッガを起動すると実行され、デバッグログウィンドウにメッセージを書き込んでMySetupMacroを呼び出し、ファイルを書き込みモードで開きます。
execUserSetup(){/* Write a message to the debug log */
__message "Debugger started\n";
MySetupMacro();
/* Opens a text file for ASCII writing */
_fileHandle = __openFile("$PROJ_DIR$\\Memory.txt", "w");
}
このセットアップマクロ関数を使用すると、実際にアプリケーションをロードする前にハードウェアの一部を初期化することもできます。同種のセットアップマクロ関数として、ターゲットのリセット時に実行されるもの(execUserExit)、実行の開始時または停止時に実行されるもの(execUserStarted/Stopped)、あるいはデバッグ終了時に実行されるもの(execUserExit)などがあります。
C-SPYマクロは、マクロクイック起動ウィンドウから手動で呼び出したり、ブレークポイントに関連付けたりすることもできます。例えば、コードブレークポイントによってメモリの内容をファイルにダンプすることができます。
WriteMemory2File()
{
__var byte,address,_fileHandle;
_fileHandle = __openFile("$PROJ_DIR$\\Memory.txt", "w");
for (address=0x20000000;address< 0x2000FFFF;address++)
{
byte=__readMemoryByte(address,"Memory");
__writeFile( _fileHandle, byte );
}
__closeFile( _fileHandle );
}
このように定義したマクロを、以下のようにアクションとしてコードブレークポイントに関連付けられます。
ターゲットの実行をブレークポイントで停止させずに、メモリダンプ後直ちに実行を継続させたい場合は、アクション(Action)ではなく条件(Condition)としてC-SPYマクロを呼び出すことができます。
最後に、IAR Embedded Workbench IDE内からではなく、コマンドライン(CSPYBAT)からC-SPYデバッガを実行中に、このメモリダンプを行う場合を考えます。この場合は、以下のようにC-SPYに用意されているブレークポイントを設定するためのシステムマクロを利用すれば実現できます。
execUserSetup(){
...
/* __setCodeBreak(location, count, condition, cond_type, action) */
__setCodeBreak("{myfile.c}.82.1",0,"WriteMemory2File()","TRUE","");
...
}
まとめ
デバッグ対象のハードウェアが利用できる場合でも、プロジェクトをシミュレーションしている場合でも、C-SPYマクロを使用すれば、有効かつ柔軟にデバッグセッションをカスタマイズすることができます。使用場面としては、デバッグのためのハードウェアの準備、実機テスト前の複雑な条件の動作確認とログ収集、周辺機器や割込みのシミュレーションなどが考えられます。使用可能なすべてのマクロについては、IAR Embedded WorkbenchのC-SPYデバッグガイドに記載されています。