JTAGデバッガの動作を確認するための何か良いサンプルプログラムはないかと思っていたところ、Interface7月号で山際さんのmonitorが紹介されていたので、早速試してみることにしました。
まず、山際さんのsh-toolsをインストールしてMakeすると、私の環境ではなぜか
Fatal: Unable to execute command: /usr/local/sh-tools/bin/sh-elf-ld
とエラーが出てしまいます。
Makefileの中でGCCとLDとASとOBJCOPYの実行ファイルを指定しているところがあるので、/usr/local/sh-tools/bin/を削除し、
--------------------------------------------
GCC = sh-elf-gcc
LD = sh-elf-ld
AS = sh-elf-as
OBJCOPY = sh-elf-objcopy
--------------------------------------------
とすると、うまくMakeが通るようになりました。
SH2のJTAGデバッガを使うには、ROMの0x20番地に0xC91F0606というマジックナンバーを書き込んでおかなければなりません。そこで、startup.sに次のように2行追加します。
--------------------------------------------
.long _startup
.long 0xFFFFFFFC
.org 0x20 ・・・ ★追加
.long 0xC91F0606 ・・・ ★追加
.org 0x200
#ERI_0
.long 0x00000000
--------------------------------------------
これで再度Makeしたところ、エラーこそ出ないものの、正しくファイルが生成されない。
コンパイル過程をよくみると、
sh-elf-as startup.o -o startup.o
となっています。どうやら、私の環境ではMakefileを実行するためのMake.exeが、Cygwinのものではなく、Borlandのものが使用されていることが判明。BorlandのMake.exeでは、Makefile中の
--------------------------------------------
startup.o: startup.s
$(AS) $< -o startup.o
--------------------------------------------
という記述で、$<が依存ファイルではなく目的のstartup.oに解釈されているようでした。
とりあえず、
$(AS) $*.s -o startup.o
に書きなおしてコンパイル成功。正しく目的のMotファイルが得られました。
FDTを使ってmonitor.motを書き込みます。19200bpsで1分くらいかかります。
7月号のモニターはちゃんと起動しました。
試しに、ダンプしてみると、あれ、ちょっと表示が変かも。
ダンプの表示は、横が16バイトなのに縦が8バイトづつ増えていくので、同じ内容が2度表示されています。まぁ、気にしない。
ところが、いろいろと使ってみると気になる点がありました。
コマンド入力で「dl 11」(つまり、11番地からダンプ開始)としたり、「rwl 11」(つまり、11番地の内容をワードで読む)をすると、このmonitorは固まってしまいます。
SHは、ワード境界、ロングワード境界を守らずにメモリアクセスすると、例外を発生させてしまいます。これはアドレスエラー例外といいます。きっと、この例外が発生しているのでしょう。
ためしに、JTAGデバッガを起動し、monitorを走らせます。アドレスの0番地に、JTAGデバッガから、ハードウェアブレークポイントを仕掛けておきます。
ここで、「rw 11」と入力します。すると、monitorの反応はなくなり、JTAGデバッガがPC=アドレス0番地を指して、コアが停止したことを告げてきました。
SH2の7144はアドレスエラー例外が発生すると例外の9番を発生させます。
JTAGデバッガで見るとVBRの値が0なので、CPUはアドレス0x24番地に記載されたアドレスにジャンプしようとします。
Interface7月号のmonitorではアドレス0x24には0が記載されているので、0番地にジャンプしようとします。
しかし、0番地はジャンプテーブルですから、0番地にジャンプしてもコードはありません。
とりあえず、0x24番地には何かのアドレスを書かなければならないので、startup.sの記述を
--------------------------------------------
#==================================
# SH-2 Exception Vector
#==================================
.long _startup
.long 0xFFFFFFFC
.org 0x20
.org 0x20
.long 0xC91F0606
.long _startup
--------------------------------------------
として、アドレスエラー例外が発生した際にリセットがかかるようにしてみました。
すると、「rl 11」とやった際にリセットがかかるようになりました。
しかし、5回ほどでリセットもかからなくなってしまいます。
例外の際にリセット番地へジャンプさせても、スタックポインタは初期化されないので、どんどんスタックを食い尽くしていくためです。
ということで、いろいろ実験してみましたが、JTAGデバッガを使って
・比較的大規模なプログラムをJTAGでとめたり動かしたりしても、それによって特に問題は発生しなかった。
・アドレスエラー例外をキャッチすることができた。
・スタックポインタの減少が確認できた。
などが確認できました。
なお、私のSH2用JTAG ICEでは、奇数番地などから4バイトを読もうとした場合、たとえば0x1111から4バイトを読もうとした場合では、0x1111はバイトで、0x1112はワードで、0x1114はバイトで、というふうに3回に分けて読み出すことでアドレスエラーを避けています。
そういった点は、GDBでも配慮されているわけではないようです。
例えばGDBで
(gdb)x/2w 1 (アドレスの1番地からワードデータを2つ読むの意)、
などとコマンドを打つとGDBはスタブに向かって
m1,4
m5,4
というコマンドを送ってきます。つまり、「奇数番地から4バイトリードを2回」と言ってきます。
つまり、アドレスエラーの回避は最も低い層で行わなければいけないようです。
ところで、SH2用JTAGデバッガをさらに使いやすくするためには、やはりJTAGデバッガから、Cのソースコードデバッグができるようにすることも必要かなと思っています。Insightを起動するのは、何かと大変です。
最近のコメント