Main Content

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

生成されたコードでの信号、状態、パラメーター データの初期化

モデル内の信号線、ブロック パラメーター、ブロックの状態は、生成されたコード内でグローバル変数などのデータとして表示されます。既定の設定では、コードはプライマリ アルゴリズムの実行前にこのデータを初期化します。Simulink® でのシミュレーションの数値と一致させるために、コード ジェネレーターはモデルで作成した仕様に基づいて初期値を選択します。

生成されたコードがデータを初期化する方法を理解すると、次を行うことができます。

  • 実行中に状態を再初期化するシステムをモデル化する。つまり、アプリケーションでシステム全体を再起動できる。

  • 初期値を変数としてメモリに保存する。これは、実行間で維持できる。これらの値はシステムを起動または再起動する前に上書きできる。

  • 不変な初期値のストレージを削除し、不必要または重複してデータを初期化するコードの生成を回避することで、効率的にコードを生成できる。

モデル内の信号および状態の初期化に関する基本的な情報については、信号と離散状態の初期化を参照してください。

静的初期化と動的初期化

グローバル変数などのデータ項目を初期化するために、アプリケーションは静的または動的な初期化を使用できます。

  • 静的初期化は変数を定義する (メモリを割り当てる) 同じステートメントで発生します。初期化は関数定義内では発生しません。

    生成されたモデル関数では初期化ステートメントが実行されないため、コードの効率を上げることができます。

  • 動的初期化は関数内で発生します。各モデルまたは非バーチャル サブシステムの場合、コード ジェネレーターは通常、初期化専用の 1 つ以上の関数を作成します。

    生成されたコードまたはコードは実行中に初期化関数を呼び出し、システムを再起動できます。

非ゼロのビット パターンが必要な実際のグラウンドの初期化

各データ項目には実際の "グラウンド値" があります。この値は項目のデータ型によって異なる場合があります。たとえば、データ型が double または int8 の信号の場合、実際のグラウンド値はゼロになります。列挙の場合、グラウンド値は既定の列挙メンバーになります。

データの種類によっては、実際のグラウンド値を表すためにコンピューターはゼロをメモリに保存します (すべてのビットがゼロ)。ただし、その他のデータによっては、コンピューターは非ゼロ値をメモリに保存します。このデータには、たとえば次が含まれます。

  • バイアスを併用する固定小数点データ。コードは、指定したスケーリングとバイアスを使用して実際のゼロを表す保存された整数値にこのようなデータ項目を初期化します。

  • 既定のメンバーをゼロ以外の整数値にマッピングする列挙。たとえば、既定のメンバーが基となる整数値 3 を使用する High の場合、コードはこのようなデータ項目を High に初期化します。

信号と状態データの初期化

モデル内では、ブロック パラメーターを使用して信号と状態データの値を制御できます。たとえば、Unit Delay ブロックの初期値を設定するには、[初期条件] パラメーターを使用します。場合によっては、Simulink.Signal オブジェクトの InitialValue プロパティを使用することもできます。これらのブロック パラメーターのほとんどにおいて、既定値は 0 です。

また、Initialize Function サブシステム内の State Writer ブロックと [初期状態] モデル コンフィギュレーション パラメーターを使用して状態を初期化することもできます。

既定の設定では、生成されたコードは信号と状態データ (およびモデルのエラー ステータスなどのその他のデータ) を生成された初期化関数内で動的に初期化します。既定で model_initialize という名前のこの関数は、信号と状態の初期化操作を次の順序で実行します。

  1. DWork 構造体などの生成された既定の構造体内にある信号と状態データを、保存されたゼロの値に初期化します。

  2. 生成された既定の構造体内にない追加の信号と状態データを関連する実際のグラウンド値に初期化します。

    この初期化は次の両方の条件を満たすデータに対してのみ適用されます。

    • 生成されたコードはデータを定義する (メモリを割り当てる)。

    • データは Auto (既定のストレージ クラス) または Model default 以外のストレージ クラスを使用します (コード マッピング エディターで [既定] ストレージ クラスを指定する場合は、既定の設定)。

    たとえば、コードはこの操作をストレージ クラス ExportedGlobal を使用するデータ項目に適用します。

  3. たとえば Unit Delay ブロックの [初期条件] パラメーターを使用して、モデルが指定する実際値に各信号と状態を初期化します。

  4. State Writer ブロックを使用して代入する実際値に各状態を初期化します。この関数は、Initialize Function サブシステムをモデル内で使用する場合にのみこの初期化を実行します。

  5. コンフィギュレーション パラメーターの [初期状態] で指定する実際値に各状態を初期化します。

