<JTAGデバッガの仕組み>

CPUのデバッガには大きく分けて3種類あります。それぞれメリット・デメリットがありますので簡単にまとめてみました。
種類 メリット デメリット コスト
フルICE 何でも出来る 値段が高い、今後のCPUの高速化に対応できない可能性あり 数十万円以上
JTAGデバッガ フルICEに近いことが出来る フルICEより安い 数万〜数十万円
モニタデバッガ 安価でお手軽 CPUのリソースが必要
ROMで実行するプログラムなど、デバッグ出来ないプログラムもある
安価
簡単に言えばJTAGデバッガはフルICEに近いことが出来て、価格もそれなりにお手ごろ(とは言っても高いですが)で、CPUのROMやRAMなどのリソースは必要ありません。
わりと最近出てきたデバッグ技術で、今後のCPUデバッグの中心技術になると思われます。

ARM7の場合はARM社から公開されている「ARM7TDMIテクニカルリファレンスマニュアル」の中にJTAGデバッグに関する技術的な情報が公開されています。ARM社のHPでユーザ登録すれば誰でも日本語版のマニュアルがダウンロードできます。

国内メーカのCPUを含めてですが、一般的にJTAGデバッグの技術的な仕様を公開しているケースそれほど多くありません。
今回MINI EZ-USBを使用したJTAGデバッガが開発できたのも、このARMのオープンな姿勢のおかげと言えます。

ARM7の場合JTAGを使用することで が可能になります。

最初の3項目はJTAGデバッグを行うために欠かすことが出来ません。最後のDCCはJTAG経由でのフラッシュ書き換えに使用しています。今回のデバッガには実装していませんが、デバッグ中のプログラムのメッセージをprintfでデバッガに出力するといった用途などに使えそうです。

ハードウエアブレーク・ウォッチポイントはROMで実行しているプログラムに対しても有効で、非常に強力です。ただし注意すべきは2個しか使えないということです。このことはEZ-ARM7をデバッグする上で常に念頭においておく必要があります。

JTAGデバッガは32bit ARMコードと16bit Thumbコードの両方に対応しています。
(jtag_stub.exeはThumbに対応していますが、Insight/GDBがThumbコードのデバッグで変な動きをするようです。
EZ-ARM7のフラッシュメモリは32bitアクセスですし、GCCの生成するThumbコードはそれほどコードサイズが小さくならないようですので、Thumbコードを使用するメリットはあまり無いと思います。)
コマンド例 処理内容
jtag_stub jtag_stubを起動する。
(jtag_stub起動後にInsight/GDBを起動することでデバッグが可能になります。)
Insight/GDBとのコネクションが終了するとjtag_stubは自動的に終了します。
jtag_stub c jtag_stubを起動する。
Insight/GDBとのコネクションが終了してもjtag_stubは終了せずに、再度Insight/GDBとの接続を待ちます。

<実際にデバッグをする>

GCCのインストールが正常に出来ていれば、lpc2214_blink(あるいはlpc2138_blink)のディレクトリで「make debug」を実行すれば、コンパイル&リンク、フラッシュ書き込み、JTAGデバッガ(jtag_stub.exe)起動、Insight/GDBの起動が行われます。

デバッグを行うプログラムをコンパイルするときには、必ずコンパイルオプションに「-g」を指定します。これによりGCCが生成するオブジェクトファイルにデバッグ情報が含まれるようになります。

make debugを実行


Insight/GDBが起動すると

このような画面が現れます。

左上の「人が走っている(RUN)アイコン」をクリックします。

初回はターゲットとの通信方法を設定する画面が現れます。


JTAGデバッガ(jtag_stub.exe)とはTCP/IP経由で接続しますので、上記のようにTarget:に「Remote/TCP」を選択し、
Hostname:は「localhost」と入力します。Port:は「2159」です。

右側のチェックボックスは「Set breakpoint at 'main'」だけにチェックを入れます。
これはC言語のmain関数の最初でブレークポイントで停止させることを意味します。
このチェックを入れないとプログラムは勝手に先に進んでしまいます。

「OK」をクリックすると、JTAGデバッガ(jtag_stub.exe)とInsight/GDBが接続され、


main関数の最初のところでブレークポイントで停止します。
JTAGデバッガではブレークポイントを2個しか使えないので、まめに不要なブレークポイントは削除しておきます。
ブレークポイントが足りないと、デバッガに思うような動作を行わせることが出来なくなります。
(ブレークポイントが不足すると、コマンドプロンプト(DOS窓)にメッセージが表示されます)

ブレークポイントを削除するには、緑色のカーソルの左側にある赤いポッチをクリックします。

画面右上の「SOURCE」のプルダウンを変更すると、、ソースウインドウの表示をアセンブル付きの表示に変えることが出来ます。例えば「MIXED」にするとこのような表示になります。

さすがGUIデバッガといったところですね。

