2022/8/15
製品
カテゴリー
タグ
12036 Views
[汎用ポート接続]カバレッジ専用ドライバ
Contents
課題
カバレッジ測定をするために、テストポイントを複数個所に自動挿入したが、オーバーヘッドの影響でターゲットが動作しなかった。テストポイントの挿入箇所を調整して、カバレッジ計測をしている。
解決方法
テストポイント通過で出力されるトレース情報をbit単位で管理し、データを圧縮します。ターゲットが保持したテストポイント通過情報を通常のDumpデータ形式で出力します。レポート収集停止後、取得したDumpレポートのデータ部分を連続したデータとして認識し、変換をしてレポートデータを生成します。
効果
一度通過したテストポイントのデータは出力しないため、出力にかかるオーバーヘッドを減らせます。また、ログを保存するPC側のハードディスクの容量も減らせます。大規模な環境でのカバレッジ計測において、ログデータの容量を抑えた運用ができます。
制限事項
-
DTヘッダを生成するC/C++で使用できます。
-
ロジックデータの取得はできません。
-
カバレッジを目的としたドライバのため、パフォーマンス測定や実行経路の確認などにはご使用できません。
-
C1カバレッジはC1カバレッジ(クイック)の場合は算出可能です。
- C1カバレッジ(クイック)は環境設定の「ソースコードの分岐解析及びルート推定をしない」にチェックをつけて解析します。
- C1カバレッジ(クイック)の算出方法はDT+Traceアプリのヘルプをご参照ください。
プロジェクト新規作成、プロジェクト設定
プロジェクト新規作成、またはプロジェクト設定で[カバレッジ専用ドライバを利用する]を"True"に変更します。カバレッジ専用ドライバは、ターゲットにメモリバッファを確保するため、利用する前にバッファサイズを決定する必要があります。DTヘッダ更新時にDTTestPointCoutDefine.hヘッダを生成します。ヘッダの作成場所は、「カバレッジ専用ドライバを利用する」がTureのときのみ表示される、「テストポイント数定義ヘッダの保存フォルダ」欄で指定します。保存場所のデフォルトは、プロジェクトファイルと同じフォルダになります。保存フォルダはカスタマイズしたドライバと同じ場所を指定してください。
プロジェクト新規作成
プロジェクト設定
テストポイント再定義
テストポイントの自動挿入など、ヘッダ構成に影響がある項目が変更される場合にテストポイントの再定義が行われます。
テストポイントの再定義の際に以下のメッセージが表示された場合は、以下のFAQをご参照ください。
テストポイントの再定義が終わったら以下のように変わり、_TP_BusOutが_TP_BusOutBufに変更となり、引数が1つになります。
ドライバのカスタマイズ
サンプルドライバのダウンロード
対応OS | 接続方式 | 言語 | イベントID出力方式 | ダウンロード |
---|---|---|---|---|
NonOS | GPIO4bit | C/C++ | ダウンロード | |
NonOS | GPIO2bit | C/C++ | ダウンロード | |
NonOS | SPI | C/C++ | ダウンロード | |
NonOS | I2C | C/C++ | ダウンロード |
サンプルドライバのカスタマイズ
カバレッジ専用ドライバを環境に合わせてカスタマイズします。
include文の変更
インクルードされているDTTestPointCountDefine.hを変更します。
/*==============================================================================*/
/* Desc: Header for Port Control */
/*==============================================================================*/
#include "DTTestPointCountDefine.h"
#include "Common.h"
// #include <itron.h>
// #include <kernel.h>
再定義後、生成されるDTTestPointCountDefine.hの場所に合わせて指定してください。またポートの操作に日うような処理などが定義されているヘッダファイルをインクルードしてください。
サンプルにある"Common.h"は例です。削除して適切なファイルをインクルードしてください。
関数のインライン設定
ドライバ内の各関数は高速化のためにインライン化されています。環境によっては"inline"を使用することでビルドエラーとなりますので、そのような環境では"static"を使用します。
/*==============================================================================*/
/* Macro: DT_INLINE */
/* Desc: Please use "static" instead of "inline" if "inline" cannot be used. */
/*==============================================================================*/
#define DT_INLINE inline
/* #define DT_INLINE static */
いずれかをコメントアウトしてください。"inline"が使用できる環境であれば上記のようにします。
使用するポートの初期化
"_TP_BusPortInit"関数で行います。サンプルドライバでは例が書かれています。削除して、ターゲット機器で使用するポートに合わせて初期化してください。また、初期化後にCLKおよびCSのポート(プローブのNo.2とNo.3が接続されているポート)はHi出力してください。
/*==============================================================================*/
/* Func: _TP_BusPortInit */
/* Desc: Please describe the code to initializes ports. */
/*==============================================================================*/
static void _TP_BusPortInit(void)
{
/* ex)
PA.DIR = 0x3f;
PD.DIR = 0x3f;
PA.word = 0x3f;
PD.word = 0x3f;
*/
SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA );
SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD );
GPIOPinTypeGPIOOutput( GPIO_PORTD_BASE, GPIO_PIN_2 ); /* CLK */
GPIOPinTypeGPIOOutput( GPIO_PORTD_BASE, GPIO_PIN_3 ); /* CS */
GPIOPinTypeGPIOOutput( GPIO_PORTA_BASE, GPIO_PIN_2 ); /* DAT0 */
GPIOPinTypeGPIOOutput( GPIO_PORTA_BASE, GPIO_PIN_3 ); /* DAT1 */
GPIOPinTypeGPIOOutput( GPIO_PORTA_BASE, GPIO_PIN_4 ); /* DAT2 */
GPIOPinTypeGPIOOutput( GPIO_PORTA_BASE, GPIO_PIN_5 ); /* DAT3 */
GPIOPinWrite( GPIO_PORTD_BASE, GPIO_PIN_2, GPIO_PIN_2);
GPIOPinWrite( GPIO_PORTD_BASE, GPIO_PIN_3, GPIO_PIN_3);
GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_2, GPIO_PIN_2 );
GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_3, GPIO_PIN_3 );
GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_4, GPIO_PIN_4 );
GPIOPinWrite( GPIO_PORTA_BASE, GPIO_PIN_5, GPIO_PIN_5 );
}
この関数は、ターゲットが初めてテストポイントを通過したときのみ実行されます。すでにターゲット機器のコード上でDT+Traceが使用するポートも初期化している場合は、空にしてかまいません。
CLKポートの制御(GPIO4bit/GPIO2bit接続の場合)
"portReverseCLK"関数で行います。プローブのNo.2で接続されているポートのHi/Loを読み込み反転させます。
/*==============================================================================*/
/* Func: portReverseCLK */
/* Desc: Please describe the code to reverse CLK Port. */
/*==============================================================================*/
DT_INLINE void portReverseCLK(void)
{
/* ex)
PA.bit.b0 ^= 1;
*/
if( GPIOPinRead( GPIO_PORTD_BASE, GPIO_PIN_2 ) ){
GPIOPinWrite( GPIO_PORTD_BASE, GPIO_PIN_2, 0 );
}
else{
GPIOPinWrite( GPIO_PORTD_BASE, GPIO_PIN_2, GPIO_PIN_2 );
}
}
サンプルドライバには例が書かれています。削除して、ターゲットに合わせてカスタマイズしてください。
CLKポートの制御(SPI/I2C接続)
"portSetCLK"関数で行います。この関数の引数"dat"の値は0か1になっていますので、1のときはポートがHi、0のときはポートがLoになるように、プローブのNo.2で接続されているポートを制御します。
/*==============================================================================*/
/* Func: portSetCLK */
/* Desc: Please describe the code to set the value to CLK Port. */
/*==============================================================================*/
DT_INLINE void portSetCLK( DT_UINT dat)
{
/* ex)
PA.bit.b0 = dat?1:0;
*/
GPIOPinWrite( GPIO_PORTD_BASE, GPIO_PIN_2, dat?0xff:0x00 );
}
サンプルドライバには例が書かれています。削除して、ターゲットに合わせてカスタマイズしてください。
CSポートの制御(GPIO4Bit/GPIO2Bit/SPI接続)
"portSetCS"関数で行います。この関数の引数"dat"の値は0か1になっていますので、1のときはポートがHi、0のときはポートがLoになるように、プローブのNo.3で接続されているポートを制御します。
/*==============================================================================*/
/* Func: portSetCS */
/* Desc: Please describe the code to set the value to CS Port. */
/*==============================================================================*/
DT_INLINE void portSetCS(DT_UINT dat)
{
/* ex)
PA.bit.b1 = dat?1:0;
*/
GPIOPinWrite( GPIO_PORTD_BASE, GPIO_PIN_3, dat?0xff:0x00 );
}
サンプルドライバには例が書かれています。削除して、ターゲットに合わせてカスタマイズしてください。
DATAポートの制御
"portSetDATA"関数で行います。この関数の引数"dat"の値はそれぞれの接続方式で以下のようになっています。
サンプルドライバには例が書かれています。削除してターゲットに合わせてカスタマイズしてください。以下はGPIO4bitでのカスタマイズ例です。
/*==============================================================================*/
/* Func: portSetDATA */
/* Desc: Please describe the code to set the value to DATA Port */
/*==============================================================================*/
DT_INLINE void portSetDATA(DT_UINT dat)
{
PA.word = (PA.word & 0xff0f) | ((dat & 0x0f) << 4);
}
割り込み禁止の設定
割り込み処理にもテストポイントが挿入されている場合は、正常なデータ出力のための割り込み禁止処理を明記します。"enterCritical"関数(割り込み禁止の有効化)および"exitCritical"(割り込み禁止の無効化)をカスタマイズしてください。
/*==============================================================================*/
/* Func: enterCritical */
/* Desc: Please describe the code to enter Critical Section. */
/*==============================================================================*/
DT_INLINE void enterCritical(void)
{
/* ex)
DI();
*/
taskENTER_CRITICAL();
}
/*==============================================================================*/
/* Func: exitCritical */
/* Desc: Please describe the code to exit Critical Section. */
/*==============================================================================*/
DT_INLINE void exitCritical(void)
{
/* ex)
EI();
*/
taskEXIT_CRITICAL();
}
そうでない場合は、空関数にして差し支えありません。
_TP_SaveCoverageData関数の実装
溜まったテストポイントの通過情報を出力する関数として_TP_SaveCoverageData関数を実装し、その関数を呼び出す必要があります。
サンプルドライバ内にはご用意していますので、実行させるターゲットプログラムの任意の場所で_TP_SaveCoverageData関数をコールするようにターゲットのソースコードに追加します。
例として、ターゲット機器の操作ボタンを押した時などの外部トリガーを発生させやすい箇所や、定周期で実行される関数に実装します。
※登録しているソースファイルに実装した場合は、再度DTプロジェクトを開き直して再定義を行ってください。
レポートデータの取得と解析
ビルドを行いターゲットを動作させます。DT+Traceでデータ取得を行い、_TP_SaveCoverageData関数が呼び出されたらレポート上にDumpデータが取得されます。
データ取得を停止すると取得したDumpレポートを変換し、テストレポートが表示されます。表示されるデータは、ソースコード上にあるテストポイントの上から順番で、通過したテストポイントだけとなります。実行された順序でテストレポートに表示されませんので、ご注意ください。
通過した情報からC0カバレッジを算出するため、DT+Traceアプリケーションの[レポート解析]→[レポートデータの解析]を行い、カバレッジレポートを表示させます。