Main Content

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

カスタマイズされた非同期ライブラリの作成

このトピックでは、Async Interrupt ブロックと Task Sync ブロックを開始点として使用して、ターゲット RTOS で使用する非同期ブロックを実装する方法について説明します。Rate Transition ブロックはターゲットから独立するブロックであるため、カスタマイズされたレート変換ブロックを作成する必要はありません。

メモ

このトピックに示されているオペレーティング システムの統合手法では、Interrupt Templates ブロック ライブラリのブロックを使用します。そのライブラリのブロックは、特定のターゲット環境でカスタム ブロックを開発するのに役立つ例となります。

非同期ブロックの実装について

非同期ライブラリ ブロックをカスタマイズするには、ブロックの実装を変更します。次のファイルが対象です。

  • ブロックの元になっている S-Function MEX ファイル

  • ブロックのコード生成を制御する TLC ファイル

また、ブロック マスクを変更して、RTOS 例 (VxWorks®) 固有の参照を削除し、ターゲット RTOS によって要求されたパラメーターを組み込む必要があります。

カスタム ブロックの実装は、最新のトピックで、Simulink® MEX S-Function 形式と API および Target Language Compiler (TLC) について熟知している必要があります。これらのトピックは、次のドキュメントで説明します。

以下の節では、TLC 非同期サポート ライブラリ (asynclib.tlc) の必須 SimStruct マクロおよび関数を含む非同期ライブラリ ブロックの C/C++ および TLC の実装について説明します。

Async Interrupt ブロックの実装

Async Interrupt ブロックのソース ファイルは、matlabroot/rtw/c/tornado/devices (開く) にあります。

  • vxinterrupt1.c:C MEX ファイル ソース コード。構成とシミュレーションに使用します。

  • vxinterrupt1.tlc:TLC 実装。コード生成に使用します。

  • asynclib.tlc: TLC サポート関数のライブラリ。ブロックの TLC 実装によって呼び出されます。このライブラリ呼び出しについては、asynclib.tlc サポート ライブラリを参照してください。

C MEX ブロックの実装

vxinterrupt1.c のほとんどのコードは、非同期サポートと無関係な通常の関数を実行します (たとえば、ブロック マスクからパラメーターを取得して検証し、パラメーターを調整できないようにマークを付け、パラメーター データを model.rtw ファイルに渡します)。

関数 mdlInitializeSizes は、以下で説明するように、非同期ブロックに必要な特殊な SimStruct マクロと SS_OPTIONS 設定を使用します。

次のマクロは、関数 ssSetOutputPortWidth を呼び出す前に呼び出すことはできません。

  • ssSetTimeSource

  • ssSetAsyncTimerAttributes

  • ssSetAsyncTimerResolutionEl

  • ssSetAsyncTimerDataType

  • ssSetAsyncTimerDataTypeEl

  • ssSetAsyncTaskPriorities

  • ssSetAsyncTaskPrioritiesEl

上記のマクロのいずれかが関数 ssSetOutputPortWidth の前に呼び出された場合、次のエラー メッセージが表示されます。

SL_SfcnMustSpecifyPortWidthBfCallSomeMacro {  
S-function '%s' in '%<BLOCKFULLPATH>'
must set output port %d width using
ssSetOutputPortWidth before calling macro %s
 }

ssSetAsyncTimerAttributes.  ssSetAsyncTimerAttributes は、ブロックでタイマーが必要なことを宣言し、ブロック パラメーター [タイマー分解能 (秒)] の指定に従い、タイマーの分解能を設定します。

関数のプロトタイプは次のとおりです。

ssSetAsyncTimerAttributes(SimStruct *S, double res)

ここで

  • S は、Simstruct ポインターです。

  • パラメーター [タイマー分解能 (秒)]res に設定します。

次のコード例は、ssSetAsyncTimerAttributes の呼び出しを示しています。

/* Setup Async Timer attributes */
ssSetAsyncTimerAttributes(S,mxGetPr(TICK_RES)[0]);

ssSetAsyncTaskPriorities.  ssSetAsyncTaskPriorities は、ブロック パラメーター [Simulink タスクの優先順位] に指定された、各割り込みレベルで実行するブロックの Simulink タスクの優先順位を設定します。

関数のプロトタイプは次のとおりです。

ssSetAsyncTaskPriorities(SimStruct *S, int numISRs, 
                         int *priorityArray)

ここで

  • S は、SimStruct ポインターです。

  • numISRs はブロック パラメーター [VME 割り込み番号] に指定された割り込みの数です。

  • priorityarray はブロック パラメーター [VME 割り込み番号] で指定された割り込み数を含んでいる整数配列です。

次のコード例は、関数 ssSetAsyncTaskPriorities の呼び出しを示しています。

/* Setup Async Task Priorities */
    priorityArray = malloc(numISRs*sizeof(int_T));
    for (i=0; i<numISRs; i++) {
        priorityArray[i] = (int_T)(mxGetPr(ISR_PRIORITIES)[i]);
    }
    ssSetAsyncTaskPriorities(S, numISRs, priorityArray); 
    free(priorityArray);
    priorityArray = NULL;
}

