バックナンバーはこちら

today&tomorrow

Technology Update

2018 vol.110

バーチャル・プロトタイプを使用した組込みソフトウェアのデバッグ

バーチャル・プロトタイプを使用したソフトウェアのデバッグ

前述のように、バーチャル・プロトタイプではハードウェアの場合に使用するのと同じ組込みソフトウェア・ビルド/デバッグ・ツールを使用できるのがソフトウェア開発における利点の1つです。開発環境内のデバッグ・サーバを使用すると、サードパーティのデバッグ・ツールに「ストップ・モード」で即座に接続できます。これ以外にも、ハードウェア・ターゲットに接続できるデバッガなら「ラン・モード」のバーチャルI/Oを使用してバーチャル・プロトタイプに接続できます。たとえば、Android向けEclipse SDKはEthernetのバーチャルI/O機能を利用してAndroid-Debug-Bridge(adb)ソフトウェア・デーモンに接続できます。

「ストップ・モード」デバッグの場合、バーチャル・プロトタイプはシステム全体を同期制御でき、あるソフトウェア・デバッガによって実行が中断されると、組込みソフトウェアから見たシステム時間も停止します。デバッグのためにシステムが停止していることはソフトウェアからは認識できないため、このデバッグ・モードは完全な非介入デバッグです。前述のように、タイマーがタイムアウトすることもなく、開発者には過渡的でない一貫したシステム・ステートが提示されます。図2に示すように、バーチャル・プロトタイプのデバッグ・サーバを使用すると複数デバッガの同期動作も可能です。

画像

図2:ストップ・モードとラン・モードのマルチコア・デバッグ

もう1つのデバッグ・モードは「ラン・モード」デバッグと呼ばれ、主にアプリケーション/プロセス・レベルのデバッグに使用します。このモードでは、組込みOS上で動作するデバッグ・サーバ・アプリケーションがUART、USB、Ethernetなどの標準インターフェイスを介してホスト上のデバッガと通信します。デバッグ対象プロセスの実行を中断するとそのプロセスの実行のみが中断され、システムのそれ以外の部分は動作を継続します。この場合、バーチャル・プロトタイプと物理ハードウェアが同じ標準インターフェイスを使用するため、バーチャル・プロトタイプをIDE/SDK(Android向けEclipse SDK、Wind River Workbenchなど)と簡単に結合できます。

バーチャル・プロトタイプを使用したシステムのデバッグ

デバッガを使用すると、ソフトウェア開発者はシステムのステートが妥当かどうかを確認できます。システムが仕様どおりに動作していないことが分かったら、まず「何が正しく動作していないのか」を解明し、次に「なぜ正しく動作していないのか」を調べる必要があります。しかし「何が正しく動作していないのか」を解明するのは必ずしも容易ではありません。デバイス・ドライバのデバッグの場合、ドライバの実行がシステム全体のどこで止まっているか分からず、「何が正しく動作していないのか」や「どこで問題が発生したのか」を把握するのが難しく、システム全体の観点で理解する必要があります。デバッガを使用すると、カーネルがスケジューリングして実行する多数のスレッドを観測できます。しかし抽象度の低いインプリメンテーションのデバッグから離れて、システム・レベルのビヘイビアをよりグローバルな視点から捉えることができれば、ドライバのカーネル・スレッド実行がミューテックスで止まっており、割り込み(たとえば先の例ではセンサーの「acknowledge」割り込み)を待っていることを突き止めることができるかもしれません。

バーチャル・プロトタイプでは、ユーザー定義のモニタを使用することでよりスマートなトレースが可能です。モニタを使用するとシステムまたはソフトウェア・コンテキストを認識できるようになり、ソフトウェア開発者にとって理解しやすい、より抽象度の高いビューが得られます。たとえばAndroidなどより高次のソフトウェア・レイヤにおけるスレッドやアクティビティをトレースする場合、メモリーまたはCPUレジスタに格納された情報からOSステートを簡単に導き出すことができます。

画像

図4:システム・ソフトウェアの解析

Linuxブリングアップ:バーチャル・プロトタイプを使用したデバッグのケース・スタディ

Linuxは複雑なOSで、プロセッサ・ベンダ、IPベンダ、オープンソース・コミュニティ、Linaroをはじめとするコンソーシアムなど多くの当事者によって継続的に改良が加えられています。リアルタイム・オペレーティング・システム(RTOS)とは対照的に、Linuxはユーザー・プロセスとカーネル・プロセスを明確に区別しており、仮想アドレスを使用してカーネル・アドレス空間とユーザー・アドレス空間を厳密に分離しています。アプリケーションは、Linuxが提供する完全なドライバ・モデルを使用して下層のハードウェアにアクセスします。Linuxドライバの開発/ポーティングは簡単な作業ではなく、新しいカーネルがリリースされるたびにドライバの変更作業が発生します。

基本的なブリングアップ

まず、よくある簡単な例から見ていきましょう。既存のArm® SoCのリビジョン変更に伴い、Linuxベースのボード・サポート・パッケージ(BSP)のブリングアップが必要になったとします。開発者はまずkernel.orgからカーネル・ソースをダウンロードし、プラットフォーム・ヘッダ・ファイル内の割り込み、メモリー・マップ、ドライバを変更して、プラットフォーム仕様に応じてカーネルをコンフィギュレーションします。カーネル・イメージをビルドしたら、圧縮したカーネル(zImage)とブートローダをバーチャル・プロトタイプのROMに格納します。ブートアップ・プロセスが開始し、UARTに接続したシリアル・コンソール・ターミナルに「Uncompressing Linux...」のメッセージが表示されます(図5)。ここまではブートローダが正しく実行され、カーネル展開ルーチンが正常に起動したように見えます。

画像

図5:Linuxコンソール・ターミナル

デバッグ経験が豊富かどうかにかかわらず、デバッグ・プロセスでは何が正しく動作して、何が正しく動作していないのか、そして今何が起こっているのかを突き止めることから始める必要があります。現在のステートは、コアのプログラム・カウンタを評価すれば簡単に調べることができます。シノプシスのバーチャル・プロトタイプ・アナライザでは、ディスアセンブリ・ビューを簡単に呼び出すことができます(図6)。

画像

図6:ディスアセンブリ・ビュー

プログラム・カウンタの位置はアドレス0xffff000cを示しており、カーネルは「boot-mmu-off」フェーズにあります。ステップ・ボタンをクリックしてもプログラムのアドレスは変化せず、実行が前に進みません。Armコアの経験があれば分かりますが、これは未定義の命令に対するプロセッサの例外ハンドラで処理が止まっています。

バーチャル・プロトタイプでは、カーネル・デバッガなどの専用デバッグ・インフラストラクチャをセットアップしなくてもこのように非常に役立つ情報が得られます。バーチャル・プロトタイプを使用すると、プロセッサ・レジスタおよびプログラム・コードをすぐに可視化できます。

カテゴリートップ