このブログは「Retrieving Code Coverage from ARM Cortex-M Microcontrollers」を翻訳・一部加筆したものです。
前回の記事では、ARM Cortex-Mマイクロコントローラのコード・カバレッジを測定する方法としてSquish Cocoをご紹介しました。今回の記事では、これらのマイクロコントローラーからコード・カバレッジ・データを取得する方法に焦点を当て、GDBの使用法を詳しく解説します。この記事を読む前に、前回の記事をご一読いただくことをお勧めします。
ご紹介するのは簡単な方法で、ホスト・コンピューターにRS232やその他の接続がない場合に便利です。
GDBを使用するために、まずAtmel Studioが正しく設定されているかを確認しましょう。メニューの Tools > Options をクリックし、Debugger options で GDB Settings を選択します。ARM アーキテクチャが選択され、GDB 実行ファイルへのパスが有効であることを確認してください。
コード・カバレッジ・データのデモンストレーションには、サンプル・アプリケーション GccApplication1.zip を使用します。これは、前述のブログ記事で提供されたものと同じアプリケーションです。このアプリケーションは単純で、指定された整数引数の絶対値を返す関数 abs(x) をテストします。また、意図的に入力引数の負の値を1つだけテストすることで、テストでカバーされなかったコードを見ることができます。
#include "sam.h"
static int abs(int x) { // simple function which we want to test
if (x <= 0) {
return x;
}
return -x;
}
static int testAbs() { // simple test case
return abs(-1) == 1 ? 1 : 0;
}
#ifdef __COVERAGESCANNER__ // Coco IO functions
// Code coverage of the rest of the code is not that important for this example
#pragma CoverageScanner(cov-off)
char coverage[256]; // execution report
static int csfputs(const char *s, void *stream) {
char **buffer_p = (char**)(stream);
do {
**buffer_p = *s;
(*buffer_p)++;
s++;
} while (*s);
return 1;
}
static void *csfopenappend(const char *path) {
int i;
static char * pp = 0 ;
for (i = 0 ; i < sizeof( coverage )/sizeof( coverage[0] ); i++)
coverage[i] = '\n';
pp = coverage ;
return (void*)( & pp );
}
static int csfclose(void *fp) {
return 1;
}
static void saveCov() {
__coveragescanner_set_custom_io(0, csfputs, csfopenappend,
0, 0, csfclose, 0);
__coveragescanner_save();
}
#endif
int main(void) {
SystemInit(); // initialize the SAM system
testAbs(); // execute test case
#ifdef __COVERAGESCANNER__
saveCov();
#endif
while (1) {} // no exit - this is an MCU
}
ここで使用するCocoのカスタムIO関数は、「リモート・デバッガ接続でコード・カバレッジ・データを取得する」の記事とほぼ同じです。画面表示時のスペースを節約するため、少し密なフォーマットになっています。
サンプルをコンパイルした後、62行目(whileループのある行)にブレークポイントを設定し、アプリケーションをデプロイしてデバッグを開始します。デバッガがブレークポイントで停止したら、Atmel StudioでGDBコンソールを開きます(menu View > Other Windows > GDB Console)。
まず、変数coverageの内容をコンソール・ウィンドウに表示してみよう:
p coverage
この後、GDBの作業ディレクトリを、Squish Cocoが.csmesファイル(ここではGccApplication1.elf.csmes)を生成したプロジェクトのディレクトリに変更します。次のコマンドを実行してください:
cd "C:¥Users¥autotest¥Documents¥Atmel Studio¥7.0¥GccApplication1¥Debug"
これにより、カバレッジ変数のファイルへのダンプがより便利になります。デフォルトでは(現在のバージョンのAtmel Studioでは)、GDBの作業ディレクトリは %LOCALAPPDATA%\VirtualStore\Program Files (x86)\Atmel\Studio\7.0\atbackend にあります。また、CocoのCoverageBrowserは、ダンプファイルがそこに置かれている場合、インポートのために自動的にダンプファイルを提供しません。
それでは、変数coverageの値をファイルにダンプしてみましょう。そのためには、GDBコンソールで以下のコマンドを実行します:
dump value GccApplication1.elf.csexe coverage
これは、C:¥Users¥autotest¥Documents¥Atmel Studio¥7.0¥GccApplication1¥Debugに作成されるファイルGccApplication1.elf.csexeに変数coverageの値を "ダンプ "します。
カバレッジデータファイル(GccApplication1.elf.csexe)を入手したら、それをCoverageBrowserにインポートすることができます。
このためには、CoverageBrowserからGccApplication1.elf.csmesファイル(注意:.csexeとは異なる拡張子です)を開きます。.csmesファイルは、プロジェクトビルドのDebugフォルダにあります。例えば、C:¥Users¥autotest¥Documents¥Atmel Studio¥7.0¥GccApplication1¥Debug のような場所にあります。その後、CoverageBrowserのメニューから File > Load Execution Report を選択し、GccApplication1.elf.csmesファイルを選択します。