SS_OPTION の設定.  以下のコード例は、vxinterrupt1.cSS_OPTION 設定を示しています。Function-Call Subsystem が割り込みに接続されている場合、SS_OPTION_ASYNCHRONOUS_INTERRUPT を使用しなければなりません。詳細については、matlabroot/simulink/include/simstruc.hSS_OPTION および SS_OPTION_ASYNCHRONOUS のドキュメンテーションを参照してください。

ssSetOptions( S, (SS_OPTION_EXCEPTION_FREE_CODE |
              SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME |
              SS_OPTION_ASYNCHRONOUS_INTERRUPT));

S-Function で SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME オプションを指定し、Inf のサンプル時間を継承すると、コード ジェネレーターは、ブロックが不変かどうかに基づいてブロックのコードを生成する方法を決めます。端子信号が不変である場合、ブロックは不変です。シミュレーション全体においてブロックに定数値がある場合、信号は不変です。Constant ブロックのサンプル時間を指定する場合は、端子信号が不変であると想定しないでください。詳細については、インライン不変信号を参照してください。ブロックが不変でない場合、コード ジェネレーターは、エントリポイント関数の初期化でのみコードを生成します。ブロックが不変の場合、コード ジェネレーターはブロックのコードを生成しません。

TLC 実装

この節では、ターゲット RTOS のコードを生成するために変更する必要があるターゲット固有の特徴に重点を置きながら、vxinterrupt1.tlc の各関数について説明します。

#include 命令の生成.  vxinterrupt1.tlc begins with the statement

%include "vxlib.tlc"

vxlib.tlc は、RTOS 例 (VxWorks) のヘッダー ファイルを含めるという命令を生成するターゲット固有のファイルです。このファイルは、ターゲット RTOS のインクルード機能を生成するファイルと置き換えなければなりません。

関数 BlockInstanceSetup.  関数 BlockInstanceSetup は、接続された Async Interrupt ブロックの出力ごとに、生成コードの対応する ISR の関数名を定義します。関数名は次の形式になります。

isr_num_vec_offset

ここで、num はブロック パラメーター [VME 割り込み番号] で定義された ISR 数で、offset はブロック パラメーター [VME 割り込みベクトル オフセット] で定義された割り込みテーブル オフセットです。

カスタム実装の場合、必ずしもこの規則に従って名前を付ける必要はありません。

関数名は、関数 Outputs によって使用される場合はキャッシュされ、実際の ISR コードを生成します。

関数 Outputs.  関数 Outputs は、接続されている Async Interrupt ブロックの出力を反復します。ISR は、このような出力ごとに生成されます。

ISR コードは、生成コードの "Functions" セクションでキャッシュされます。関数 Outputs は、ISR の生成前に次の処理を実行します。

  • 下流ブロックの呼び出し (一時的なバッファーにキャッシュされます) を生成します。

  • ISR をロックする必要があるかどうかを決定します (ブロック パラメーター [プリエンプション フラグ] で指定)。

  • Async Interrupt ブロックに接続されているブロックが Task Sync ブロックかどうかを特定します (この情報は、asynclib 呼び出し (関数 LibGetFcnCallBlock および関数 LibGetBlockAttribute) を使用して取得します)。このとき、以下のようになります。

    • ISR のプリエンプション フラグは、1 に設定されなければなりません。それ以外の場合、エラーになります。

    • 整数のみのコード生成のモデルが設定されていない場合、浮動小数点コンテキストを保存および復元する RTOS (VxWorks) 呼び出しが生成されます。

ISR コードを生成すると、関数 Outputs によって asynclib 関数 LibNeedAsyncCounter が呼び出され、接続されているサブシステムによってタイマーが要求されます。このとき、時間ソースが関数 ssSetTimeSource によって SS_TIMESOURCE_SELF に設定されている場合、関数 LibSetAsyncCounter が呼び出され、RTOS (VxWorks) 関数 tickGet 呼び出しが生成され、カウンターが更新されます。実装時、ターゲット RTOS と同等の呼び出しを生成するか、コードを生成して、ターゲット ハードウェアのタイマー レジスタを読み取ります。

関数 Start.  関数 Start は、各 ISR に接続して有効にするために必要な RTOS (VxWorks) 呼び出し (int_connect および sysInt_Enable) を生成します。この呼び出しは、ターゲット RTOS の呼び出しと置き換えなければなりません。

関数 Terminate.  関数 Terminate は、各 ISR を無効にするための呼び出し sysIntDisable を生成します。この呼び出しは、ターゲット RTOS の呼び出しと置き換えなければなりません。

Task Sync ブロックの実装

Task Sync ブロックのソース ファイルは、matlabroot/rtw/c/tornado/devices (開く) にあります。内容は以下のとおりです。

  • vxtask1.cpp:MEX ファイル ソース コード。構成とシミュレーションに使用します。

  • vxtask1.tlc:TLC 実装。コード生成に使用します。

  • asynclib.tlc: TLC サポート関数のライブラリ。ブロックの TLC 実装によって呼び出されます。このライブラリ呼び出しについては、asynclib.tlc サポート ライブラリを参照してください。