この初期化関数を実行すると、関数が代入した最後の実際値が各データ項目に追加されます。たとえば、State Writer ブロックを使用してブロックの状態を 5 に初期化し、同時に [初期状態] コンフィギュレーション パラメーターを使用して同じ状態を 10 に初期化すると、状態は最終的に 10 を初期値として使用します。

一括初期化用の memset

連続するストレージをもつ信号または状態のデータ項目を保存されたゼロの値に初期化するために、生成されたコードで初期化変数に memset を呼び出すことができます。連続するストレージをもつデータ項目には DWork 構造体、配列またはマルチワード データ型を使用するデータ項目が含まれます。

アプリケーションで必要な場合は、生成されたコードが memset を使用して浮動小数点データ型を保存されたゼロに初期化するのを回避できます。float と double を 0.0 に初期化するために memset を使用を参照してください。

調整可能な初期値

Gain ブロックの [ゲイン] パラメーターなど、調整可能なブロック パラメーターが生成されたコードに表示される方法を設定できます。初期値を設定するほとんどのブロック パラメーター ([初期条件] など) は調整可能です。たとえば、コンフィギュレーション パラメーターの [既定のパラメーター動作] では、生成されたコード内で初期値をインライン化された定数または調整可能なグローバル データのどちらとして表示するかを決定できます。また、パラメーター オブジェクトとストレージ クラスを使用してこれらの初期値の表現を制御できます。

調整可能な初期値の場合、モデル初期化関数では代入ステートメントの右側がグローバル変数、構造体フィールドまたはメモリ内で変更可能な値をもつその他のデータになります。

生成されたコード内で初期値を調整可能にする方法の詳細については、生成されたコードにおける信号および状態の初期化の制御を参照してください。

パラメーター データの初期化

生成されたコードは、パラメーター データを Simulink で指定した値に静的に初期化します。

調整可能なパラメーター (グローバル変数) の初期値をシステム定数または他のマクロを伴う数式として表す場合は (Embedded Coder® を必要とします)、数式による初期化 (Embedded Coder)を参照してください。

パラメーター データの種類

次のモデル要素は生成されたコード内でパラメーター データとして表示されます。

  • [既定のパラメーター動作][調整可能] に設定した場合の Gain ブロックの [ゲイン] パラメーターなどの調整可能なブロック パラメーター。各パラメーターは専用のグローバル構造体のフィールドとして表示されます。

  • [既定のパラメーター動作][インライン] に設定した場合の調整可能な一部のブロック パラメーター。コード ジェネレーターがパラメーターの値を数値リテラルとしてインライン化できない場合、パラメーターは専用のグローバルな const 構造体のフィールドとして表示されます。

  • エクスポートされたデータ スコープをもつストレージ クラスを適用する Simulink.Parameter オブジェクト。たとえば、組み込みストレージ クラス ExportedGlobal にはエクスポートされたデータ スコープがありますが、ストレージ クラス ImportedExtern にはありません。

数式による初期化 (Embedded Coder)

パラメーター オブジェクト (Simulink.Parameter など) の値を、数値、MATLAB® 変数、他のパラメーター オブジェクトを伴う数式に設定できます。数式を使用した変数値の設定を参照してください。

この手法を Embedded Coder で使用する場合、指定した式を使用して、対応するパラメーター データ (グローバル変数) を初期化するコードを生成できます。例については、システム定数または他のマクロからのパラメーター値の初期化 (Embedded Coder)を参照してください。制限など、一般情報については、式の値を使用したパラメーター オブジェクトのコード生成を参照してください。

生成されたコードでのデータの初期化

この例では、生成されたコードが信号、状態、パラメーター データを初期化する方法を示します。

モデル例の確認

モデル例 CounterModel を開き、grt.tlc システム ターゲット ファイルを使用するようにモデルを構成します。

open_system('CounterModel')
set_param('CounterModel', 'SystemTargetFile', 'grt.tlc');

アプリ ギャラリーで [Simulink Coder] をクリックします。

モデル データ エディターを開きます。[モデル化] タブで [モデル データ エディター] をクリックします。

[状態] タブを検査します。Unit Delay ブロックの状態について、[初期値] は既定で 0 に設定されます。つまり、状態の初期値はゼロです。状態の名前は X です。

[初期値]5 などの非ゼロの数値に設定します。

set_param('CounterModel/X','InitialCondition','5')

コード マッピング エディターを開きます。[C コード] タブで、[コード インターフェイス]、[個々の要素コードのマッピング] を選択します。

[信号/状態] タブの [状態] で、X[ストレージ クラス]ExportedGlobal に設定します。この設定により、ブロックの状態が独立したグローバル変数として生成されたコードに現れます。

coder.mapping.utils.create('CounterModel');
cm = coder.mapping.api.get('CounterModel');
setState(cm,'CounterModel/X','StorageClass','ExportedGlobal');

モデルで、Triggered Subsystem である Amplifier サブシステムを開きます。

