C コード生成のための信号データの構成
信号データは、生成されたアルゴリズム コードでブロックの入力信号からブロックの出力信号の値を計算する際に、ルートの Inport ブロックと Outport ブロックに接続する信号を除く中間結果をグローバル メモリに格納する変数で構成されます。信号データはモデルのブロック線図の信号線ではありません。たとえば、次のような場合は、生成コードに信号線のデータ表現は含まれません。
関数呼び出し端子に入る
Send ブロックなどのメッセージ ブロックから出る
計算ブロックを介さずにサブシステムの境界をまたぐ
コード生成用にモデルを構成する際、生成コードでアクセス可能にするブロックの入力信号と出力信号を選択します。たとえば、次のような目的で信号データを構成します。
生成コードの実行中に操作および監視するためにデータをアクセス可能にする。
メモリに格納されるデータの量を最小限に抑える。
コード ジェネレーターが信号データをメモリ内のどこに配置するかを制御する。
信号データをモデル インターフェイスにプロモートし、他のコンポーネントおよびシステムがそのデータにアクセスできるようにする。
生成されたコードの可読性およびトレーサビリティを向上させる。
コード ジェネレーターは信号線の構成の整合性をチェックします。たとえば、コード ジェネレーターは、サブシステムに入る信号線の構成について、対応するサブシステムの入力端子を出る信号線の構成と一致することを検証します。
コード生成について、例ではモデル ConfigurationRapidPrototypingInterface
のブロックの信号を構成する方法を説明します。コード マッピング エディター – C またはコード マッピング プログラミング インターフェイス (coder.mapping.api.CodeMapping
) を使用してコード マッピングを構成できます。
信号についてのコード構成オプションの選択
コード生成の要件に応じて、生成コードで表現するブロックの信号と、その信号データの表現方法を決定します。既定では、モデルの信号は、生成されたコードでは
という名前のグローバル データ構造体のフィールドとして表示されます。カスタマイズを構成しない場合、コード ジェネレーターは生成されたコード内の信号の表現を最適化目的で削除するか変更するかを判断します。カスタマイズを構成する場合は、以下を決定します。model
_B
生成されたコードでアクセス可能にする信号
生成されたコードでアクセス可能にする信号は、モデル コード マッピングに追加する必要があります。
既定の構成を設定するかどうか
多数の信号 (10 を超えるなど) へのアクセスを取得する必要がある場合、既定の設定で信号を構成してから、その設定を特殊なケースについてオーバーライドすると効率的です。固有のソース、命名規則、または配置要件をもつ少数の信号へのアクセスを取得する必要がある場合は、それらの信号を個別に構成することを検討します。
生成されたコードでの信号データの宣言と取り扱いの方法
個別のグローバル変数として
外部コードで定義されているグローバル変数から入力データを読み取るため
アクセス関数への呼び出しとして。Embedded Coder® が必要
これらのオプションの詳細については、生成コードでのデータと関数インターフェイスの制御を参照してください。
その他の考慮事項には次のものがあります。
モデルに表示される信号ラベルを使用して、または一意のコード識別子を使用して、生成されたコードで信号に名前を付けるかどうか。
volatile
型の修飾子をグローバル変数定義および宣言に含めるかどうか。Embedded Coder が必要です。型修飾子 const と volatile を使用したグローバル データの保護 (Embedded Coder)を参照してください。信号データをメモリの特定の領域に配置するかどうか。Embedded Coder が必要です。Control Data and Function Placement in Memory by Inserting Pragmas (Embedded Coder)を参照してください。
信号とそれに対応するストレージ クラスとストレージ クラスのプロパティに関連するインターフェイス要件のリストについては、データ ストアのストレージ クラスおよびストレージ クラス プロパティの選択を参照してください。
モデル例 ConfigurationRapidPrototypingInterface
の信号の要件は次のとおりです。
Switch ブロックに出入りする信号をコード生成用に構成する。生成コードの実行中に監視できるように信号データを保持する。
信号を個別のグローバル変数として表現する。
信号を表す変数の名前に接頭辞
dout_
を適用する。
生成されたコードでの既定の信号の表現を static
型修飾子をもつグローバル変数として設定します。次に、2 つの Lookup Table ブロックの出力信号について、既定のストレージ クラスと必須の接頭辞 dout_
を含む一意のコード識別子を使用するように構成します。
信号をモデル コード マッピングに追加
コード生成用に信号を構成する前に、信号をモデル コード マッピングに追加します。モデル コード マッピングに 2 つの Lookup Table ブロックの出力信号を追加します。
モデル例
ConfigurationRapidPrototypingInterface
を開きます。書き込み可能な場所にモデルのコピーを保存します。Simulink Coder アプリを開きます。
[C コード] タブで、[コード インターフェイス] 、 [個々の要素コードのマッピング] を選択します。
コード マッピング エディターで、[信号/状態] タブをクリックします。リストされた信号はありません。
コード マッピングに信号を追加します。Lookup Table ブロック
Table1
およびTable2
の出力信号について次を実行します。モデルで信号を選択します。
信号線の上または下に表示される省略記号上で一時停止してアクション バーを開きます。[信号の追加] ボタンをクリックします。
コード マッピング エディターで、[信号] ノードが展開され、追加した 2 つの信号がリストされます。
信号に対する既定のコード生成設定の構成
信号の既定のコード生成設定を使用すると、生成されたコードの実行中に監視する信号が多数あるモデルの場合は特に、コード生成のためのモデルの準備作業を軽減できます。構成設定を一度選択すると、コード ジェネレーターによってそれらの設定がモデル全体の信号に適用されます。Simulink® は既定の構成をモデルの一部として保存します。
固有の要件がない複数の信号をモデルで使用する場合は、モデルの信号について既定のコード生成設定を構成することを検討します。
この例では、コード マッピング エディター – C を使用して、モデル ConfigurationRapidPrototypingInterface
の信号に対する既定のストレージ クラスを ExportedGlobal
に設定する方法を示します。ストレージ クラス設定をそのようにすると、コード ジェネレーターは、生成されたコードで信号データをグローバル変数として表します。
まだ実行していない場合は、信号をモデル コード マッピングに追加の説明に従って、信号をモデル コード マッピングに追加します。
[C コード] タブで、[コード インターフェイス] 、 [既定のコード マッピング] を選択します。
コード マッピング エディターの [データの既定の設定] タブで、[信号] の下にあるカテゴリ [Signals, states, and internal data] を選択します。既定のストレージ クラスを
[ExportedGlobal]
に設定します。モデルを保存します。
個別の信号に対するコード生成設定の構成
コード生成についての個別の信号を構成できます。たとえば、モデルに固有のコード生成要件をもつ信号が 2 つある場合、信号を個別に構成します。または、信号について既定の設定を構成する場合、特定の信号についてその設定をオーバーライドできます。
モデルが以下の条件のうち少なくとも 1 つを満たす場合、信号に対して個別にコード生成設定を構成することを検討してください。
固有のソース、命名規則、または配置要件をもつ複数の信号を使用する。
少数の信号を使用する。
信号について既定の構成があり、いくつかの固有の信号についてその構成をオーバーライドする必要がある。
この例では、コード マッピング エディターを使用して、既定のストレージ クラス設定をモデル ConfigurationInterface
内の Lookup Table ブロック Table1
および Table2
の出力信号に適用する方法を示します。この例では、それらの出力信号に対するコード識別子を構成する方法も示します。コード生成識別子は、たとえば統合用に、モデル設計の変更を伴わずに指定できます。
まだ実行していない場合は、信号に対する既定のコード生成設定の構成の手順を完了します。
コード マッピング エディターで、[信号/状態] タブをクリックします。[信号] を展開します。エディターで、コード マッピングに追加した信号の名前またはブロック端子識別子がリストされます。信号が信号オブジェクトに関連付けられる場合、信号オブジェクトへの関連付けアイコンが要素名または端子識別子の右側に表示されます。各信号のストレージ クラスは
Auto
に設定されています。これは、コード ジェネレーターが最適化を目的として関連するコードの表現を削除または変更する可能性があることを意味しています。最適化が不可能な場合、コード ジェネレーターはモデルの既定の構成を適用します。この例の場合、モデルの既定の構成はストレージ クラスExportedGlobal
を指定します。最適化を回避し、コード ジェネレーターで既定の構成が強制的に使われるようにするには、ストレージ クラスを
[Model default]
に設定します。既定の構成をオーバーライドするには、その信号のコード生成に関する要件を満たすストレージ クラスを指定します。
コード マッピング エディターで、
Table1
ブロックとTable2
ブロックの出力信号を選択します。ストレージ クラスを[Model default:ExportedGlobal]
に設定します。2 つの Lookup Table ブロックの出力信号に対するコード識別子を接頭辞
dout_
を含む名前で構成します。コード マッピング エディターで、信号Table1:1
を選択します。 アイコンをクリックして、[識別子] プロパティをdout_Table1
に設定します。信号Table2:1
について、[識別子] をdout_Table2
に設定します。モデルを保存します。
コードを生成して表示します。たとえば、
ConfigurationRapidPrototypingInterface.c
で、ルックアップ テーブル データのデータ定義を見つけます。real_T dout_Table1; real_T dout_Table2;
ステップ エントリポイント関数内でルックアップ テーブル データが使用されている場所を見つけます。
. . . dout_Table1 = look1_binlc((*input2), (&(mp_Table1.BP[0])), (&(mp_Table1.Table[0])), 10U); if (mode) { output = (real_T)mp_K1 * dout_Table1; } else { output = dstate_X; } dout_Table2 = look2_binlc((*input3), (*input4), (&(mp_Table2.BP1[0])), (&(mp_Table2.BP2[0])), (&(mp_Table2.Table[0])), (&(rtwdemo_configr_Table2_maxIndex[0])), 3U);} dstate_X = dout_Table2; }
信号をモデル コード マッピングから削除
[C コード] タブで、[コード インターフェイス] 、 [個々の要素コードのマッピング] を選択します。
コード マッピング エディターで、[信号/状態] タブをクリックします。
削除する信号ごとに次を実行します。
モデルで信号を選択します。
信号線の上または下に表示される省略記号上で一時停止してアクション バーを開きます。[信号の削除] ボタンをクリックします。
信号に対するコード生成設定のプログラムによる構成
コード生成のための信号の構成を自動化するには、コード マッピングのプログラミング インターフェイスを使用します。たとえば、カスタム ブロック ライブラリまたはアプリケーション テスト環境の一部を作成する場合は、プログラミング インターフェイスを使用してデータの構成を自動化します。
この例では、プログラミング インターフェイスを使用して、モデル ConfigurationRapidPrototypingInterface
の信号を構成する方法を示します。生成されたコードでの既定の信号の表現をグローバル変数として設定します。次に、2 つの Lookup Table ブロックの出力信号について、既定のストレージ クラスと必須の接頭辞 dout_
を含む一意のコード識別子を使用するように構成します。
モデル例を開きます。
openExample("ConfigurationRapidPrototypingInterface")
関数
coder.mapping.api.get
を呼び出してオブジェクトcm
を作成します。オブジェクトは、モデルConfigurationRapidPrototypingInterface
のデータのコード生成構成を保存します。cm = coder.mapping.api.get("ConfigurationRapidPrototypingInterface");
関数
setDataDefault
を呼び出して信号の既定の設定を構成します。引数には、次の値を指定します。coder.mapping.api.get
で返されるオブジェクト既定のカテゴリの
InternalData
プロパティ値
ExportedGlobal
をもつプロパティ名StorageClass
setDataDefault(cm,"InternalData","StorageClass","ExportedGlobal");
信号の既定の構成を検証します。
coder.mapping.api.get
およびカテゴリInternalData
によって返されるオブジェクトを指定するgetDataDefault
の呼び出しを発行します。3 番目の引数をプロパティStorageClass
として指定します。getDataDefault(cm,"InternalData","StorageClass")
ans = 'ExportedGlobal'
Lookup Table ブロック
Table1
およびTable2
の出力端子へのハンドルを取得します。端子ハンドルは、信号データをモデル コード マッピングに追加するために使用します。lut1D_ports = get_param("ConfigurationRapidPrototypingInterface/Table1","PortHandles"); lut2D_ports = get_param("ConfigurationRapidPrototypingInterface/Table2","PortHandles"); lut1D_outPort = lut1D_ports.Outport; lut2D_outPort = lut2D_ports.Outport;
モデル コード マッピングに Lookup Table ブロックの出力信号を追加します。
addSignal(cm,[lut1D_outPort,lut2D_outPort]);
信号に対する既定の構成を Lookup Table ブロックの出力信号に適用します。
既定では、Simulink は個別の信号のストレージ クラスを
Auto
に設定します。コード ジェネレーターは次を行います。最適化目的で生成されたコードからデータを削除するかどうかを決定する。
データを保持する場合、既定の構成設定を考慮して、生成されたコード内でデータを効率的に表す方法を決定する。
信号の構成を制御するには、関数
setSignal
を呼び出します。それぞれの信号について、次を指定する
setSignal
への呼び出しを発行します。coder.mapping.api.get
によって返されるオブジェクト信号の端子ハンドル
lut1D_outport
またはlut2D_outport
。信号に対してプロパティ
StorageClass
およびプロパティ値Model default
を使用して以前に設定された既定のストレージ クラス。プロパティ
Identifier
およびプロパティ値dout_Table1
またはdout_Table2
setSignal(cm,lut1D_outPort,"StorageClass","Model default","Identifier","dout_Table1"); setSignal(cm,lut2D_outPort,"StorageClass","Model default","Identifier","dout_Table2");
関数
getsignal
を呼び出して構成の設定を検証します。coder.mapping.api.get
から返されるオブジェクト、信号の端子ハンドル (lut1D_outport
またはlut2D_outport
)、およびプロパティStorageClass
またはIdentifier
を指定します。getSignal(cm,lut1D_outPort,"StorageClass")
ans = 'Model default'
getSignal(cm,lut1D_outPort,"Identifier")
ans = 'dout_Table1'
getSignal(cm,lut2D_outPort,"StorageClass")
ans = 'Model default'
getSignal(cm,lut2D_outPort,"Identifier")
ans = 'dout_Table2'
モデルを保存します。
コードを生成して表示します。たとえば、
ConfigurationRapidPrototypingInterface.c
で、ルックアップ テーブル データのデータ定義を見つけます。real_T dout_Table1; real_T dout_Table2;
ステップ エントリポイント関数内でルックアップ テーブル データが使用されている場所を見つけます。
. . . dout_Table1 = look1_binlc((*input2), (&(mp_Table1.BP[0])), (&(mp_Table1.Table[0])), 10U); if (mode) { output = (real_T)mp_K1 * dout_Table1; } else { output = dstate_X; } dout_Table2 = look2_binlc((*input3), (*input4), (&(mp_Table2.BP1[0])), (&(mp_Table2.BP2[0])), (&(mp_Table2.Table[0])), (&(rtwdemo_configr_Table2_maxIndex[0])), 3U);} dstate_X = dout_Table2; }
信号のストレージ クラスおよびストレージ クラス プロパティの選択
コード生成の要件に応じて、ブロックの信号に対してコード生成を構成するストレージ クラスを次から選択します。
ヒント
既定のマッピングでは、信号は [Signals, states, and internal data] セクションで構成されます。
要件 | 既定のマッピングのストレージ クラス | 個別のマッピングのストレージ クラス |
---|---|---|
より効率的なコードを生成するように、最適化を有効にします。 | 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)を参照してください。
個別の信号については、[識別子] ストレージ クラス プロパティを使用して、生成されたコードで信号を表す変数の名前を構成します。[Identifier] プロパティを空白のままにすると、コード ジェネレーターは信号ラベルを使用します。信号ラベルが空の場合、コード ジェネレーターは信号を出力するブロックの名前を使用します。
参考
コード マッピング エディター – C | coder.mapping.api.CodeMapping