よくある質問(FAQ)

レジスタマップにi/oポートの構造体が表示されません。どの様にすればいいですか?

テストCSVについて

質問

ソースコードに定義されたi/oポートを入出力変数に指定したいのですが、「レジスタマップ」に該当i/oポートの構造体が表示されません。どの様にすればいいですか?

回答

typedef struct { // タグ名がない
union {
unsigned char BYTE;
struct {
unsigned char B7:1;
unsigned char B6:1;
unsigned char B5:1;
unsigned char B4:1;
unsigned char B3:1;
unsigned char B2:1;
unsigned char B1:1;
unsigned char B0:1;
} BIT;
} DR;
} st_port;

#define PORT (*(volatile st_port *)0x10000000) // キャストにのみ使用される
#define PORT_TEST PORT.DR.BIT.B6

void Test_IO(void)
{
PORT_TEST = 1; // 特定ビットに出力する
}


上記サンプルコードの場合、構造体情報がデバッグ情報に出力されず、その結果構造体が「レジスタマップ」に表示されません。2つの問題があります。1)のみで回避できる場合と、1), 2)両方の回避法が必要な場合があります(コンパイラによります)。

1) 構造体定義に「タグ名」がない。

構造体のtypedef 定義にタグ名がない場合、レジスタマップに表示することができません。カバレッジマスターにおいては、レジスタマップはタグ名を使用してレジスタポートを表示する仕組みとなっているためです。

回避方法は構造体定義にタグ名を付加することです。

typedef struct _st_port { // 任意のタグ名を付加する
union {
unsigned char BYTE;
struct {
unsigned char B7:1;
unsigned char B6:1;
unsigned char B5:1;
unsigned char B4:1;
unsigned char B3:1;
unsigned char B2:1;
unsigned char B1:1;
unsigned char B0:1;
} BIT;
} DR;
} st_port;


2) 構造体の宣言(typedef)がキャストのみに使用され、実体が作成されていない。

構造体のtypedefがキャストのみに使用され、実体が作成されていない場合、コンパイラによっては構造体情報がデバッグ情報に出力されず、その結果レジスタマップに表示されないことがあります。

回避するためには、構造体のダミー変数をグローバル宣言し、メンバーをアクセスするダミー関数を作成し、強制的に構造体情報をデバッグ情報に出力させるという方法になります。具体的には下記のようなコードを別ソース(たとえば"dummy.c")に実装してプロジェクトに追加ビルドするか、あるいは既存のスタブソース("SMSTB_SrcFile.c")に記載します。

volatile st_port *st_dummy; // ダミーの構造体変数を宣言する

// ダミー関数(ダミー構造体変数がコンパイラ最適化で削除されないようにする)

void dummy(void)
{
st_dummy->DR.BIT.B0 = 0; // メンバ名までアクセスするコードを書く
}


1)のみ、もしくは1), 2)両方の対策によってオブジェクトファイル中に構造体のデバッグ情報が出力されるようになり、その結果レジスタマップに構造体が表示される様になります。