今回は、何かとデバッグには重宝する手法としてprintfデバッグについて、Tipsや設定方法を紹介します。
printfデバッグは、その名の通りprintf()関数を使ったコードのデバッグとして使用され、変数が期待される値となっているのか、コードの実行や条件分岐などが正しく動作しているのか
確認するためコードの実行ログなどをコードの動的な状態として、標準出力(ディスプレイなど)に出力して可視化するのに役立ちます。
コンテンツ
printfデバッグの有効なケース
現在でもprintfデバッグを好んで使われる方は多いと思います。
近年は、デバッグ手法としては、デバッガーを使用しますよね。
ステップ実行を行いながら、問題だと思われる個所周辺をブレイクして、変数やコードの記述が正しか確認するのが一般的です。
ただ、一旦止めることが出来ないアプリケーション、例えばモーターなどや、一見誤りの無いコードのデバッグの場合にはデバッガーを使用してもバグ解析が困難な場合があります。
そんな時にそのアプリケーションを動的に可視化して、バグの可能性がある範囲を絞り込みたいといったケースにはprintfデバッグが有効なんです。
printfデバッグの注意点
printfデバッグを行う上で、いくつか注意しなければいけない点があります。
printf()関数の負荷
ただ単にprintf関数を置いてしまうと、printf関数の有無でコード処理の負荷が変わってしまいます。コード処理を実行する負荷が発生して、アプリケーションの期待する動作とならないケースがあります。
また、最終製品や開発段階によっては、ディスプレイが無いケースもあります。そもそも、printf出来ないじゃんといったケースです。
出力する画面がない
小型機器などには、ディスプレイがない物が多いですし、例えばテレビのリモコンなども画面は無く、ボタンしかありません。このような機器の開発では、画面にプログラムの動的な状態を出力することが困難です。
そんな場合には、セミホスティング出力が有効です。
セミホスティング出力とは
セミホスティングとは、ARM ターゲット上のアプリケーションコードから発行される入出力要求を、デバッガが実行されているホストコンピュータに伝達するメカニズムです。これを使用すると、例えば、printf()やscanf()などの C ライブラリ関数で、ターゲットシステム上の画面とキーボードではなく、ホストの画面とキーボードを使用することができます。
引用元:ARM社ARMソフトウェア開発ツールドキュメント
つまり、printf出力をUARTなどで接続したシリアルターミナル画面では無く、開発ツールのデバッガ画面に出力できる機構のことですね。
通常のprintfでは、マイコンを使用した製品などの開発では、printf()関数経由で基板上のUARTなどのシリアル出力にリダイレクトし、外部デバイスやディスプレイに出力します。
ただ、開発が初期段階でまだシリアル出力を備えていない場合や小型機器でディスプレイがそもそも無い場合には、シリアルインタフェースで出力できません。
そこで、セミホスティングという設定をすると、通常のprintf()関数を実行することでデバッガー画面(コンソール)に出力するようになります。
そんなprintfデバッグの設定はLPCマイコンを使用する時には、いくつか気を付けなければいけない設定があります。
MCUXpresso IDEでのセミホスティング設定
LPCマイコンを使用する場合は、LPCOpen のSDKがMCUXpresso IDEには既に組み込まれています。
通常、LPCOpenを使用してビルドすると、printf()出力は直接マイコンのUARTに出力するように設定されています。セミホスティングによってデバッガコンソール画面にprintf()出力する際には、2つの設定を行う必要があります。
- UARTへのリダイレクトをしない
- プロジェクトのコンパイラーをセミホスティング対応コンパイラに変更
1-1 UARTへリダイレクトしない
UARTへprintf出力されている設定を無効にします。無効にするには、下記2つのうち1つを行うことで可能です。
- ボードライブラリのboard.c内のインクルードファイル(retarget.h)をコメントアウトする
- ボードライブラリプロジェクトをDEBUG_SEMIHOSTINGをdefineする
board.c内のインクルードファイルをコメントアウトする場合
DEBUG_SEMIHOSTINGをdefineする場合
1-2 アプリケーションのプロジェクトのコンパイラー設定をセミホスティング
Quick Start Panel(左下パネル)にあるQuick Setting – Set Library/header type – Redline(semihost)を設定します。
上記設定後、アプリケーションプロジェクトをリビルドし、デバッグを開始します。
以上の設定で、printf()出力は、デバッガのコンソールに出力されます。
デバッグして確認
下図の例では、printf(“Hello World\r\n”);を実行しています。
まとめ
printfデバッグは、アプリケーションの動的解析には重宝するデバッグ手法です。また、小型機器など画面が無い機器の開発でも同様に、セミホスティングによってprintfデバッグが可能です。
printfデバッグは、実行時にprintf関数の実行負荷が掛かり、実際のアプリケーションの動作や振る舞いに影響を与えるため、意図しない動作となる可能性もありますので、十分理解して使用する必要があります。
実は、ARM Cortex-MのITMというデバッグ用回路を使用すると、printf()の実行負荷を掛けずにprintfデバッグを行うことも可能です。ITM printfデバッグについても、記事にしていきたいと思います。
最後までお読みいただきありがとうございます。
もし、良かった!と思われたら、シェアして頂ければ幸いです。