Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

Simulink Function ブロックとコードの生成

Simulink Function ブロックと関数呼び出し元からコードを生成する理由

Simulink Function ブロックは、共有リソースを表すモデリング コンポーネントの C コードまたは C++ コードを生成するためのメカニズムを提供します。Simulink Function ブロックでロジックをリソースとして定義すると、関数インターフェイス (名前と引数) がロジックの実装と分離されます。関数の呼び出し元 (Function Caller ブロック、MATLAB Function ブロック、および Stateflow® チャート) はモデルの階層構造のさまざまなレベルで関数ロジックを再利用できます。

Simulink Function ブロックは、再利用可能なサブシステムに代わる方法を提供します。たとえば、Subsystem ブロックではなく Simulink Function ブロックを使用する場合、Simulink Function ブロックでは関数の呼び出し元間で状態が共有される点に注意します。コード ジェネレーターは 1 つの関数を生成します。Simulink Function ブロックに、遅延やメモリなどの状態をもつブロックが含まれている場合、状態は関数の呼び出し元間で維持されます。関数の呼び出し順序は、重要な考慮事項です。

コード ジェネレーターがサブシステムから生成する再利用可能な関数では、状態は共有されません。コード ジェネレーターはサブシステムの複数のインスタンスに対して 1 つの関数を最適化として生成します。該当のサブシステムに状態をもつブロックが含まれる場合、コード ジェネレーターでは 1 つの関数が生成されますが、異なる状態変数が各インスタンスに渡されます。インスタンスは状態を共有しません。

Simulink Function ブロックと呼び出し元のその他の用途は次のとおりです。

  • 関数の呼び出しを入れ子にする。

  • 1 つのモデリング コンポーネントで定義された関数を別のモデリング コンポーネントから呼び出す。

  • グローバルにアクセス可能な関数またはスコープが設定された関数を生成する。

  • クライアント/サーバー アプリケーション用のコードを生成する。

実装オプション

コード生成要件に基づいて、Simulink® 関数および関数の呼び出し元を実装する方法を選択します。考慮事項は以下のとおりです。

  • モデルで関数および関数の呼び出し元を表す方法

  • 関数のスコープ

  • 関数をモデルからエクスポートするかどうか (Embedded Coder® が必要)

  • 関数コード インターフェイスのカスタマイズ (Embedded Coder が必要)

  • コード生成に関する要件

  • コード生成の制限

モデリング パターンの選択

この表には、入力値を 2 倍にする関数と、Simulink モデルでこの関数を表すことができる Simulink Function ブロックを表す C コードを示します。

関数定義モデル要素

codegen-folder/subsystem.c

#include "timestwo_sf.h"

#include "ex_slfunc_comp_sf.h"
#include "ex_slfunc_comp_sf_private.h"

void timestwo_sf(real_T rtu_x, real_T *rty_y)
{
  *rty_y = 2.0 * rtu_x;
}

Simulink Function ブロック

Simulink 関数の呼び出し元は、Simulink Function ブロックで定義された関数を呼び出します。モデルまたはチャート階層のいずれかの場所から、次のいずれかのモデル要素を使用して、Simulink Function ブロックで定義された関数を呼び出すことができます。

関数呼び出しモデル要素

codegen-folder/model.c

