Main Content

C コード生成のためのルートレベルの Inport ブロックの構成

モデルから生成するコードを使用するには、生成されたエントリポイント関数を呼び出します。呼び出しの環境と生成される関数は、たとえばグローバル変数や関数の引数として、入力データと出力データを交換します。ルートレベルの Inport ブロック (入力端子) がインターフェイスの入力データを構成します。生成されたコードをアプリケーションに統合して展開するため、入力データの宣言と取り扱いの方法を含め、コード ジェネレーターがインターフェイス コードを生成する方法をカスタマイズできます。カスタマイズにより、次のことができます。

  • 既存のコードに行わなければならない変更の最小化。

  • モデルに変更を行う場合に、変更しない、あるいは最小限の変更しか行わない、安定したインターフェイスの生成。

  • データをより効率的に交換するコードの生成 (たとえば、非スカラー データに対するポインターおよび参照渡しの引数の使用による)。

コード生成について、この例ではモデル ConfigurationRapidPrototypingInterface の Inport インターフェイスをカスタマイズする方法を説明します。コード マッピング エディター – C またはコード マッピング API (coder.mapping.api.CodeMapping) を使用してコード マッピングを構成できます。

Inport インターフェイスのカスタマイズ オプションの選択

既定では、モデルのルートレベルの Inport は、生成されたコードでは model_ExtU という名前のグローバル データ構造体のフィールドとして表示されます。コード インターフェイスの要件に基づいて、ルートレベルの Inport データの生成をカスタマイズするかどうかを決定します。カスタマイズを構成しない場合、コード ジェネレーターは生成されたコード内の Inport の表現を最適化目的で削除するか変更するかを判断します。カスタマイズを構成する場合は、以下を決定します。

  • 既定の構成を設定するかどうか

    モデルに多数 (たとえば 10 より多い) のルートレベルの Inport が含まれている場合、それらの Inport を既定の設定で構成して、それから特殊な場合についてその設定をオーバーライドすることがより効率的です。モデルに固有のソース、名前、または配置要件をもつ少数のルートレベルの Inport が含まれている場合は、その Inport を個別に構成することを検討します。

  • 生成されたインターフェイスでルートレベルの Inport データを宣言し取り扱う方法

    • 個別のグローバル変数として

    • 外部コードで定義されているグローバル変数から入力データを読み取るため

    • 参照モデルの Inport の場合にグローバル変数 (void-void) として

    • アクセス関数への呼び出しとして。Embedded Coder® が必要

    • エントリポイント関数の引数として。Embedded Coder が必要

    これらのオプションの詳細については、生成コードでのデータと関数インターフェイスの制御を参照してください。

その他の考慮事項には次のものがあります。

対応するストレージ クラスとストレージ クラス プロパティをもつ Inport に関連するインターフェイス要件のリストについては、生成されたコードでのデータ表示を制御するストレージ クラスの選択を参照してください。

モデル例 ConfigurationRapidPrototypingInterface の Inport のインターフェイス要件は次のとおりです。

  • ルートレベルの Inport In1In2In3、および In4 のデータを外部ヘッダー ファイルから取得する。In1 で読み取られたデータはメモリに格納される値の計算に使用され、Switch ブロックについて生成されたコードの if-else 条件で使用されます。他の 3 つの Inport から読み取られたデータはルックアップ テーブル Table1 および Table2 で使用されます。

  • Inport In1 のデータは値で渡されなければならない。

  • Inport In2In3、および In4 のデータは参照で渡されなければならない。

  • 生成されたコードで Inport を表す変数は input1input2input3、および input4 という名前でなければならない。

この例では、ConfigurationRapidPrototypingInterface の Inport を構成して、これらのコード生成要件を満たすようにします。

ルートレベルの Inport に対する既定のコード生成設定の構成

ルートレベルの Inport に対する既定のコード生成設定を使用すると、特に、モデルに多数の Inport がある場合に、コード生成のためのモデルの準備作業を削減できます。構成設定を一度選択すると、コード ジェネレーターによってこれらの設定がモデル全体の Inport に適用されます。Simulink® は既定の構成をモデルの一部として保存します。

固有の要件がないルートレベルの Inport がモデルで複数使用されている場合は、モデルのルートレベルの Inport について既定のコード生成設定を構成することを検討します。

