デバッグ手法

あなたの書いたソフトウェアは思った通りに動いていますか?何かがおかしいけど何がおかしいのかわからない。デバッグするにはどうしましょう。純粋なソフトウェア開発ではテストコードを書いたりデバッガーを使うという方法があります。もちろんそういった手法も有効ですが、組み込みシステムならではのデバッグ方法もあります。

Printデバッグ

printfでデバッグするのと同じ考え方ですが、一般的にはUARTを使っていろいろな状況を出力して動作状況を把握する方法です。動作状況を記録することをログをとるとも言いますね。UARTの通信速度は、小規模システムだと9600bps, 中規模システムだと115200bps程度です。8bit文字を10bitに符号化するので960文字/秒とか11520文字/秒程度の速さ(遅さ)になります。あまりにも大量のログを出すことはできませんので、#defineやパラメーターなどでログの出力レベルや出力範囲などを変更できるようにしておいた方が良いです。ログを出したせいで動作タイミングが変わってしまってバグが再現しなくなった(逆にするようになった)ということも起こり得ます。

通信系のソフトウェアなど、自分だけでは動作が完結していない場合、デバッガーで停止させるとその時点でデバッグしたい状況とは状態が変わってしまいますので、Printデバッグは非常に有効になります。

UARTの出力先は、以前はレベル変換ICを経由した9pin D-SUBコネクタのRS-232Cが多かったですが、最近はUART-USB変換ICを経由したUSB接続も増えています。とはいっても、量産基板に使うかどうかもわからない変換ICをのせるのはお金がもったいないので、実装用のランドだけを用意しておいて必要なときだけ使ったり、変換ICは外部で準備したり、ということになります。

いつでもPCを接続しておくわけにもいかないので、内部メモリにログをためておいて、PCをつないだときにログを取り出せるようにする、という仕組みを作りこむのも有効です。この場合は時間情報も一緒に保存しておかないと、あとで振り返ってもなんのことかわからなくなります。

GPIOデバッグ

普通のソフトウェアではやらない方法ですが、GPIOをデバッグに使うという方法があります。組み込みシステムでは必ずIOポートがついていると思います。ポイントは、観察しやすい出力変化を作り出すことです。UART出力ではタイミングが変わってバグの発生状況が変わってしまう場合にも有効です。

ある動作が起こっている間にHIGH出力する

わかりやすいですね。LEDを取り付けるとその間に光るので、視覚的にもデバッグできるようになります。オシロスコープを接続して、処理時間を測定することもできます。観察したいことの数だけIOピンが必要になります。あまりに動作時間が短いとオシロスコープのサンプリングレートではとらえられない場合があります。

ある動作が起こったときに反転する

処理時間があまりに短いものだったり、たくさんのことを1つのIOピンで観察しないといけなかったり、そういう場合には出力を反転すると良いです。観察区間に入る前の初期化としてLOW出力にしておくなど、スタート地点の出力を把握できていれば、あとはその出来事が発生した順番で反転していくので、1つのIOピンでも複数の出来事のタイミングをまとめて観察することができます。

反転するのに知っておくべき演算子は ^ ですね。こんな風にすると最下位ビットを反転できます。

output ^= 1;

まとめ

とにかく、バグが起こっている状況を観察することが必要です。テストコードも、どういう入力の場合にバグが起こるのか起こらないのか、観察しているということですね。オシロスコープで観察する、UART出力で観察する、とにかく観察できるようにして、正しく問題を理解して、それから解決に取り組みましょう。

コメント