C MEX ブロックの実装

Task Sync ブロックは、Async Interrupt ブロックと同様に、タイマーを設定します (この場合、固定分解能)。このブロックに関連付けられたタスクの優先順位は、ブロック パラメーター [Simulink タスクの優先順位] から取得されます。SS_OPTION 設定は、Async Interrupt ブロックに使用される設定と同じです。

ssSetAsyncTimerAttributes(S, 0.01);

priority  = (int_T) (*(mxGetPr(PRIORITY)));
ssSetAsyncTaskPriorities(S,1,&priority);

ssSetOptions(S, (SS_OPTION_EXCEPTION_FREE_CODE |
                 SS_OPTION_ASYNCHRONOUS |
                 SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME));
}

TLC 実装

#include 命令の生成.  vxtask1.tlc begins with the statement

%include "vxlib.tlc"

vxlib.tlc は、RTOS 例 (VxWorks) のヘッダー ファイルを含めるという命令を生成するターゲット固有のファイルです。このファイルは、ターゲット RTOS のインクルード機能を生成するファイルと置き換えなければなりません。

関数 BlockInstanceSetup.  関数 BlockInstanceSetup は、後でコード生成に使用するタスク名、ブロック名および他の識別子を導出します。また、未接続のブロックの条件をチェックして、警告を生成し、割り込みオーバーフロー条件で使用されるセマフォ (stopSem) のストレージ宣言を生成します。

関数 Start.  関数 Start は、Task Sync ブロックによって発生したタスクの管理に使用されるセマフォのストレージを定義するために必要な RTOS (VxWorks) 呼び出しを生成します。ターゲットの CodeFormat TLC 変数の値に応じて、静的なストレージ宣言または動的メモリ割り当て呼び出しが生成されます。また、この関数によって、セマフォ (semBCreate) が作成され、RTOS タスク (taskSpawn) が発生します。これらの呼び出しは、ターゲット RTOS の呼び出しで置き換えなければなりません。

関数 Outputs.  関数 Outputs は、セマフォを待機する RTOS 例 (VxWorks) タスクを生成します。この関数は、セマフォを取得すると、ブロックのタイマー目盛りを更新し、下流のサブシステム コードを呼び出します。また、関数 Outputs でも、セマフォを許可するコード (割り込みレベルから呼び出されます) を生成します。

関数 Terminate.  関数 Terminate は、RTOS 例 (VxWorks) 呼び出し taskDelete を生成して、ブロックによって発生したタスクの実行を終了します。この呼び出しは、ターゲット RTOS の呼び出しと置き換えなければなりません。

また、ターゲット RTOS によってタスクに関連付けられたメモリが動的に割り当てられている場合、関数 Terminate はメモリの割り当てを解除します。

asynclib.tlc サポート ライブラリ

asynclib.tlc は、非同期ブロックの実装をサポートする TLC 関数のライブラリです。一部の関数は、非同期ブロック専用に設計されています。たとえば、関数 LibSetAsyncCounter は、非同期ブロックのタイマーを更新する呼び出しを生成します。また、別の関数は、非同期ブロックによって要求された情報 (接続された Function-Call Subsystem の情報など) を返すユーティリティです。

次の表は、ライブラリのパブリックな呼び出しをまとめたものです。詳細は、ライブラリ ソース コードと、ライブラリ関数を呼び出す vxinterrupt1.tlc ファイルおよび vxtask1.tlc ファイルを参照してください。

asynclib.tlc ライブラリ関数のまとめ

関数

説明

LibBlockExecuteFcnCall

関数呼び出し出力をもつインライン S-Function によって使用されます。Function-Call Subsystem を実行するコードを生成します。

LibGetBlockAttribute

ブロック レコードのフィールド値を返します。

LibGetFcnCallBlock

S-Function ブロックと呼び出しインデックスが指定されている場合、下流の Function-Call Subsystem ブロックのブロック レコードを返します。

LibGetCallerClockTickCounter

上流の非同期タスクの時間カウンターへのアクセスを可能にします。

LibGetCallerClockTickCounterHighWord

上流の非同期タスクの時間カウンターの上位ワードへのアクセスを可能にします。

LibManageAsyncCounter

非同期タスクがカウンターを必要とし、独自のタイマーを管理するかどうかを決定します。

LibNeedAsyncCounter

呼び出し側のブロックは、非同期カウンターが必要な場合、TLC_TRUE を返します。それ以外の場合、TLC_FALSE を返します。

LibSetAsyncClockTicks

非同期タスクによって維持される clockTick カウンターを設定するコードを返します。

LibSetAsyncCounter

ブロックの非同期カウンターの目盛り値を設定するコードを生成します。

LibSetAsyncCounterHighWord

ブロックの非同期カウンターの上位ワードの目盛り値を設定するコードを生成します。

関連するトピック