Qtブログ(日本語)

ARM Cortex-Mマイクロコントローラからコード・カバレッジを取得

作成者: Qt Group 日本オフィス|Apr 16, 2024 12:52:23 AM

このブログは「Retrieving Code Coverage from ARM Cortex-M Microcontrollers」を翻訳・一部加筆したものです。

はじめに

前回の記事では、ARM Cortex-Mマイクロコントローラのコード・カバレッジを測定する方法としてSquish Cocoをご紹介しました。今回の記事では、これらのマイクロコントローラーからコード・カバレッジ・データを取得する方法に焦点を当て、GDBの使用法を詳しく解説します。この記事を読む前に、前回の記事をご一読いただくことをお勧めします。

ご紹介するのは簡単な方法で、ホスト・コンピューターにRS232やその他の接続がない場合に便利です。

Atmel Studioのセットアップ

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関数は、「リモート・デバッガ接続でコード・カバレッジ・データを取得する」の記事とほぼ同じです。画面表示時のスペースを節約するため、少し密なフォーマットになっています。

GDBコンソールの使用

サンプルをコンパイルした後、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ファイルを選択します。