組み込み向けデバッグ技術の基本(1/3 ページ)
組み込みシステムのデバッグ作業は、プロジェクト全体における負荷の半分以上を占めることもある。ハードウエアのデバッグ機能や、それらが対象とする問題を理解することが、適切なチップを選択し、より良いデバッグシステムを構築して生産性を向上する上で重要な鍵となる。
高度化するシステム、進化するデバッグ技術
「バグ(bug)」という言葉の語源には諸説ある。一般的には、コンピュータのリレーに挟まっていたガ(蛾)を取り除いたことで、シャットダウンしていたマシンの問題が解決されたという出来事が最初の「デバッグ(debug)」だといわれている*1)。この例では、文字通りバグ (虫)をハードウエアから取り除いたのだが、今日ではデバッグとはプログラムの欠陥を理解し、誤りのあるコードを取り除く作業のことを指すようになった。
ここでいう欠陥とは、「本来の目的から少し逸脱した部分」といった意味である。この欠陥を解消するには、修正したコードを加えるより、誤りのあるコードを取り除くほうが望ましい。そしてスムーズにデバッグを行うためには、すべてのバスやレジスタの値にいつでもアクセスできることが理想である。しかし、LSIがSoC(system on chip)へと発展したことにより、そうしたアクセスは以前よりも困難になってきた。
ハードウエアのデバッグのためには、システムの内部リソースに対する可能な限りのアクセス手段を提供することが重要である。提供すべきアクセス手段としては、CPUの状態やパソコンの設定値といったシステムの属性を観測/変更可能にする仕組みが挙げられる。組み込みシステムのデバッグ手法は、大まかにいえば、設計の初期段階にロギングやモニターなどの簡単な手段を用いて行う方法と、トレース用、キャッシュ用のデバッグ回路、クロストリガーなど、マルチコアSoC用に新しく開発された方法の2つに分けられる。
本稿では、コードをどのようにデバッグするのかということではなく、デバッグにはどのような手法があり、どのような組み込みハードウエアIP(intellectual property)が利用可能で、そのIPはデバッグのどの側面を対象としているのかということに焦点を当てる。
ロギングとデバッグモニター
最も古く、そして最もよく用いられるデバッグ手法はprint文を使う方法である。プログラムコードにprint文を挿入することで、どの部分が実行されたのか、レジスタや変数の実際の値はいくつなのかといった情報を表示させるのだ。
この手法は、プログラミングの入門段階で必ず習う“Hello Worldプログラム”の名残かもしれない。Hello Worldプログラムとは、print文(通常はprintf文)を使って「Hello World」という文字列を画面に表示させるプログラムのことだ。この文字列が画面に表示されれば、プログラムに問題がなく、かつprint文の位置まで正しく実行されたことが分かる。
printf文は、ログをとる処理(ロギング)の一例である。ロギングとは、外部で処理をトレースするために、プロセッサを使用して重要な情報をパイプに書き出す処理のことだ。パイプに相当するものはシステムによって異なるが、printf文を用いた場合、パイプは通常は標準出力(画面)となる。ただし、UART、USB、さらには汎用I/Oなどが出力先であってもかまわない。センサーからの情報や状態マシンの遷移など、システムの構成要素に関する情報がプログラマにとって理解できる形式で必要となる場合、ログは非常に貴重なものとなる。
ログを解析し、後処理用のデータベースを生成する際にはロギングツールを使用すると便利だ。その場合、デバッグ作業の効率化を図るために、ロギング関数を慎重に選択しなければならない。例えば、ログメッセージの頭には「警告」、「エラー」、「デバッグ」などのキーワードを付加し、メッセージの発生元とその重要度を明確にする必要がある。メンテナンスが容易になるよう、ロギング出力をいくつかのファイルにグループ分けし、可能ならばタイムスタンプ情報を付加するとよい。
ただし、ロギングには1つ注意点がある。ロギングを行うと、ソフトウエアの動作に変更が加わり、本来の動作とは異なるものとなってしまうのだ。
もう1つよく用いられるデバッグツールにデバッグモニター(リモートデバッガ)がある。デバッグモニターは、ターゲットとなる機器/回路のCPUメモリーに格納されたコードに対して使用する*2)、*3)。その際にはホスト上でデバッガを利用し、専用ポートを介してコマンドを送信したり、結果を受信したりしてデバッグモニターと通信を行う。
Linux OSのgdbserverプログラムは、初期のROMモニターよりも複雑だが、デバッグモニターの典型的な例だといえる(図1)。デバッガをホストマシン上で実行し、シリアルまたはイーサーネットによってgdbserverを含むターゲットと接続する*4)。
ある命令に対してブレークポイントを設定する場合、gdbserverはその命令を退避させてシステムコールに置き換える。その上で、Linuxのptraceプログラムを用いて、システムコールを実行するすべてのアプリケーションの情報を取得する。ブレークポイントにおいてシステムコールが発生した際、gdbserverはデバッグ中のアプリケーションを制御することが可能である。
デバッグモニターは安価で実用的である。しかし、デバッグ作業やアプリケーションソフトウエアとのやりとりを行う前にコードをロードしなければならないといったいくつかの欠点もある。なお、コードがフラッシュメモリー上に存在する場合には、ブレークポイントを挿入するためにアプリケーションにパッチを当てなければならない。そのため、デバッグモニターを利用することはできない。
便利だが高価なICE
ICE(in circuit emulator)は、かなり以前から存在したハードウエアベースのデバッグツールである。これはデバッグの対象とするプロセッサの“変形版”ともいえ、通常はFPGAを利用して構成する。そのFPGAはユーザーが内部バスと状態信号を参照できるようにする役割を担う(図2)。
ICEはROMモニターよりも多くのデバッグ機能を提供する。ICEを利用する際には、デバッグの対象となるプロセッサを基板から取り外し、代わりにICEボックスを接続する。このICEボックスは、デバッガの機能を実行し、プロセッサのエミュレーションを行うホストによって制御される。
ICEの最大の問題点は、それが高価であることだ。また、ICEを利用する手法は単純なプロセッサには適しているが、最新のSoCには向いていない。LSIベンダーにとって、集積度と周波数が高く複雑なSoCに対応したICEを提供するのは難しいことなのだ。
脚注
※1…"Rear Admiral Grace Murray Hopper, USNR".
※2…O'Keeffe, Hugh, "Embedded Debugging: A White Paper," Ashling Microsystems Ltd.
※3…Engblom, Jakob, "Debugging real-time multiprocessor systems: Parts 1 and 2," Virtutech, March 23, 2006, www.embedded.com/.
※4…Best, Steve, "Mastering Linux debugging techniques," IBM, www.ibm.com.
Copyright © ITmedia, Inc. All Rights Reserved.