よくある質問(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) の両方を実施することで、オブジェクトファイル内に対象構造体のデバッグ情報が出力されるようになり、その結果として「レジスタマップ」に構造体が表示されるようになります。