H8/gdbstub
H8/tiny用のGDBスタブを改造する。†
改造要点
- 普通のシリアル接続のモニター機能を追加したい。
- これはGDBを使わないときにもモニタとして使ったり、Sレコードを転送して実行したいから。
- 操作方法は '$' '$' と入力することでモニター側にエスケープする。
- s(tub) コマンドでGDBスタブに戻る。
- ライブラリ関数をRAM側から簡単に呼び出せるようにしたい。
- システム定義のユーザーベクターは0〜25までなのでその後ろ(26〜127)に関数テーブルを書いておくと、jsr @@(vect:8)でライブラリ呼び出しできる。
- 割り込みハンドラーも入れたい。
- f780〜の仮想ベクターにリセット時の初期ベクトルをコピー。
とりあえず、それらしい改造を行ってみる。†
- ソースは省略。
- おお!動いたぁ!
- GCC Developer Liteに含まれているGDB6.1(Insight Debugger)にて、接続成功!
- ソースコードデバッグが可能になった。
感動した。
では、現状の問題点とその対策を立てようではないか。†
遅い。
- 19200bpsでしか接続できないからだ。
- 38400にしたいが、中継ぎをしているAVR-USB仕立てのシリアル変換が文字落ちするのだ・・・。うむむ。
- いっそPIC18F2550とかで高速な中継ぎをさせる?
モニタが起動しない。
- なんかフックする場所を間違えたか、
- それともgdbstubの動作を見切っていなかったか・・・。
- さらなる修練が必要だ。
まあ、GDBがあればモニタいらない説もあるけれど・・・
- ホストPCが非力なやつだったりとか
- GDBでデバッグするんじゃなくて、デバッグ済みのコードを走らせたいだけなら、モニタに切り替えてSレコードをロードするほうが気楽。
- GDBスタブのプロトコルを使ってホストPC側にモニタを作成するという手もあるが・・・これも面倒いし。(だったらGDBでいいじゃん)
モニタも起動するようになった。†
- 残るは、Sレコードのローダーだけとなった。
- Sローダーも実装した。
- 適当なサンプルを組んで、ロードさせる。
- ロードはOK。
- 実行もとりあえずOKっぽい。
- ただし、割り込みを許可するとGDB側に制御が移ってしまい、それっきりだ。
- なぜだろう?
原因がわかった。
- gdbstubは、割り込みハンドリングを行っている。
- 具体的には、
TRAP#0 TRAP#1 TRAP#2 TRAP#3 SLEEP (ブレークポイント用. SLEEP命令で行っている) INT_SCI3 (シリアル)
- の例外が発生すると、レジスタコンテクストをセーブして、gdbstubの handle_exception()を 呼び出すようになっている。
- ここで問題なのはシリアル割り込み。
- シリアル受信はポーリングで行っているくせに、どういうわけか、受信割り込みだけイネーブルにしている。
- ユーザーアプリが無限ループに陥っても、GDBからブレーク信号(RS232C)を送ることでプログラム停止できるようにするためらしい。
- GDBの管理下から離れて、Sレコードをメモリーにロードして実行しようとすると、割り込みが許可された瞬間にGDBに制御が移ってしまうようだ。・・・ううむ。
- 結局、SCI3のSCRの値を変更してRIE(受信割り込み)をOFFにすると、Sレコードを実行できるようになった。
- ついでに述べると、以下の例外は、仮想ベクターに書かれた飛び先を呼び出すようなコードが入っていた。
IRQ0 IRQ1 IRQ2 IRQ3 ABRK WKP TA TW TV IIC2 ADI Reserved
- 仮想ベクターは 0xf780〜に置かれていて、 0x0000 にあるものと同一の配置である。
DOWNLOAD†
トラ技2004.4基板用:†
モニタとGDBスタブの統合がほぼ出来上がったので、ソースを公開します。
- upload/gdbstub.zip
- コードサイズはROM:12kB、RAM:768バイト(0xFD80〜0xFF80)
GDBスタブを含まないモニタ単体のソースとMOTファイルです。
- upload/tinymon.zip
- コードサイズはROM:4kB強、RAM:128バイト(0xF780〜0xF7FF)
秋月H8/3048F基板用:†
GDBスタブを含まないモニタ単体のソースとMOTファイルです。
- upload/tinymon3048F.zip
- コードサイズはROM:6kB強、RAM:160バイト(0xFFEF10〜0xFFEFAE)