デバッグが終了したら、Insight/GDBのソースウインドを閉じます。ソースウインドウを閉じると、メモリダンプやレジスタウインドウなどの子ウインドウも自動的に閉じます。
JTAGデバッガ(jtag_stub.exe)はInsight/GDBとのコネクションが失われると自動的に終了します。
(キーボードの「Ctrl + C」キーを押すことで強制的に終了させることも出来ます。)
(jtag_stub.exe起動時に「C」オプションを指定すると、自動終了しなくなります。)

この状態でプログラムソースを修正して、再度「make debug」でコンパイルからデバッグ開始までを行うことが出来ます。

<Insight/GDBの操作方法>

Insight/GDBは特に癖も無いので、少し触れば大体の操作方法はマスター出来ると思います。
と言ってしまうと身も蓋もないので、GUIのアイコンを中心に簡単に解説します。



No コマンド名 何をするか
実行(Run) ターゲットプログラムを最初からリスタート実行させる
1 停止(Stop) ターゲットプログラムが実行中(Running)はRunアイコンからStopアイコンに表示が変わる。このときクリックするとターゲットプログラムを停止させる。
ステップ(Step) Cソース行のステップ動作 関数呼び出しの場合は関数の中に入って止まる
次(Next) Cソース行のステップ動作 関数呼び出しの場合は関数の関数の中には入らずに(関数は実行される)、関数呼び出しの次の行で止まる
完了(Finish) 関数の中にいるときは、関数を呼び出した次の行で止まる(つまり関数を抜け出す)
18 続行(Cont) シングルステップ動作を行わないで、ターゲットプログラムを続行する。
プログラム続行中は停止(Stop)アイコン以外は無効になる。
ステップAsm(Step Asm Inst) アセンブラ行のステップ動作 関数呼び出しの場合は関数の中に入る
次Asm(Next Asm Inst) アセンブラ行のステップ動作 関数呼び出しの場合は関数の呼び出しの次の行で止まる
レジスタ(Register) レジスターウインドウを表示する (W1)
メモリー(Memory) メモリーダンプウインドウを表示する (W2)
スタック(Stack) コーリングスタック(関数の呼び出し状況)ウインドウを表示する (W3)
10 値評価(Watch Expressions) 変数を含む式などの値を表示する (W4)
11 ローカル変数
(Local Variables)
ローカル(局所変数)を表示する 関数に入るとその関数内のローカル変数を自動的に表示する (W5)
12 ブレークポイント
(Breakpoints)
現在設定されているブレークポイント一覧ウインドウを表示する (W6)
13 GDBコンソール(Console) GDBコンソールを表示する ハードウエアウォッチポイントなどはGUIでは設定できないためコンソールからGDBコマンドを入力する (W7)
14 ファイル・関数表示 ソースファイル・関数を選択すると対象の場所がソースウインドウに表示される
15 文字列検索(Search) ソースウインドウから対象の文字列を検索する
16 スタック選択 ソースウインドウに、コーリングスタック中の関数の呼び出し位置を表示する
17 C/Asm切り替え表示 ソースウインドウ内の表示形式C/Asmを切り替える

(W1) レジスターウインドウ


(W2) メモリーウインドウ


(W3) スタック(関数呼び出し)ウインドウ

main()の中でdelay()が呼び出されている状態

(W4) 値評価(Watch Expressions)

d*10 のような変数を含む式の値を表示する

(W5) ローカル変数(Local Variables)


(W6) ブレークポイントリスト(Breakpoints)


(W7) GDBコンソール(Console)

<Insight/GDBの使いこなしTips>

ちょっと便利なInsight/GDBの使いこなしを紹介します。
<ハードウエアウォッチポイントを使う>
JTAGデバッガはハードウエアウォッチポイントが使用できます。
ハードウエアウォッチポイントは変数などが更新あるいは参照されたときにブレークポイントをかける機能です。

ある程度の規模のプログラムを作成していると、変数などが意図せず(勝手に)書き換わってしまうようなバグに遭遇します。多くの場合はポインタや配列などの不正使用が原因なのですが、どこに原因があるのか突き止めるのが大変です。このような場合には対象となる変数にウォッチポイントを仕掛けておくことで簡単に原因を突き止められます。

Insightでは残念ながらウォッチポイントをGUIから設定することが出来ません。そこで登場するのがGDBコンソールです。
GDBコンソールを開いて「watch 変数名」と入力します。watch命令は変数が更新(値が書き換わる)とブレークがかかります。
同じような使い方で「awatch 変数名」とすると、更新だけではなく参照時にもブレークを掛けることが出来ます。



この例では「watch test[0]」でtest[0]に対してウォッチポイントを設定します。
その後「continue」コマンドでプログラムを再開させます。
すると、blink.cの18行目でtest[0]が125から126に更新されてブレークがかかります。

ソースウインドウ上はこのような感じで、「test[0]++;」の次の行で止まっているのが確認できます。


ウォッチポイントを削除するには「del 番号」コマンドでウォッチポイントの番号を指定します。
ウォッチ/ブレークポイントの番号は「info br」コマンドで確認することが出来ます。