エミュレータからデバッグ情報を吐き出す

マイコンのデバッグ用に使っているツールがある。

プログラムの中に自動的にデバッグ用のコードを埋め込んで、そのコードによりデバッグ情報をシリアル通信で出力する。

このシリアル通信を受信して、プログラムの内部動作を解析するというもの。

デバッグ用のコードを埋め込む必要があるのは難点だが、他のツールではできない解析ができるのが長所だ。

なかなか使い所が難しいという話もあるが、僕はデバッグの効果を高められるツールだと思っている。


このツールをエミュレーターでのユニットテストと組み合わせて使うことができないかということを考えていた。

うちでもユニットテストできるの?

エミュレータを使ってのユニットテストでハードウェアに依存しない機能のテストをしようと考えている。

このときの内部動作を実機でのデバッグで使っているのと同じツールで解析しようと考えたわけだ。


というのも、このツールはデバッグ用のコードを埋め込む都合、全機能の内部動作を一気に解析するのは難しい。

過去には何度かに分けて解析を行ったこともあるが、同じような操作を何度か繰り返す必要があるなど不都合も多かった。

そこで、ハードウェアに依存しない部分の詳細はエミュレータで詳しく内部動作を調べて、

実機ではハードウェア依存の部分の内部動作と、結合しての動作の解析と役割分担するとよいと考えた。

同じツールを使うことで、エミュレータでの解析結果と実機での解析結果との結合ができるというメリットもある。


とはいえ、1つ問題があって、それはエミュレータではシリアル通信でデバッグ情報を出力することができないということ。

そこで代替策がないか調べたところ、このツールはデバッグ情報をファイル出力する方法も持っていると書いてある。

ファイルシステムを持っているシステムでデバッグ情報を自分のファイルシステムに保存するようなのを想定しているらしいが、

エミュレータならメモリダンプをファイルに保存することはできそうだし、なんとでもなるでしょう。

というわけで方法を調べてみた。


具体的な方法だが、データブレイクポイントを使うとできるようだ。

書き込み用バッファをプログラム内で用意しておいて、そのバッファの最終バイトへの書き込みにブレークポイントを仕掛ける。

一般的にブレイクポイントはコード上に仕掛けるものだが、データの読み書きに対して仕掛けることもできる。

特にマイコンのエミュレータでは、ペリフェラルを模擬するのにデータブレイクポイントが使われることがあると。

ブレークポイントでコードを停止するのではなく、ここでエミュレータのマクロを呼び出すように設定する。

このマクロに書き込みバッファのダンプをファイルに出力するというように書いておく。

するとプログラム中ではバッファに書き込むだけで、そのバッファの内容がファイルに出力される仕組みが作れる。

出力されたデータをツールに食わせれば、見事に内部動作の解析ができるというわけ。


このファイルにはタイムスタンプを埋め込むことができる。タイムスタンプを埋め込むことで実行時間の解析などができる。

シリアル通信でデバッグ情報を出力する方式では、受信側でタイムスタンプを付けることができるが、

ファイルに出力する方式ではタイムスタンプは出力する側で付ける必要がある。

必須ではないものの、できることならエミュレータでもそれらしいタイムスタンプを付けたいものである。


それでエミュレータのマニュアルを見ていたら、エミュレータ内のサイクル数をカウントするレジスタがあることがわかった。

ファイル出力時にこの値を持ってきて、実機のクロック周波数でわり算した値をタイムスタンプとして埋め込む。

すると、解析結果にそれらしい実行時間が表示されるようになった。

エミュレータはマイコンのサイクル数も模擬しているはずなので、それなりの見積もりにはなっているはず。

厳密に実機での実行時間と一致するということはないだろうが、感覚的にはそんなもんだよねという数字になっていた。


このツールを使って解析することで、ユニットテストの妥当性の確認が容易になる。

こういう内部動作を期待して、こういう入力を用意したけど、本当にその通りになっているか。

ブレークポイントを差し込んで内部変数の値を調べて妥当性を確認することもできるが、

ツールをうまく使えば、収集したデバッグ情報を一括解析して、妥当性が確認できる。

すでに実機で使っているのと同じツールなので納得感も高い。

そこまでしてエミュレータで使うかという話もあるが、完成したものを見てみるとなかなかよいと思う。