モデル データ エディターで、[パラメーター] タブを検査します。信号および状態の初期値の設定および確認のために、[状態] タブではなく [パラメーター] タブを使用できます。

Outport ブロックの [初期出力] (InitialOutput) パラメーターが既定値の 0 に設定されていることがモデル データ エディターに表示されます。このサブシステムは条件付きで実行されるため、このサブシステムの出力には初期値が必要です。初期値は既定のままにします。

モデルで、[コンフィギュレーション パラメーター]、[信号ストレージの再利用] をオフにします。この設定をオフにすると、信号データを保存する目的で生成された構造体のフィールドとして、信号線が生成されたコードに表示されます。この信号の表現により、コード ジェネレーターでデータが初期化される方法を確認しやすくなります。

set_param('CounterModel','OptimizeBlockIOStorage','off')

モデルで、コンフィギュレーション パラメーター ([コンフィギュレーション パラメーター]、[最適化]、[既定のパラメーター動作]) を検証します。コンフィギュレーション パラメーターは Inlined に設定されています。つまり、初期値を含むブロック パラメーターは、インライン化されたリテラルまたは const データとして生成されたコードに現れます。

モデルのルート レベルに移動します。

モデル データ エディターで [追加情報の表示/更新] ボタンをクリックします。

[コンテンツのフィルター] ボックスの近くの [選択を使用してフィルター処理します] ボタンをクリックします。

モデルで INC というラベルの Constant ブロックをクリックします。このブロックの [定数値] (Value) パラメーターは INC に設定されていることがモデル データ エディターで表示されます。INC はベース ワークスペース内の MATLAB 変数です。

INC について、[値] 列の値を Simulink.Parameter(uint8(1)) に設定します。MATLAB によって INCSimulink.Parameter オブジェクトに変換されます。

コード マッピング エディターの [パラメーター] タブで、ストレージ クラス ExportedGlobalINC に適用します。この設定により、生成されたコードでは INC がグローバル変数として定義されます。初期化の場合、INC はパラメーター データの項目です。

INC = Simulink.Parameter(INC);
INC.StorageClass = 'ExportedGlobal';

コードの生成と検査

モデルをビルドしてコードを生成するには、Ctrl+B を押します。

slbuild('CounterModel');
### Starting build procedure for: CounterModel
### Successful completion of build procedure for: CounterModel

Build Summary

Top model targets built:

Model         Action                        Rebuild Reason                                    
==============================================================================================
CounterModel  Code generated and compiled.  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 16.783s

生成されたファイル CounterModel.c のコードでは、関数定義の外でパラメーター データ INC が静的に初期化されています。INC の値は 1 です。

file = fullfile('CounterModel_grt_rtw','CounterModel.c');
coder.example.extractLines(file,'/* Exported block parameters */','uint8_T INC = 1U;',1,1)
/* Exported block parameters */
uint8_T INC = 1U;                      /* Variable: INC

同じファイル内で関数 CounterModel_initialize の定義を検証します。最初に、この関数は memset を使用して、モデル内の内部信号を保存された 0 の値に初期化します。

coder.example.extractLines(file,'/* block I/O */','sizeof(B_CounterModel_T));',1,1)
  /* block I/O */
  (void) memset(((void *) &CounterModel_B), 0,
                sizeof(B_CounterModel_T));

次に、関数は Unit Delay の状態 X をグラウンド値に初期化します。この場合、グラウンド値はゼロです。

coder.example.extractLines(file,'/* exported global states */','X = 0U;',1,1)
  /* exported global states */
  X = 0U;

また、この関数はルートレベルの入出力 (Inport ブロックと Outport ブロック) を含めたその他のデータもグラウンド値に初期化します。

coder.example.extractLines(file,'/* external inputs */','Amplifier_Trig_ZCE = POS_ZCSIG;',1,1)
  /* external inputs */
  CounterModel_U.Input = 0;

  /* external outputs */
  CounterModel_Y.Output = 0;

  /* Matfile logging */
  rt_StartDataLoggingWithStartTime(CounterModel_M->rtwLogInfo, 0.0, rtmGetTFinal
    (CounterModel_M), CounterModel_M->Timing.stepSize0, (&rtmGetErrorStatus
    (CounterModel_M)));
  CounterModel_PrevZCX.Amplifier_Trig_ZCE = POS_ZCSIG;

次に、関数は X[初期条件] ブロック パラメーターで指定した値に初期化します。

coder.example.extractLines(file,'/* InitializeConditions for UnitDelay: ''<Root>/X'' */',...
    'X = 5U;',1,1)
  /* InitializeConditions for UnitDelay: '<Root>/X' */
  X = 5U;

最後に、関数は Amplifier サブシステムの出力を初期化します。