この例では、コード マッピング エディター – C を使用して、モデル ConfigurationRapidPrototypingInterface のルートレベルの Inport について既定の設定を構成する方法を説明します。Inport が外部ヘッダー ファイルで宣言された変数から入力を読み取るように指定します。

  1. モデル例 ConfigurationRapidPrototypingInterface を開きます。書き込み可能な場所にモデルのコピーを保存します。

    Simulink model to use for learning how to configure signals for code generation.

  2. Simulink Coder アプリを開きます。

  3. [C コード] タブで、[コード インターフェイス][既定のコード マッピング] を選択します。

  4. コード マッピング エディターの [Inports and Outports] でカテゴリ [Inports] を選択します。既定のストレージ クラスを [ImportedExternPointer] に設定します。

    Code Mappings editor with Data Defaults tab selected, Inports and Outports tree node expanded, and storage class for Inports set to ImportedExternPointer.

  5. モデルを保存します。

個別のルートレベル Inport に対するコード生成設定の構成

コード生成について、個別のルートレベルの Inport を構成できます。たとえば、固有のコード生成要件をもつルートレベルの Inport がモデルに 2 つある場合には、Inport を個別に構成します。または、Inport に対して既定の設定を構成する場合、個別の Inport を、既定の設定を使用するか、または固有の設定を使用するよう構成します。

モデルが以下の条件のうち少なくとも 1 つを満たす場合、ルートレベルの Inport に対して個別にコード生成設定を構成することを検討してください。

  • 固有の要件をもつ Inport を複数使用する。

  • 使用する Inport が少数である。

  • Inport について既定の構成があり、いくつかの Inport について、その構成をオーバーライドする必要がある。

この例では、コード マッピング エディターを使用して、モデル ConfigurationRapidPrototypingInterface の Inport の 1 つに対する既定のコード生成構成をオーバーライドする方法を説明します。前の例で、Inport の既定のストレージ クラスを ImportedExternPointer に設定しました。

