割り込みサービス ルーチンの生成
RTOS 例 (たとえば VxWorks®) の特定の VME 割り込みレベルに関連付けられている割り込みサービス ルーチン (ISR) を生成するには、Async Interrupt ブロックを使用します。Async Interrupt ブロックは、指定した割り込みレベルを有効にし、接続されている Function-Call Subsystem を呼び出す ISR をインストールします。
シミュレーション時に Async Interrupt ブロックを使うこともできます。これにより、有効化して、シミュレーション対象の割り込みソースに接続できる入力端子を提供できます。
メモ
この節に示されているオペレーティング システムの統合手法では、Interrupt Templates ブロック ライブラリのブロックを使用します。そのライブラリのブロックは、ターゲット環境でカスタム ブロックを開発するのに役立つ開始点の例を提供します。
Async Interrupt ブロックの接続
ISR を生成するには、Async Interrupt ブロックの出力を以下の制御入力に接続します。
Function Call Subsystem
Task Sync ブロックの入力
関数呼び出し入力イベントについて設定された Stateflow® チャートへの入力
モデル例 rtwdemo_async
は、2 つの割り込みソースを有効にするように設定された Async Interrupt ブロックを示しています。2 つの出力信号がそれぞれ Function-Call Subsystem に接続されています。
要件と制限
Async Interrupt ブロックは VME 割り込みの 1 から 7 までをサポートします。
Async Interrupt ブロックでは、次に示す RTOS 例 (VxWorks) のシステム呼び出しを使用します。
sysIntEnable
sysIntDisable
intConnect
intLock
intUnlock
tickGet
パフォーマンスについて
割り込みレベルで大規模なサブシステムが実行されると、システム内で優先度が同じか、低い割り込みの割り込み応答時間に大きく影響します。ISR はできるだけ短くすることを推奨します。ブロック数が少ない Function-Call Subsystem のみを Async Interrupt ブロックに接続します。
大きなサブシステムの場合は Task Sync ブロックを使用して Function-Call Subsystem の実行を RTOS タスクと同期させることをお勧めします。Async Interrupt ブロックと Function-Call Subsystem の間に Task Sync ブロックを配置します。Async Interrupt ブロックは Task Sync ブロックを ISR としてインストールします。ISR は、同期セマフォをタスクにリリースし (関数 semGive
を実行し)、割り込みレベルからすぐに返されます。タスクは、その後スケジューリングされ、RTOS (VxWorks) によって実行されます。詳細については、RTOS タスクの例の発生と同期を参照してください。
ISR を含むリアルタイム システムを開発するための双対モデル アプローチ
ISR を含むリアルタイム システムの開発時には、"双対モデル" アプローチの使用を検討してください。プラントとシミュレーションのコントローラーを含むモデルと、コード生成のコントローラーのみを含む別のモデルを作成します。Simulink® ライブラリを使用して、2 つのモデルの変更を同時に実装します。次の図は、ライブラリ内のプラントまたはコントローラーの変更がモデルにどのように伝播されるかを示しています。
シミュレーションおよびコード生成のための Async Interrupt ブロックの双対モデルの使用
"単一モデル" アプローチも使用できます。モデルのプラント コンポーネントはシミュレーション中にのみアクティブです。コード生成では、プラント コンポーネントはシステム外に切り替えられ、コードはモデルの割り込みブロックおよびコントローラー部に対してのみ生成されます。
双対モデル アプローチ:シミュレーション
モデル例 rtwdemo_async
は、モデリングに対する双対モデル アプローチを示しています。シミュレーション時、Pulse Generator ブロックによってシミュレートされた割り込み信号が送られます。
シミュレーション中に以下を行います。
入力端子の値が非ゼロの場合、Simulink は、割り込みが発生した場所で、接続先の関数を無条件で呼び出すことにより、各割り込みの動作を模倣します。
Async Interrupt ブロックの出力端子に接続されたサブシステムは、RTOS (この例では VxWorks) の優先度の順序に従って実行されます。2 つ以上の割り込み信号が同時に発生した場合、Async Interrupt ブロックによって、割り込みレベル (レベル 7 が最高の優先順位) で指定された順序で下流のシステムが実行されます。最初の入力要素は最初の出力要素にマッピングされます。
シミュレーション時にシミュレーション入力を有効にせずに Async Interrupt ブロックを使用できます。Async Interrupt ブロックは、モデルの基本レートを継承し、RTOS で優先度の順序で接続されているサブシステムを呼び出します (この場合、Async Interrupt ブロックは、入力が 1
を同時に受信した場合と同様に動作します)。
双対モデル アプローチ:コード生成
モデル例の生成コードでは以下のようになります。
Ground ブロックは Variant Source ブロックに入力信号を送ります。
Async Interrupt ブロックはそのシミュレーション入力を使用しません。
Ground ブロックが Variant Source ブロックの制御入力を駆動するため、コード ジェネレーターはその信号パスについてコードを生成しません。コード ジェネレーターは、Variant Source ブロックへのシミュレーション制御入力を駆動するブロックのコードについては、そのパスがコード生成中に選択されないため、生成しません。ただし、Variant Source ブロックへのシミュレーション入力の駆動ブロックのサンプル時間は、生成されたコードでサポートされるサンプル時間に影響を与えます。生成されたコードに不要なサンプル時間が含まれないようにするには、生成コードの対象のモデルでシミュレーション入力を駆動するブロックのサンプル時間を使用します。
コード ジェネレーターは ISR のスタンドアロン関数を生成します。このときの割り込みベクトル テーブルは次のとおりです。
オフセット | |
---|---|
192 | &isr_num1_vec192() |
193 | &isr_num2_vec193() |
以下の図のように Async Interrupt ブロック パラメーターが設定されているという前提で、このモデルから生成されたコードについて検討します。
初期化コード
コード生成時に Async Interrupt ブロックは、Subsystem ブロックに生成されたコードに、割り込みサービス ルーチンとして割り込みコードをインストールします。IRQ1
および IRQ2
の割り込みベクトルは、[VME 割り込みベクトル オフセット] パラメーターの指定に従い、割り込みベクトル テーブルのベースを基準として 192
および 193
の位置に格納されます。
ISR をインストールする場合、2 つの RTOS (VxWorks) 呼び出し (関数 int_connect
および関数 sysInt_Enable
) が必要です。Async Interrupt ブロックは、次のコード フラグメントで示すように、関数
にこれらの呼び出しを挿入します。model
_initialize
/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Connect and enable ISR function: isr_num1_vec192 */ if( intConnect(INUM_TO_IVEC(192), isr_num1_vec192, 0) != OK) { printf("intConnect failed for ISR 1.\n"); } sysIntEnable(1); /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Connect and enable ISR function: isr_num2_vec193 */ if( intConnect(INUM_TO_IVEC(193), isr_num2_vec193, 0) != OK) { printf("intConnect failed for ISR 2.\n"); } sysIntEnable(2);
Async Interrupt ブロックは、割り込みを生成するハードウェアを構成しません。通常、割り込みソースは VME I/O ボードで、特定のイベントの割り込みを生成します (たとえばアナログ デジタル変換の終了時など)。VME 割り込みのレベルとベクトルは、レジスタで設定するか、ボード上のジャンパーを使用して設定します。レジスタを設定するか、ボード上の割り込み生成を有効にするには、ユーザー記述デバイス ドライバー (S-Function) の mdlStart
ルーチンを使用します。Async Interrupt ブロック パラメーター ダイアログ ボックスで指定された割り込みレベルとベクトルは、I/O ボードで設定されたレベルとベクトルと一致しなければなりません。
生成された ISR コード
RTOS (VxWorks) で実際に生成された IRQ1
の ISR を以下に示します。
/* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ void isr_num1_vec192(void) { int_T lock; FP_CONTEXT context; /* Use tickGet() as a portable tick counter example. A much higher resolution can be achieved with a hardware counter */ Async_Code_M->Timing.clockTick2 = tickGet(); /* disable interrupts (system is configured as non-ive) */ lock = intLock(); /* save floating point context */ fppSave(&context); /* Call the system: <Root>/Subsystem A */ Count(0, 0); /* restore floating point context */ fppRestore(&context); /* re-enable interrupts */ intUnlock(lock); }
ISR には次の特徴があります。
ISR は、[プリエンプション フラグ] パラメーターの設定に従い、ロックされます。すなわち、さらに優先度の高い割り込みによってプリエンプトされません。RTOS 例 (VxWorks) では、関数
int_lock
および関数int_unlock
を呼び出して、ISR をロックおよびロック解除しています。接続されたサブシステム
Count
は、ISR 内から呼び出されます。関数
Count
は、アルゴリズム (モデル) コードを実行します。したがって、浮動小数点コンテキストは、関数Count
の呼び出し全体で保存および復元されます。ISR では、システム内の他の周期的な基本レートまたはサブレート カウンターとは異なる独自の絶対時間カウンターを保持します。タイミング データは、ISR 内で実行され、絶対時間または経過時間が必要なブロックに生成されたコードに使用するために維持されます。
詳細については、非同期タスクにおけるタイマーを参照してください。
モデル終了コード
次のように、モデルの終了関数によって RTOS (VxWorks) で割り込みが無効になります。
/* Model terminate function */ void Async_Code_terminate(void) { /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Disable interrupt for ISR system: isr_num1_vec192 */ sysIntDisable(1); /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ /* Disable interrupt for ISR system: isr_num2_vec193 */ sysIntDisable(2); }