coder.example.extractLines(file,'SystemInitialize for Triggered SubSystem',...
    'End of SystemInitialize for SubSystem',1,1)
  /* SystemInitialize for Triggered SubSystem: '<Root>/Amplifier' */
  /* SystemInitialize for Outport: '<Root>/Output' incorporates:
   *  Outport: '<S1>/Out'
   */
  CounterModel_Y.Output = 0;

保存された値と実際値との違いの検証

一部のデータでは、実際の初期値がゼロであってもコンピューターのメモリに非ゼロの値が保存されます。この違いを確認するには、勾配とバイアスでスケーリングされた固定小数点データ型をブロックの状態 X に適用します。この例を実行するには、Fixed-Point Designer™ が必要です。

モデル データ エディターで、[信号] タブを検査します。

モデルで、Switch ブロック switch_out の出力信号をクリックします。

モデル データ エディターの [データ型] 列を使用して、信号のデータ型を fixdt(1,16,1,3) に設定します。この式は 1 の勾配と 3 のバイアスをもつ固定小数点データ型を表します。

set_param('CounterModel/Switch','OutDataTypeStr',...
    'fixdt(1,16,1,3)')

モデルで、Sum ブロックを選択します。プロパティ インスペクターで、[信号属性] の下の [すべての入力が同じデータ型をもつ] をオフにします。

set_param('CounterModel/Sum','InputSameDT','off')

異なるプラットフォームでコンパイル エラーを回避するには、モデル コンフィギュレーション パラメーターの [コード生成のみ] を選択します。この設定により、モデルで生成されるのはコードのみになります。

set_param('CounterModel','GenCodeOnly','on')

モデルをビルドしてコードを生成するには、Ctrl+B を押します。

slbuild('CounterModel')
### Starting build procedure for: CounterModel
### Successful completion of code generation for: CounterModel

Build Summary

Top model targets built:

Model         Action           Rebuild Reason                   
================================================================
CounterModel  Code generated.  Generated code was out of date.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 10.133s

モデル初期化関数は、最初に X を実際のグラウンド値 0 に初期化します。バイアス 3 をもつ勾配とバイアスでスケーリングされたデータ型により、この実際値は保存された -3 の値に対応します。

coder.example.extractLines(file,'/* exported global states */','X = -3;',1,1)
  /* exported global states */
  X = -3;

次に、関数は X[初期条件] ブロック パラメーターで指定した実際の初期値である 5 に初期化します。この実際値は保存された 2 の値に対応します。

coder.example.extractLines(file,'/* InitializeConditions for UnitDelay: ''<Root>/X'' */',...
    'X = 2;',1,1)
  /* InitializeConditions for UnitDelay: '<Root>/X' */
  X = 2;

モデル化の目的

目的詳細
ブロックを使用した初期化動作の明示的なモデル化

Initialize Function サブシステムと Reset Function サブシステムを使用して初期化とリセット動作を明示的にモデル化できます。サブシステムで State Writer ブロックを使用し、初期値を計算して状態に動的に代入します。対応するコードがモデル初期化関数に表示されます。

詳細については、起動、リセット、シャットダウン関数インターフェイスを参照してください。

明示的にデータをゼロに初期化するコード生成の防止

アプリケーション環境で既にグローバル変数をゼロに初期化している場合は、コードをより効率的にするため、グローバル変数を明示的にゼロに初期化するステートメントの生成を防ぐことができます。この最適化はメモリにゼロとして保存されている初期値をもつ信号と状態に対してのみ適用されます。たとえば、コード ジェネレーターは以下に対して最適化を適用しません。

  • ブロック パラメーターを使用して非ゼロの初期値を指定するデータ。

  • 実際値はゼロでも、対応する保存された値がゼロではないデータ。

  • 既定のメンバーが非ゼロの整数にマッピングされる列挙型データ。

最適化には Embedded Coder が必要です。詳細については、Remove Zero-Initialization Codeを参照してください。

外部コードからデータをインポートするコードの生成

外部コードが定義するデータを再利用 (インポート) するコードを生成できます。たとえば、ストレージ クラス ImportedExtern を信号線、ブロックの状態、パラメーター オブジェクトに適用できます。インポートしたデータには以下が適用されます。

  • 生成されたコードはパラメーター データを初期化しない。インポートしたパラメーター データはコードで初期化しなければなりません。

  • 生成した初期化関数は一部の信号と状態データを動的に初期化する。生成されたコードによって割り当てられるデータとは異なり、コードは、インポートした信号または状態データを保存されたゼロの値に初期化しません。その代わり、コードはデータを Simulink で指定した実際値にすぐに初期化します。

生成されたコードによるインポート データの初期化を回避する方法など、詳細については、外部の呼び出しコードと生成コード間のデータ交換を参照してください。

参考

関連するトピック