この例では、コード ジェネレーターが、生成されたコードで 4 つの Inport に名前を付けるために使用する識別子を構成する方法も説明します。コード生成識別子は、たとえば統合用に、モデル設計の変更を伴わずに指定できます。

  1. まだ実行していない場合は、ルートレベルの Inport に対する既定のコード生成設定の構成の手順を完了します。

  2. コード マッピング エディターで、[入力端子] タブをクリックします。エディターに、モデル内の Inport ブロックの名前とバス要素の名前がリストされます。端子が信号オブジェクトに関連付けられる場合、信号オブジェクトへの関連付けアイコンが要素名の右側に表示されます。各 Inport のストレージ クラスは Auto に設定されています。これは、コード ジェネレーターが最適化を目的として関連するコードの表現を削除または変更する可能性があることを意味しています。最適化が不可能な場合、コード ジェネレーターはモデルの既定の構成を適用します。この例の場合、モデルの既定の構成はストレージ クラス ImportedExternPointer を指定します。

    • 最適化を回避し、コード ジェネレーターで既定の構成が強制的に使われるようにするには、ストレージ クラスを [Model default] に設定します。

    • 既定のコンフィギュレーションをオーバーライドするには、その Inport のコード生成に関する要件を満たすストレージ クラスを指定します。

  3. コード ジェネレーターを構成し、既定のストレージ クラスが Inport In2In3、および In4 に設定されるように適用します。これら 3 つの Inport の行を選択します。次に、選択したいずれかの Inport に対して、ストレージ クラスを [Model default: ImportedExternPointer] に設定します。

    Code Mappings editor with Inports tab selected, signals In2, In3, and In4 selected, and storage class being set to Model default: ImportedExternPointer.

    選択した 3 つの Inport のストレージ クラスが [Model default: ImportedExternPointer] に変更されます。

  4. Inport In1 については、既定のストレージ クラス設定をオーバーライドします。ストレージ クラスを [ImportedExtern] に設定します。

    Code Mappings editor with Inports tab selected, signal In1 selected, and storage class being set to ImportedExtern

  5. 生成されたコード内のインターフェイス引数名が外部のヘッダー ファイルおよび定義ファイル内のインターフェイス名と一致するように、Inport のコード識別子を構成します。コード マッピング エディターで、各 Inport の行を選択します。Icon to configure additional code mapping properties アイコンをクリックして、[識別子] プロパティを次の値に設定します。

    Inportコード識別子
    In1input1
    In2input2
    In3input3
    In4input4
  6. モデルを保存します。

  7. コードを生成して表示します。たとえば、ConfigurationRapidPrototypingInterface.c で、ステップ エントリポイント関数内で変数 input1input2input3、および 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 のコード識別子を構成します。

  1. モデル例を開きます。

    openExample("ConfigurationRapidPrototypingInterface")
    
  2. 関数 coder.mapping.api.get を呼び出してオブジェクト cm を作成します。オブジェクトは、モデル ConfigurationRapidPrototypingInterface のデータのコード生成構成を保存します。

    cm = coder.mapping.api.get("ConfigurationRapidPrototypingInterface");
    
  3. 関数 setDataDefault を呼び出して Inport の既定の設定を構成します。引数には、次の値を指定します。

    • coder.mapping.api.get で返されるオブジェクト

    • 既定のカテゴリの Inports

    • プロパティ値 ImportedExternPointer をもつプロパティ名 StorageClass

    setDataDefault(cm,"Inports","StorageClass","ImportedExternPointer")
    
  4. Inport の既定の構成を検証します。coder.mapping.api.get によって返されるオブジェクト、カテゴリ Inports、および StorageClass を指定する getDataDefault の呼び出しを発行します。

    getDataDefault(cm,"Inports","StorageClass")
    
    ans =
    
        'ImportedExternPointer'
    
  5. Inport In1 について、既定の Inport の構成をオーバーライドします。その Inport の要件は他の 3 つの Inport の要件と異なります。

    既定では、Simulink は個別の Inport のストレージ クラスを Auto に設定します。ストレージ クラスが Auto の場合、コード ジェネレーターは次を行います。

    • 最適化目的で生成されたコードからデータを削除するかどうかを決定する。

    • データを保持する場合、既定の構成設定を考慮して、生成されたコード内でデータを効率的に表す方法を決定する。

    Inport のストレージ クラスの構成を制御するには、関数 setInport で Inport の設定を構成します。Inport In1 に対して生成されるコードについて、要件で指定されているとおり、外部ファイルで定義されたグローバル変数から入力データを読み取るように構成します。coder.mapping.api.get によって返されるオブジェクト、In1 という名前の Inport ブロック、プロパティ名 StorageClass、およびプロパティ値 ImportedExtern を指定する関数 setInport の呼び出しを発行します。

    setInport(cm,"In1","StorageClass","ImportedExtern")
    
  6. 関数 getInport を呼び出して、Inport In1 の構成を検証します。

    getInport(cm,"In1","StorageClass")
    
    ans =
    
        'ImportedExtern'
    
  7. コード ジェネレーターを構成して、既定の Inport の設定を Inport In2In3、および 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")
    
  8. 関数 getInport への呼び出しを使用して、Inport In2In3、および In4 の構成の変更を検証します。

    getInport(cm,"In2","StorageClass")
    
    ans =
    
        'Model default'
    
    getInport(cm,"In3","StorageClass")
    
    ans =
    
        'Model default'
    
    getInport(cm,"In4","StorageClass")
    
    ans =
    
        'Model default'
    
  9. 生成されたコード内の Inport を表すグローバル変数が外部の定義ファイル内の変数名と一致するように、Inport のコード識別子を構成します。Inport ごとに関数 setInport を呼び出します。coder.mapping.api.get から返されるオブジェクト、ブロック名 Inport、プロパティ名 Identifier、および次のいずれかのプロパティ値を指定します。

    Inportコード識別子
    In1input1
    In2input2
    In3input3
    In4input4
    setInport(cm,"In1","Identifier","input1");
    setInport(cm,"In2","Identifier","input2");
    setInport(cm,"In3","Identifier","input3");
    setInport(cm,"In4","Identifier","input4");
    
  10. 関数 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'
    
  11. モデルを保存します。

  12. コードを生成して表示します。たとえば、ConfigurationRapidPrototypingInterface.c で、ステップ エントリポイント関数内で変数 input1input2input3、および 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,
グローバル変数の定義と宣言を生成します。ExportedGlobalExportedGlobal
外部コードで定義されたグローバル変数またはグローバル変数のポインターに対して読み取りと書き込みを実行するコードを生成します。ImportedExtern、ImportedExternPointerImportedExtern、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 ブロックの名前を使用します。

参考

|

関連するトピック