void ex_slfunc_comp_sf_step(void)
{
  real_T rtb_FunctionCaller1;

timestwo_sf(ex_slfunc_comp_sf_U.In1, &rtb_FunctionCaller1);

ex_slfunc_comp_sf_Y.Out1 = rtb_FunctionCaller1;
.
.
.

Function Caller ブロック

codegen-folder/model.c

void ex_slfunc_comp_gf_step(void)
{
  real_T rtb_y1_l;

  timestwo_gf(ex_slfunc_comp_gf_U.In4, &rtb_y1_l);

  ex_slfunc_comp_gf_Y.Out4 = rtb_y1_l;  
  .
  .
  .

Stateflow チャート遷移

codegen-folder/model.c

void ex_slfunc_comp_mf_step(void)
{ 
  real_T rtb_y;
  
  timestwo_mf(ex_slfunc_comp_mf_U.In3, &rtb_y);

  ex_slfunc_comp_mf_Y.Out3 = rtb_y;
  .
  .
  .

MATLAB Function ブロック

モデリングの選択の詳細については、Simulink 関数の概要を参照してください。

関数スコープの指定

Simulink Function ブロックで定義した関数はグローバルまたはスコープ内にすることができます。

  • グローバル---コード ジェネレーターは、モデル コード ファイルとは別のソース ファイルとヘッダー ファイル (function.cfunction.h など) にグローバル関数のコードを配置します。これらの個別のファイルにより、関数コードを関数の呼び出し元間で共有できるようになります。

  • スコープ内---コード ジェネレーターは、モデル コード ファイル (model.cmodel.h) にスコープが設定された関数のコードを配置します。スコープが設定された関数をモデルのコンテキストで呼び出すには、関数の呼び出し元がモデルの階層構造内の関数と同じレベル、または 1 つ以上レベルが下でなければなりません。

    生成されたモデル コードの任意の場所からアクセスできる関数のライブラリを作成するには、各関数をスコープが設定された Simulink Function ブロックとして設定します。スコープが設定された各関数をモデルのルート レベルにあるバーチャル サブシステム内に配置します。

詳細については、スコープ内、グローバル、および端子スコープ内の Simulink Function ブロックの概要を参照してください。

エクスポート関数コードを生成するかどうかの決定

単一の最上位モデル設計で Simulink Function ブロックを使用できますが、関数コードは、スタンドアロンのアトミック コンポーネントとして生成した方が再利用しやすくなります。Embedded Coder を使用している場合は、エクスポート関数モデルのコンテキストで関数を設計できます。

詳細については、外部コード ベースにエクスポートするコンポーネント ソース コードの生成エクスポート関数モデルの概要を参照してください。

関数のコード インターフェイスの構成

Embedded Coder では、Simulink Function ブロックと Function Caller ブロックの関数コード インターフェイスを構成して生成し、生成コードと外部コードの統合を簡略化します。次の関数インターフェイスを構成できます。

  • グローバル Simulink Function ブロック

  • モデルのルート レベルにある、スコープが設定された Simulink Function ブロック

詳細については、Configure Entry-Point Function Interfaces for Simulink Function and Function Caller Blocksを参照してください。

呼び出されない Simulink Function ブロック

Simulink Function ブロックがレートベース モデルで使用され、その関数が呼び出されない場合、コード ジェネレーターは Simulink Function ブロックを定数として扱い、関数のコードを生成しません。たとえば、モデル開発中に、関数を定義する準備ができていても、呼び出し元を特定する準備はできていない場合に発生する可能性があります。

レートベース モデル内でこのようなブロックを特定するには、シミュレーション中にサンプル時間の色を表示します (サンプル時間情報の表示を参照)。既定で、Constant ブロックはマゼンタで表示されます。コード ジェネレーターはシミュレーション時に呼び出されない Simulink Function ブロックを定数と認識するため、これらはマゼンタで表示されます。

要件

  • モデルの階層構造内で、関数名は一意です。コード ジェネレーターで同じ名前の複数の関数が検出されると、エラーが発行されます。いずれかの関数の名前を変更し、slprj フォルダーを削除します。

  • 関数および関数の呼び出し元のシグネチャ (引数と引数のデータ型など) が一致しなければなりません。

    • コード ジェネレーターで最初に関数が検出され、関数呼び出し元のシグネチャが一致しない場合、エラーが発行されます。関数の呼び出し元のシグネチャを変更して Simulink Function ブロックのシグネチャと一致させるか、slprj フォルダーを削除します。

    • コード ジェネレーターで最初に関数の呼び出し元が検出され、関数のシグネチャが一致しない場合、警告メッセージが発行されます。関数または関数の呼び出し元のシグネチャを変更してシグネチャを一致させます。

  • Simulink Function ブロックの定義では、ストレージ クラスを使用して Argument Inport ブロックと Argument Outport ブロックの入力信号と出力信号を定義しないでください。

  • Argument Inport ブロックおよび Argument Outport ブロックをテスト ポイントとして指定しないでください。

  • Argument Inport ブロックと Argument Outport ブロックの入力信号と出力信号のデータ型を Simulink.IntEnumTypeSimulink.AliasType、または Simulink.Bus として指定する場合は、DataScope プロパティを [インポート] または [エクスポート] として設定します。

  • 関数のインターフェイスと関数の呼び出し元は、データ型、実数/複素数、次元、引数の数が一致しなければなりません。

制限

  • Simulink 関数および関数の呼び出し元は MaxStackSize パラメーターに従いません。

  • スコープが設定された Simulink 関数を含むモデルからコードを生成するには、モデルがエクスポート関数モデルでなければなりません。コード ジェネレーターは、スコープが設定された Simulink 関数を含むレートベースのモデルをサポートしません。

  • 参照モデル内で Simulink Function ブロックを使用して、スコープが設定された関数を定義できます。Atomic サブシステムの Function Caller ブロックを使用してその関数を呼び出すエクスポート関数モデルのコードは生成できません。

  • Stateflow チャートから生成されたコードを使用すると、コード ジェネレーターによって Simulink Function ブロックから生成された C++ 関数を呼び出すことができます。生成された C++ 関数の現在のスコープ制限により、それらの関数を Function Caller ブロックから生成されたコードで呼び出さなければなりません。

  • C++ クラス インターフェイスのコード生成では、スコープが設定された Simulink 関数のみサポートします。

Simulink Function と Function Caller のコードの生成

この例では、Simulink Function ブロックと Function Caller ブロックの C コードを生成する方法と、関連の生成コードを表示する方法を示します。

モデル例 SimulinkFunctionsTestHarness を開きます。このモデルは Stateflow ソフトウェアを使用しますが、この例では参照モデルから生成されたコードのみを確認します。

open_system('SimulinkFunctionsTestHarness')

関数定義のコードの生成

モデル SimulinkFunctions を開きます。Simulink Function ブロックは y = f3(u) として定義される f3 サブシステムです。

open_system('SimulinkFunctions')

コードを生成します。コード ジェネレーターにより SimulinkFunctions.c が作成されます。このファイルには関数の初期化コードと関数定義が含まれます。

関数 f3 の初期化コード:

void SimulinkFunctions_initialize(void)
{
  rtDWork.Delay_DSTATE = 1;
}

関数 f3 のコード:

void f3(real_T rtu_u, real_T *rty_y)
{
  int8_T = rtb_Gain;

  rtY.TicToc10 = rtDWork.Delay_DSTATE;

  rtb_Gain = (int8_T)(int32_T)-(int32_T)rtY.TicToc10;

  adder(rtB.Subtract, rtU.U2, rtu_u, &rtB.FunctionCaller);

  *rty_y = rtB.FunctionCaller;

  rtDWork.Delay_DSTATE = rtb_Gain;
}

static void adder(real_T rtu_u1, real_T rtu_u2, real_T rtu_u3, real_T *rty_y)
{
  *rty_y = (rtu_u1 + rtu_u2) + rtu_u3;
}

共有ヘッダー ファイル f3.h には、関数 f3 のエントリ ポイント宣言が含まれます。

#include "rtwtypes.h"

extern void f3(real_T rtu_u, real_T *rty_y);

Function Caller のコードの生成

モデル SimulinFunctionCaller を開いて、呼び出し元のサブシステムの内容を表示します。

open_system('SimulinkFunctionCaller')

コードを生成します。コード ジェネレーターによりフォルダー SimulinkFunctionCaller_ert_rtw にファイル SimulinkFunctionCaller.hSimulinkFunctionCaller.c が作成されます。

SimulinkFunctionCaller.h には、関数のエントリポイント宣言を含む共有ヘッダー ファイル f3.h が含まれます。

SimulinkFunctionCaller.c は関数 f3 を呼び出します。

void f3_caller(void)
{
  rtY.y = f3(rtu_u);
}

詳細

参考

|

関連するトピック