C コード生成のためのルートレベルの Inport ブロックの構成
モデルから生成するコードを使用するには、生成されたエントリポイント関数を呼び出します。呼び出しの環境と生成される関数は、たとえばグローバル変数や関数の引数として、入力データと出力データを交換します。ルートレベルの Inport ブロック (入力端子) がインターフェイスの入力データを構成します。生成されたコードをアプリケーションに統合して展開するため、入力データの宣言と取り扱いの方法を含め、コード ジェネレーターがインターフェイス コードを生成する方法をカスタマイズできます。カスタマイズにより、次のことができます。
既存のコードに行わなければならない変更の最小化。
モデルに変更を行う場合に、変更しない、あるいは最小限の変更しか行わない、安定したインターフェイスの生成。
データをより効率的に交換するコードの生成 (たとえば、非スカラー データに対するポインターおよび参照渡しの引数の使用による)。
コード生成について、この例ではモデル ConfigurationRapidPrototypingInterface
の Inport インターフェイスをカスタマイズする方法を説明します。コード マッピング エディター – C またはコード マッピング API (coder.mapping.api.CodeMapping
) を使用してコード マッピングを構成できます。
Inport インターフェイスのカスタマイズ オプションの選択
既定では、モデルのルートレベルの Inport は、生成されたコードでは
という名前のグローバル データ構造体のフィールドとして表示されます。コード インターフェイスの要件に基づいて、ルートレベルの Inport データの生成をカスタマイズするかどうかを決定します。カスタマイズを構成しない場合、コード ジェネレーターは生成されたコード内の Inport の表現を最適化目的で削除するか変更するかを判断します。カスタマイズを構成する場合は、以下を決定します。model
_ExtU
既定の構成を設定するかどうか
モデルに多数 (たとえば 10 より多い) のルートレベルの Inport が含まれている場合、それらの Inport を既定の設定で構成して、それから特殊な場合についてその設定をオーバーライドすることがより効率的です。モデルに固有のソース、名前、または配置要件をもつ少数のルートレベルの Inport が含まれている場合は、その Inport を個別に構成することを検討します。
生成されたインターフェイスでルートレベルの Inport データを宣言し取り扱う方法
個別のグローバル変数として
外部コードで定義されているグローバル変数から入力データを読み取るため
参照モデルの Inport の場合にグローバル変数 (
void-void
) としてアクセス関数への呼び出しとして。Embedded Coder® が必要
エントリポイント関数の引数として。Embedded Coder が必要
これらのオプションの詳細については、生成コードでのデータと関数インターフェイスの制御を参照してください。
その他の考慮事項には次のものがあります。
モデル内で表示される Inport ブロック ラベルを使用して、または一意のコード識別子を使用して、生成されたコード内の Inport に名前を付けるかどうか。
volatile
型の修飾子をグローバル変数定義および宣言に含めるかどうか。Embedded Coder が必要です。型修飾子 const と volatile を使用したグローバル データの保護 (Embedded Coder)を参照してください。読み取られたデータをメモリの特定の領域に配置するかどうか。Embedded Coder が必要です。Control Data and Function Placement in Memory by Inserting Pragmas (Embedded Coder)を参照してください。
対応するストレージ クラスとストレージ クラス プロパティをもつ Inport に関連するインターフェイス要件のリストについては、生成されたコードでのデータ表示を制御するストレージ クラスの選択を参照してください。
モデル例 ConfigurationRapidPrototypingInterface
の Inport のインターフェイス要件は次のとおりです。
ルートレベルの Inport
In1
、In2
、In3
、およびIn4
のデータを外部ヘッダー ファイルから取得する。In1
で読み取られたデータはメモリに格納される値の計算に使用され、Switch ブロックについて生成されたコードの if-else 条件で使用されます。他の 3 つの Inport から読み取られたデータはルックアップ テーブルTable1
およびTable2
で使用されます。Inport
In1
のデータは値で渡されなければならない。Inport
In2
、In3
、およびIn4
のデータは参照で渡されなければならない。生成されたコードで Inport を表す変数は
input1
、input2
、input3
、およびinput4
という名前でなければならない。
この例では、ConfigurationRapidPrototypingInterface
の Inport を構成して、これらのコード生成要件を満たすようにします。
ルートレベルの Inport に対する既定のコード生成設定の構成
ルートレベルの Inport に対する既定のコード生成設定を使用すると、特に、モデルに多数の Inport がある場合に、コード生成のためのモデルの準備作業を削減できます。構成設定を一度選択すると、コード ジェネレーターによってこれらの設定がモデル全体の Inport に適用されます。Simulink® は既定の構成をモデルの一部として保存します。
固有の要件がないルートレベルの Inport がモデルで複数使用されている場合は、モデルのルートレベルの Inport について既定のコード生成設定を構成することを検討します。
この例では、コード マッピング エディター – C を使用して、モデル ConfigurationRapidPrototypingInterface
のルートレベルの Inport について既定の設定を構成する方法を説明します。Inport が外部ヘッダー ファイルで宣言された変数から入力を読み取るように指定します。
モデル例
ConfigurationRapidPrototypingInterface
を開きます。書き込み可能な場所にモデルのコピーを保存します。Simulink Coder アプリを開きます。
[C コード] タブで、[コード インターフェイス] 、 [既定のコード マッピング] を選択します。
コード マッピング エディターの [Inports and Outports] でカテゴリ [Inports] を選択します。既定のストレージ クラスを
[ImportedExternPointer]
に設定します。モデルを保存します。
個別のルートレベル Inport に対するコード生成設定の構成
コード生成について、個別のルートレベルの Inport を構成できます。たとえば、固有のコード生成要件をもつルートレベルの Inport がモデルに 2 つある場合には、Inport を個別に構成します。または、Inport に対して既定の設定を構成する場合、個別の Inport を、既定の設定を使用するか、または固有の設定を使用するよう構成します。
モデルが以下の条件のうち少なくとも 1 つを満たす場合、ルートレベルの Inport に対して個別にコード生成設定を構成することを検討してください。
固有の要件をもつ Inport を複数使用する。
使用する Inport が少数である。
Inport について既定の構成があり、いくつかの Inport について、その構成をオーバーライドする必要がある。
この例では、コード マッピング エディターを使用して、モデル ConfigurationRapidPrototypingInterface
の Inport の 1 つに対する既定のコード生成構成をオーバーライドする方法を説明します。前の例で、Inport の既定のストレージ クラスを ImportedExternPointer
に設定しました。
この例では、コード ジェネレーターが、生成されたコードで 4 つの Inport に名前を付けるために使用する識別子を構成する方法も説明します。コード生成識別子は、たとえば統合用に、モデル設計の変更を伴わずに指定できます。
まだ実行していない場合は、ルートレベルの Inport に対する既定のコード生成設定の構成の手順を完了します。
コード マッピング エディターで、[入力端子] タブをクリックします。エディターに、モデル内の Inport ブロックの名前とバス要素の名前がリストされます。端子が信号オブジェクトに関連付けられる場合、信号オブジェクトへの関連付けアイコンが要素名の右側に表示されます。各 Inport のストレージ クラスは
Auto
に設定されています。これは、コード ジェネレーターが最適化を目的として関連するコードの表現を削除または変更する可能性があることを意味しています。最適化が不可能な場合、コード ジェネレーターはモデルの既定の構成を適用します。この例の場合、モデルの既定の構成はストレージ クラスImportedExternPointer
を指定します。最適化を回避し、コード ジェネレーターで既定の構成が強制的に使われるようにするには、ストレージ クラスを
[Model default]
に設定します。既定のコンフィギュレーションをオーバーライドするには、その Inport のコード生成に関する要件を満たすストレージ クラスを指定します。
コード ジェネレーターを構成し、既定のストレージ クラスが Inport
In2
、In3
、およびIn4
に設定されるように適用します。これら 3 つの Inport の行を選択します。次に、選択したいずれかの Inport に対して、ストレージ クラスを[Model default: ImportedExternPointer]
に設定します。選択した 3 つの Inport のストレージ クラスが
[Model default: ImportedExternPointer]
に変更されます。Inport
In1
については、既定のストレージ クラス設定をオーバーライドします。ストレージ クラスを[ImportedExtern]
に設定します。生成されたコード内のインターフェイス引数名が外部のヘッダー ファイルおよび定義ファイル内のインターフェイス名と一致するように、Inport のコード識別子を構成します。コード マッピング エディターで、各 Inport の行を選択します。
アイコンをクリックして、[識別子] プロパティを次の値に設定します。
Inport コード識別子 In1
input1
In2
input2
In3
input3
In4
input4
モデルを保存します。
コードを生成して表示します。たとえば、
ConfigurationRapidPrototypingInterface.c
で、ステップ エントリポイント関数内で変数input1
、input2
、input3
、およびinput4
が使用されている場所を見つけます。void ConfigurationRapidPrototypingInterface_step(void) { mode = ((input1 > 10.0) || (input1 < -10.0)); if (mode) { output = 2.0 * look1_binlc((*input2), rtCP_Table1_bp01Data, rtCP_Table1_tableData, 10U); } else { output = ConfigurationRapidPrototypin_DW.X; } ConfigurationRapidPrototypin_DW.X = look2_binlc((*input3), (*input4), rtCP_Table2_bp01Data, rtCP_Table2_bp02Data, rtCP_Table2_tableData, rtCP_Table2_maxIndex, 3U); }
ルートレベルの Inport についてのプログラムでのコード生成設定の構成
コード生成のためのルートレベルの Inport の構成を自動化するには、コード マッピングのプログラミング インターフェイスを使用します。たとえば、カスタム ブロック ライブラリまたはアプリケーション テスト環境の一部を作成する場合は、プログラミング インターフェイスを使用してデータの構成を自動化します。
この例では、プログラミング インターフェイスを使用して、モデル ConfigurationRapidPrototypingInterface
についてルートレベルの Inport の既定の設定を構成する方法を説明します。4 つの Inport のうちの 3 つが外部ファイルで定義されたグローバル ポインター変数から入力を読み取ります。生成されたコードにおいて Inport が既定でグローバル ポインター変数から入力を読み取るように構成します。その後、入力データを値で渡す必要がある In1
について、既定のコード生成構成をオーバーライドします。
さらに、生成されたコード内のグローバル変数名が外部ファイルで定義された変数名と一致するように、Inport のコード識別子を構成します。
モデル例を開きます。
openExample("ConfigurationRapidPrototypingInterface")
関数
coder.mapping.api.get
を呼び出してオブジェクトcm
を作成します。オブジェクトは、モデルConfigurationRapidPrototypingInterface
のデータのコード生成構成を保存します。cm = coder.mapping.api.get("ConfigurationRapidPrototypingInterface");
関数
setDataDefault
を呼び出して Inport の既定の設定を構成します。引数には、次の値を指定します。coder.mapping.api.get
で返されるオブジェクト既定のカテゴリの
Inports
プロパティ値
ImportedExternPointer
をもつプロパティ名StorageClass
setDataDefault(cm,"Inports","StorageClass","ImportedExternPointer")
Inport の既定の構成を検証します。
coder.mapping.api.get
によって返されるオブジェクト、カテゴリInports
、およびStorageClass
を指定するgetDataDefault
の呼び出しを発行します。getDataDefault(cm,"Inports","StorageClass")
ans = 'ImportedExternPointer'
Inport
In1
について、既定の Inport の構成をオーバーライドします。その Inport の要件は他の 3 つの Inport の要件と異なります。既定では、Simulink は個別の Inport のストレージ クラスを
Auto
に設定します。ストレージ クラスがAuto
の場合、コード ジェネレーターは次を行います。最適化目的で生成されたコードからデータを削除するかどうかを決定する。
データを保持する場合、既定の構成設定を考慮して、生成されたコード内でデータを効率的に表す方法を決定する。
Inport のストレージ クラスの構成を制御するには、関数
setInport
で Inport の設定を構成します。InportIn1
に対して生成されるコードについて、要件で指定されているとおり、外部ファイルで定義されたグローバル変数から入力データを読み取るように構成します。coder.mapping.api.get
によって返されるオブジェクト、In1
という名前の Inport ブロック、プロパティ名StorageClass
、およびプロパティ値ImportedExtern
を指定する関数setInport
の呼び出しを発行します。setInport(cm,"In1","StorageClass","ImportedExtern")
関数
getInport
を呼び出して、InportIn1
の構成を検証します。getInport(cm,"In1","StorageClass")
ans = 'ImportedExtern'
コード ジェネレーターを構成して、既定の Inport の設定を Inport
In2
、In3
、およびIn4
に適用します。Inport ごとに関数setInport
を呼び出します。coder.mapping.api.get
から返されるオブジェクト、ブロック名 Inport、プロパティ名StorageClass
、およびプロパティ値Model default
を指定します。setInport(cm,"In2","StorageClass","Model default") setInport(cm,"In3","StorageClass","Model default") setInport(cm,"In4","StorageClass","Model default")
関数
getInport
への呼び出しを使用して、InportIn2
、In3
、およびIn4
の構成の変更を検証します。getInport(cm,"In2","StorageClass")
ans = 'Model default'
getInport(cm,"In3","StorageClass")
ans = 'Model default'
getInport(cm,"In4","StorageClass")
ans = 'Model default'
生成されたコード内の Inport を表すグローバル変数が外部の定義ファイル内の変数名と一致するように、Inport のコード識別子を構成します。Inport ごとに関数
setInport
を呼び出します。coder.mapping.api.get
から返されるオブジェクト、ブロック名 Inport、プロパティ名Identifier
、および次のいずれかのプロパティ値を指定します。Inport コード識別子 In1
input1
In2
input2
In3
input3
In4
input4
setInport(cm,"In1","Identifier","input1"); setInport(cm,"In2","Identifier","input2"); setInport(cm,"In3","Identifier","input3"); setInport(cm,"In4","Identifier","input4");
関数
getInport
への呼び出しを使用して、Inport の構成の変更を検証します。getInport(cm,"In1","Identifier")
ans = 'input1'
getInport(cm,"In2","Identifier")
ans = 'input2'
getInport(cm,"In3","Identifier")
ans = 'input3'
getInport(cm,"In4","Identifier")
ans = 'input4'
モデルを保存します。
コードを生成して表示します。たとえば、
ConfigurationRapidPrototypingInterface.c
で、ステップ エントリポイント関数内で変数input1
、input2
、input3
、およびinput4
が使用されている場所を見つけます。void ConfigurationRapidPrototypingInterface_step(void) { mode = ((input1 > 10.0) || (input1 < -10.0)); if (mode) { output = 2.0 * look1_binlc((*input2), rtCP_Table1_bp01Data, rtCP_Table1_tableData, 10U); } else { output = ConfigurationRapidPrototypin_DW.X; } ConfigurationRapidPrototypin_DW.X = look2_binlc((*input3), (*input4), rtCP_Table2_bp01Data, rtCP_Table2_bp02Data, rtCP_Table2_tableData, rtCP_Table2_maxIndex, 3U); }
ルートレベルの Inport に対するストレージ クラスとストレージ クラス プロパティの選択
コード生成の要件に応じて、ルートレベルの Inport に対してコード生成を構成するストレージ クラスを次から選択します。
要件 | 既定のマッピングのストレージ クラス | 個別のマッピングのストレージ クラス |
---|---|---|
より効率的なコードを生成するように、最適化を有効にします。 | Auto | |
最適化できないデータ要素の場合、データを標準のデータ構造体のフィールドとして表します。 | 既定値 | |
最適化によってデータ要素のストレージが削除されるのを防ぎ、データ要素のカテゴリに対して既定のマッピングを使用します。 | Model Default, | |
グローバル変数の定義と宣言を生成します。 | ExportedGlobal | ExportedGlobal |
外部コードで定義されたグローバル変数またはグローバル変数のポインターに対して読み取りと書き込みを実行するコードを生成します。 | ImportedExtern、ImportedExternPointer | ImportedExtern、ImportedExternPointer |
使用可能なストレージ クラスのリストには、Embedded Coder ディクショナリで定義された他のプロジェクト固有のストレージ クラスが含まれている可能性があります。リストされているストレージ クラスでは満たされない特別な要件がある場合、Embedded Coder ソフトウェアをお持ちであれば、ストレージ クラスを定義できます。Define Service Interfaces, Storage Classes, Memory Sections, and Function Templates for Software Architecture (Embedded Coder)を参照してください。
個別の Inport について、[識別子] ストレージ クラス プロパティを使用して、生成されたコードでその Inport を表す変数の名前を構成します。[Identifier] プロパティを空白のままにすると、コード ジェネレーターは Inport ブロックに接続されている信号の名前を使用します。信号ラベルが空の場合、コード ジェネレーターは Inport ブロックの名前を使用します。
参考
コード マッピング エディター – C | coder.mapping.api.CodeMapping