RTOS タスクの例の発生と同期
この例では、リアルタイム マルチタスク システム上の非同期イベントのシミュレーションとコード生成方法について説明します。モデルには Async Interrupt ブロック、Task Sync ブロック、非同期で実行されるサブシステム Count
と Algorithm
、Rate Transition ブロックが含まれます。Async Interrupt ブロックは、割り込み信号をサブシステム Count
と Task Sync ブロックに渡す 2 つの Versa Module Eurocard (VME) 割り込みサービス ルーチン (ISR) を作成します。Count
は割り込みレベルで実行されます。Algorithm
は非同期タスクとして実行されます。コード ジェネレーターでサブシステムに対して生成されるコードは VxWorks® オペレーティング システムに合わせて調整されます。
モデル例について
モデル例 rtwdemo_async
を開きます。
シミュレートされた割り込みソースと次のいずれか 1 つのモデル要素間に Async Interrupt ブロックを置くことができます。
Function Call Subsystem
Task Sync ブロック
関数呼び出し入力イベント用に構成された Stateflow® チャート
上記のモデル要素の 1 つに接続する Inport ブロックを含む参照モデル
Async Interrupt ブロックと Task Sync ブロックによって、サブシステムを非同期で実行できます。Async Interrupt ブロックと Task Sync ブロックを再設定し、代替のランタイム環境用にコードを生成します。
Count
は、割り込みレベルで実行されるシンプルな割り込みサービス ルーチン (ISR) を表します。ISR はできる限りシンプルにすることをお勧めします。このサブシステムには、Discrete-Time Integrator ブロックのみ含まれます。
Algorithm
にはさらに多くのものが含まれます。これは複数のブロックを含み、2 つの出力値を生成します。割り込みレベルでより大規模なサブシステムが実行されると、システム内で優先順位が同じか、低い割り込みの応答時間に大きく影響します。より大規模なサブシステムの場合は、Task Sync ブロックを使用して Function-Call Subsystem の ISR を表すソリューションをお勧めします。
Async Interrupt ブロックは ISR への呼び出しを生成します。シミュレーションする割り込みソースと次のいずれか 1 つの間にブロックを置きます。
Function Call Subsystem
Task Sync ブロック
関数呼び出し入力イベント用に構成された Stateflow チャート
指定された各割り込みレベルで、ブロックは、接続されたサブシステム、Task Sync ブロックまたはチャートを実行する Versa Module Eurocard (VME) ISR を生成します。
このモデル例では、Async Interrupt ブロックは割り込みベクトル オフセット 192 および 193 を使用して、VME 割り込み 1 および 2 について設定されています。割り込み 1 はサブシステム Count
に直接接続します。割り込み 2 は Task Sync ブロックに接続し、Task Sync ブロックは Algorithm
の ISR として機能します。Task Sync ブロックを次のいずれかの場所に置きます。
Async Interrupt ブロックと Function-Call Subsystem または Stateflow チャートの間。
関数呼び出しとして設定するイベント
Output to Simulink
をもつ Stateflow チャートの出力端子。
モデル例では、Task Sync ブロックは Async Interrupt ブロックと Function-Call Subsystem Algorithm
の間にあります。Task Sync ブロックは、タスク名 Task()
、優先順位 50、スタック サイズ 8192、呼び出し側タスクと同期されるタスクのデータ転送を使用して設定されます。発生したタスクはセマフォを使用してタスクの実行を同期します。Async Interrupt ブロックは、タスク セマフォのリリースをトリガーします。
4 つの Rate Transition ブロックが、さまざまなレートで動作する端子間でのデータ転送を処理します。2 つのインスタンスで、保護された Rate Transition ブロックはデータ転送を保護します (データ転送がプリエンプトされ破損するのを防ぎます)。他の 2 つのインスタンスでは、保護されていない Rate Transition ブロックは特別な動作を導入しません。その存在により、Simulink® にレート変換を伝えます。
Async Interrupt ブロックと Task Sync ブロックで生成されるコードは、RTOS 例 (VxWorks) に合わせて調整されます。ただし、ブロックを変更してランタイム環境に固有のコードを生成できます。
データ転送の仮定
データ転送は、1 つの読み取りタスクと 1 つの書き込みタスクの間に行われる。
バイト単位の変数の読み取り操作または書き込み操作はアトミックである。
2 つのタスクが相互作用する場合、一方だけがプリエンプトできる。
周期的タスクの場合、速いレートのタスクの方が、遅いレートのタスクよりも優先順位が高くなる。速いレートのタスクは、遅いレートのタスクをプリエンプトする。
タスクは 1 つのプロセッサ上で実行される。タイム スライスは許可されない。
プロセスは、特にデータがタスク間で転送されているとき、停止または再起動しない。
モデルのシミュレーション
モデルのシミュレーションを実行します。既定の設定では、モデルはサンプル時間を異なる色で表示します。入力と出力の離散サンプル時間は、それぞれ赤と緑で表示されます。定数は赤みがかった青です。非同期割り込みとタスクは紫です。ハイブリッド レート (入力および出力サンプル時間が異なる可能性がある) の Rate Transition ブロックは黄色です。
コードとレポートの生成
モデルのコードとコード生成レポートを生成します。Async Interrupt ブロックと Task Sync ブロックの生成コードは RTOS 例 (VxWorks) 用です。ただし、ブロックを変更して別の実行時環境用にコードを生成できます。
1. ビルドと検査プロセス用に一時フォルダーを作成します。
2. モデルを作成します。
### Starting build procedure for: rtwdemo_async Warning: Simulink Coder: The tornado.tlc target will be removed in a future release. ### Successful completion of code generation for: rtwdemo_async Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================== rtwdemo_async Code generated. Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 10.194s
初期化コードのレビュー
生成されたソース ファイル rtwdemo_async.c
を開きます。初期化コード:
1. 同期セマフォ Task0_semaphore
を作成し、初期化します。
*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); if (rtwdemo_async_DW.SFunction_PWORK.SemID == NULL) { printf("semBCreate call failed for block Task0.\n"); }
2. タスク task0
を発生させ、タスクに優先順位 50 を割り当てます。
rtwdemo_async_DW.SFunction_IWORK.TaskID = taskSpawn("Task0", 50.0, VX_FP_TASK, 8192.0, (FUNCPTR)Task0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0); if (rtwdemo_async_DW.SFunction_IWORK.TaskID == ERROR) { printf("taskSpawn call failed for block Task0.\n"); } /* End of Start for S-Function (vxtask1): '<S4>/S-Function' */ /* 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);
3. 割り込み 1 では ISR isr_num1_vec192
、割り込み 2 では ISR isr_num2_vec193
に接続して有効にします。
{ int32_T i; /* InitializeConditions for RateTransition: '<Root>/Protected RT1' */ for (i = 0; i < 60; i++) { rtwdemo_async_DW.ProtectedRT1_Buffer[i] = 0.0; } /* End of InitializeConditions for RateTransition: '<Root>/Protected RT1' */ /* InitializeConditions for RateTransition: '<Root>/Protected RT2' */ for (i = 0; i < 60; i++) { rtwdemo_async_DW.ProtectedRT2_Buffer[i] = 0.0; } /* End of InitializeConditions for RateTransition: '<Root>/Protected RT2' */ /* SystemInitialize for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorporates: * SubSystem: '<Root>/Count' */ /* System initialize for function-call system: '<Root>/Count' */ /* InitializeConditions for DiscreteIntegrator: '<S2>/Integrator' */ rtwdemo_async_DW.Integrator_DSTATE_l = 0.0; rtwdemo_async_DW.Integrator_PREV_U_o = 0.0; /* SystemInitialize for Outport: '<Root>/Out1' incorporates: * Outport: '<S2>/Out' */ rtwdemo_async_Y.Out1 = 0.0; /* SystemInitialize for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorporates: * SubSystem: '<S3>/Subsystem' */ /* System initialize for function-call system: '<S3>/Subsystem' */ /* SystemInitialize for S-Function (vxtask1): '<S4>/S-Function' incorporates: * SubSystem: '<Root>/Algorithm' */ /* System initialize for function-call system: '<Root>/Algorithm' */ rtwdemo_async_M->Timing.clockTick2 = rtwdemo_async_M->Timing.clockTick4; /* InitializeConditions for DiscreteIntegrator: '<S1>/Integrator' */ rtwdemo_async_DW.Integrator_DSTATE = 0.0; /* InitializeConditions for Sum: '<S1>/Sum1' incorporates: * DiscreteIntegrator: '<S1>/Integrator' */ rtwdemo_async_DW.Integrator_PREV_U = 0.0; /* SystemInitialize for Sum: '<S1>/Sum' incorporates: * Outport: '<S1>/Out1' */ memset(&rtwdemo_async_B.Sum[0], 0, 60U * sizeof(real_T)); /* SystemInitialize for Outport: '<Root>/Out3' incorporates: * Outport: '<S1>/Out2' */ rtwdemo_async_Y.Out3 = 0.0; /* End of SystemInitialize for S-Function (vxtask1): '<S4>/S-Function' */ /* End of SystemInitialize for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* Enable for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorporates: * SubSystem: '<Root>/Count' */ /* Enable for function-call system: '<Root>/Count' */ rtwdemo_async_DW.Count_RESET_ELAPS_T = true; /* Enable for DiscreteIntegrator: '<S2>/Integrator' */ rtwdemo_async_DW.Integrator_SYSTEM_ENABLE_h = 1U; /* Enable for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorporates: * SubSystem: '<S3>/Subsystem' */ /* Enable for function-call system: '<S3>/Subsystem' */ /* Enable for S-Function (vxtask1): '<S4>/S-Function' incorporates: * SubSystem: '<Root>/Algorithm' */ /* Enable for function-call system: '<Root>/Algorithm' */ rtwdemo_async_M->Timing.clockTick2 = rtwdemo_async_M->Timing.clockTick4; rtwdemo_async_DW.Algorithm_RESET_ELAPS_T = true; /* Enable for DiscreteIntegrator: '<S1>/Integrator' */ rtwdemo_async_DW.Integrator_SYSTEM_ENABLE = 1U; /* End of Enable for S-Function (vxtask1): '<S4>/S-Function' */ /* End of Enable for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* Model terminate function */ static void rtwdemo_async_terminate(void) { /* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* 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); /* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorporates: * SubSystem: '<S3>/Subsystem' */ /* Termination for function-call system: '<S3>/Subsystem' */ /* Terminate for S-Function (vxtask1): '<S4>/S-Function' */ /* VxWorks Task Block: '<S4>/S-Function' (vxtask1) */ /* Destroy task: Task0 */ taskDelete(rtwdemo_async_DW.SFunction_IWORK.TaskID); /* End of Terminate for S-Function (vxtask1): '<S4>/S-Function' */ /* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /*========================================================================* * Start of Classic call interface * *========================================================================*/ void MdlOutputs(int_T tid) { rtwdemo_async_output(tid); } void MdlUpdate(int_T tid) { rtwdemo_async_update(tid); } void MdlInitializeSizes(void) { } void MdlInitializeSampleTimes(void) { } void MdlInitialize(void) { } void MdlStart(void) { rtwdemo_async_initialize(); } void MdlTerminate(void) { rtwdemo_async_terminate(); } /* Registration function */ RT_MODEL_rtwdemo_async_T *rtwdemo_async(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)rtwdemo_async_M, 0, sizeof(RT_MODEL_rtwdemo_async_T)); /* Initialize timing info */ { int_T *mdlTsMap = rtwdemo_async_M->Timing.sampleTimeTaskIDArray; mdlTsMap[0] = 0; mdlTsMap[1] = 1; /* polyspace +2 MISRA2012:D4.1 [Justified:Low] "rtwdemo_async_M points to static memory which is guaranteed to be non-NULL" */ rtwdemo_async_M->Timing.sampleTimeTaskIDPtr = (&mdlTsMap[0]); rtwdemo_async_M->Timing.sampleTimes = (&rtwdemo_async_M->Timing.sampleTimesArray[0]); rtwdemo_async_M->Timing.offsetTimes = (&rtwdemo_async_M->Timing.offsetTimesArray[0]); /* task periods */ rtwdemo_async_M->Timing.sampleTimes[0] = (0.016666666666666666); rtwdemo_async_M->Timing.sampleTimes[1] = (0.05); /* task offsets */ rtwdemo_async_M->Timing.offsetTimes[0] = (0.0); rtwdemo_async_M->Timing.offsetTimes[1] = (0.0); } rtmSetTPtr(rtwdemo_async_M, &rtwdemo_async_M->Timing.tArray[0]); { int_T *mdlSampleHits = rtwdemo_async_M->Timing.sampleHitArray; int_T *mdlPerTaskSampleHits = rtwdemo_async_M->Timing.perTaskSampleHitsArray; rtwdemo_async_M->Timing.perTaskSampleHits = (&mdlPerTaskSampleHits[0]); mdlSampleHits[0] = 1; rtwdemo_async_M->Timing.sampleHits = (&mdlSampleHits[0]); } rtmSetTFinal(rtwdemo_async_M, 0.5); rtwdemo_async_M->Timing.stepSize0 = 0.016666666666666666; rtwdemo_async_M->Timing.stepSize1 = 0.05; rtwdemo_async_M->solverInfoPtr = (&rtwdemo_async_M->solverInfo); rtwdemo_async_M->Timing.stepSize = (0.016666666666666666); rtsiSetFixedStepSize(&rtwdemo_async_M->solverInfo, 0.016666666666666666); rtsiSetSolverMode(&rtwdemo_async_M->solverInfo, SOLVER_MODE_MULTITASKING); /* block I/O */ rtwdemo_async_M->blockIO = ((void *) &rtwdemo_async_B); (void) memset(((void *) &rtwdemo_async_B), 0, sizeof(B_rtwdemo_async_T)); /* states (dwork) */ rtwdemo_async_M->dwork = ((void *) &rtwdemo_async_DW); (void) memset((void *)&rtwdemo_async_DW, 0, sizeof(DW_rtwdemo_async_T)); /* external inputs */ rtwdemo_async_M->inputs = (((void*)&rtwdemo_async_U)); (void)memset(&rtwdemo_async_U, 0, sizeof(ExtU_rtwdemo_async_T)); /* external outputs */ rtwdemo_async_M->outputs = (&rtwdemo_async_Y); (void)memset(&rtwdemo_async_Y, 0, sizeof(ExtY_rtwdemo_async_T)); /* Initialize Sizes */ rtwdemo_async_M->Sizes.numContStates = (0);/* Number of continuous states */ rtwdemo_async_M->Sizes.numY = (3); /* Number of model outputs */ rtwdemo_async_M->Sizes.numU = (60); /* Number of model inputs */ rtwdemo_async_M->Sizes.sysDirFeedThru = (1);/* The model is direct feedthrough */ rtwdemo_async_M->Sizes.numSampTimes = (2);/* Number of sample times */ rtwdemo_async_M->Sizes.numBlocks = (19);/* Number of blocks */ rtwdemo_async_M->Sizes.numBlockIO = (6);/* Number of block outputs */ return rtwdemo_async_M; } /*========================================================================* * End of Classic call interface * *========================================================================*/
これらの操作の順序は重要です。コード ジェネレーターは、タスクをアクティブにする割り込みを有効にする前に、タスクを発生させなければなりません。
タスクとタスク同期コードのレビュー
生成されたソース ファイル rtwdemo_async.c
で、タスクとタスク同期コードをレビューします。
コード ジェネレーターは、Task Sync ブロックから関数 Task0
のコードを生成します。この関数は、少量の割り込みレベル コードを含み、RTOS タスクとして実行されます。
タスクは、システムが同期セマフォをリリースするまで無限 for
ループで待機します。システムがセマフォをリリースすると、関数がその時間タイマーを更新し、Algorithm
サブシステムに対して生成されたコードを呼び出します。
モデル例では、Task Sync ブロックの [このタスクのデータ転送を呼び出し側タスクと同期] パラメーターが設定されます。このパラメーター設定では、Task Sync ブロックに関連付けられたタイマー (rtM->Timing.clockTick2
) を、Async Interrupt ブロックが維持するタイマー (rtM->Timing.clockTick3
) の値で更新します。その結果、Algorithm
サブシステム内のブロックのコードは、Task0
の最新のアクティブ化ではなく、最新の割り込みの時間に基づくタイマー値を使用します。
{ /* Wait for semaphore to be released by system: rtwdemo_async/Task Sync */ for (;;) { if (semTake(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID,NO_WAIT) != ERROR) { logMsg("Rate for Task Task0() too fast.\n",0,0,0,0,0,0); #if STOPONOVERRUN logMsg("Aborting real-time simulation.\n",0,0,0,0,0,0); semGive(stopSem); return(ERROR); #endif } else { semTake(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID, WAIT_FOREVER); } /* Use the upstream clock tick counter for this Task. */ rtwdemo_async_M->Timing.clockTick2 = rtwdemo_async_M->Timing.clockTick4; /* Call the system: '<Root>/Algorithm' */ { int32_T i; int32_T i_0; /* RateTransition: '<Root>/Protected RT1' */ i = rtwdemo_async_DW.ProtectedRT1_ActiveBufIdx * 60; for (i_0 = 0; i_0 < 60; i_0++) { rtwdemo_async_B.ProtectedRT1[i_0] = rtwdemo_async_DW.ProtectedRT1_Buffer[i_0 + i]; } /* End of RateTransition: '<Root>/Protected RT1' */ /* S-Function (vxtask1): '<S4>/S-Function' */ /* Output and update for function-call system: '<Root>/Algorithm' */ { int32_T i; rtwdemo_async_M->Timing.clockTick2 = rtwdemo_async_M->Timing.clockTick4; if (rtwdemo_async_DW.Algorithm_RESET_ELAPS_T) { rtwdemo_async_DW.Algorithm_ELAPS_T = 0U; } else { rtwdemo_async_DW.Algorithm_ELAPS_T = rtwdemo_async_M->Timing.clockTick2 - rtwdemo_async_DW.Algorithm_PREV_T; } rtwdemo_async_DW.Algorithm_PREV_T = rtwdemo_async_M->Timing.clockTick2; rtwdemo_async_DW.Algorithm_RESET_ELAPS_T = false; /* DiscreteIntegrator: '<S1>/Integrator' */ if (rtwdemo_async_DW.Integrator_SYSTEM_ENABLE == 0) { /* DiscreteIntegrator: '<S1>/Integrator' */ rtwdemo_async_DW.Integrator_DSTATE += 0.016666666666666666 * (real_T) rtwdemo_async_DW.Algorithm_ELAPS_T * rtwdemo_async_DW.Integrator_PREV_U; } /* End of DiscreteIntegrator: '<S1>/Integrator' */ /* Outport: '<Root>/Out3' incorporates: * SignalConversion generated from: '<S1>/Out2' */ rtwdemo_async_Y.Out3 = rtwdemo_async_DW.Integrator_DSTATE; /* Sum: '<S1>/Sum1' */ rtwdemo_async_DW.Integrator_PREV_U = -0.0; for (i = 0; i < 60; i++) { /* Sum: '<S1>/Sum' incorporates: * Constant: '<S1>/Offset' */ rtwdemo_async_B.Sum[i] = rtwdemo_async_B.ProtectedRT1[i] + 1.25; /* Sum: '<S1>/Sum1' */ rtwdemo_async_DW.Integrator_PREV_U += rtwdemo_async_B.Sum[i]; } /* Update for DiscreteIntegrator: '<S1>/Integrator' */ rtwdemo_async_DW.Integrator_SYSTEM_ENABLE = 0U; } /* End of Outputs for S-Function (vxtask1): '<S4>/S-Function' */ /* RateTransition: '<Root>/Protected RT2' */ for (i = 0; i < 60; i++) { rtwdemo_async_DW.ProtectedRT2_Buffer[i + (rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx == 0) * 60] = rtwdemo_async_B.Sum[i]; } rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx = (int8_T) (rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx == 0); /* End of RateTransition: '<Root>/Protected RT2' */ } } } /* 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 */ rtwdemo_async_M->Timing.clockTick3 = tickGet(); /* disable interrupts (system is configured as non-preemptive) */ lock = intLock(); /* save floating point context */ fppSave(&context); /* Call the system: '<Root>/Count' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* Output and update for function-call system: '<Root>/Count' */ if (rtwdemo_async_DW.Count_RESET_ELAPS_T) { rtwdemo_async_DW.Count_ELAPS_T = 0U; } else { rtwdemo_async_DW.Count_ELAPS_T = rtwdemo_async_M->Timing.clockTick3 - rtwdemo_async_DW.Count_PREV_T; } rtwdemo_async_DW.Count_PREV_T = rtwdemo_async_M->Timing.clockTick3; rtwdemo_async_DW.Count_RESET_ELAPS_T = false; /* DiscreteIntegrator: '<S2>/Integrator' */ if (rtwdemo_async_DW.Integrator_SYSTEM_ENABLE_h == 0) { /* DiscreteIntegrator: '<S2>/Integrator' */ rtwdemo_async_DW.Integrator_DSTATE_l += 0.016666666666666666 * (real_T) rtwdemo_async_DW.Count_ELAPS_T * rtwdemo_async_DW.Integrator_PREV_U_o; } /* End of DiscreteIntegrator: '<S2>/Integrator' */ /* Outport: '<Root>/Out1' incorporates: * SignalConversion generated from: '<S2>/Out' */ rtwdemo_async_Y.Out1 = rtwdemo_async_DW.Integrator_DSTATE_l; /* Update for DiscreteIntegrator: '<S2>/Integrator' incorporates: * Constant: '<S2>/Constant' */ rtwdemo_async_DW.Integrator_SYSTEM_ENABLE_h = 0U; rtwdemo_async_DW.Integrator_PREV_U_o = 1.0; /* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* restore floating point context */ fppRestore(&context); /* re-enable interrupts */ intUnlock(lock); } /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */ void isr_num2_vec193(void) { /* Use tickGet() as a portable tick counter example. A much higher resolution can be achieved with a hardware counter */ rtwdemo_async_M->Timing.clockTick4 = tickGet(); /* Call the system: '<S3>/Subsystem' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* Output and update for function-call system: '<S3>/Subsystem' */ /* S-Function (vxtask1): '<S4>/S-Function' */ /* VxWorks Task Block: '<S4>/S-Function' (vxtask1) */ /* Release semaphore for system task: Task0 */ semGive(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID); /* End of Outputs for S-Function (vxtask1): '<S4>/S-Function' */ /* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } }
コード ジェネレーターは、ISR isr_num1_vec192
および isr_num2_vec293
のコードを生成します。ISR isr_num2_vec192
は次を行います。
割り込みを無効にする。
浮動小数点コンテキストを保存する。
割り込みを受信する参照モデル Inport ブロックに接続するサブシステムに対して生成されたコードを呼び出す。
浮動小数点コンテキストを復元する。
割り込みを再度有効にする。
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 */ rtwdemo_async_M->Timing.clockTick3 = tickGet(); /* disable interrupts (system is configured as non-preemptive) */ lock = intLock(); /* save floating point context */ fppSave(&context); /* Call the system: '<Root>/Count' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* Output and update for function-call system: '<Root>/Count' */ if (rtwdemo_async_DW.Count_RESET_ELAPS_T) { rtwdemo_async_DW.Count_ELAPS_T = 0U; } else { rtwdemo_async_DW.Count_ELAPS_T = rtwdemo_async_M->Timing.clockTick3 - rtwdemo_async_DW.Count_PREV_T; } rtwdemo_async_DW.Count_PREV_T = rtwdemo_async_M->Timing.clockTick3; rtwdemo_async_DW.Count_RESET_ELAPS_T = false; /* DiscreteIntegrator: '<S2>/Integrator' */ if (rtwdemo_async_DW.Integrator_SYSTEM_ENABLE_h == 0) { /* DiscreteIntegrator: '<S2>/Integrator' */ rtwdemo_async_DW.Integrator_DSTATE_l += 0.016666666666666666 * (real_T) rtwdemo_async_DW.Count_ELAPS_T * rtwdemo_async_DW.Integrator_PREV_U_o; } /* End of DiscreteIntegrator: '<S2>/Integrator' */ /* Outport: '<Root>/Out1' incorporates: * SignalConversion generated from: '<S2>/Out' */ rtwdemo_async_Y.Out1 = rtwdemo_async_DW.Integrator_DSTATE_l; /* Update for DiscreteIntegrator: '<S2>/Integrator' incorporates: * Constant: '<S2>/Constant' */ rtwdemo_async_DW.Integrator_SYSTEM_ENABLE_h = 0U; rtwdemo_async_DW.Integrator_PREV_U_o = 1.0; /* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* restore floating point context */ fppRestore(&context); /* re-enable interrupts */ intUnlock(lock); } /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */
ISR isr_num2_vec293
は、割り込みが発生した時点の目盛りのカウントを格納するタイマーを維持します。タイマーの更新後、ISR は Task0
をアクティブにするセマフォをリリースします。
/* Spawned with priority: 50 */ void Task0(void) { /* Wait for semaphore to be released by system: rtwdemo_async/Task Sync */ for (;;) { if (semTake(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID,NO_WAIT) != ERROR) { logMsg("Rate for Task Task0() too fast.\n",0,0,0,0,0,0); #if STOPONOVERRUN logMsg("Aborting real-time simulation.\n",0,0,0,0,0,0); semGive(stopSem); return(ERROR); #endif } else { semTake(*(SEM_ID *)rtwdemo_async_DW.SFunction_PWORK.SemID, WAIT_FOREVER); } /* Use the upstream clock tick counter for this Task. */ rtwdemo_async_M->Timing.clockTick2 = rtwdemo_async_M->Timing.clockTick4; /* Call the system: '<Root>/Algorithm' */ { int32_T i; int32_T i_0; /* RateTransition: '<Root>/Protected RT1' */ i = rtwdemo_async_DW.ProtectedRT1_ActiveBufIdx * 60; for (i_0 = 0; i_0 < 60; i_0++) { rtwdemo_async_B.ProtectedRT1[i_0] = rtwdemo_async_DW.ProtectedRT1_Buffer[i_0 + i]; } /* End of RateTransition: '<Root>/Protected RT1' */ /* S-Function (vxtask1): '<S4>/S-Function' */ /* Output and update for function-call system: '<Root>/Algorithm' */ { int32_T i; rtwdemo_async_M->Timing.clockTick2 = rtwdemo_async_M->Timing.clockTick4; if (rtwdemo_async_DW.Algorithm_RESET_ELAPS_T) { rtwdemo_async_DW.Algorithm_ELAPS_T = 0U; } else { rtwdemo_async_DW.Algorithm_ELAPS_T = rtwdemo_async_M->Timing.clockTick2 - rtwdemo_async_DW.Algorithm_PREV_T; } rtwdemo_async_DW.Algorithm_PREV_T = rtwdemo_async_M->Timing.clockTick2; rtwdemo_async_DW.Algorithm_RESET_ELAPS_T = false; /* DiscreteIntegrator: '<S1>/Integrator' */ if (rtwdemo_async_DW.Integrator_SYSTEM_ENABLE == 0) { /* DiscreteIntegrator: '<S1>/Integrator' */ rtwdemo_async_DW.Integrator_DSTATE += 0.016666666666666666 * (real_T) rtwdemo_async_DW.Algorithm_ELAPS_T * rtwdemo_async_DW.Integrator_PREV_U; } /* End of DiscreteIntegrator: '<S1>/Integrator' */ /* Outport: '<Root>/Out3' incorporates: * SignalConversion generated from: '<S1>/Out2' */ rtwdemo_async_Y.Out3 = rtwdemo_async_DW.Integrator_DSTATE; /* Sum: '<S1>/Sum1' */ rtwdemo_async_DW.Integrator_PREV_U = -0.0; for (i = 0; i < 60; i++) { /* Sum: '<S1>/Sum' incorporates: * Constant: '<S1>/Offset' */ rtwdemo_async_B.Sum[i] = rtwdemo_async_B.ProtectedRT1[i] + 1.25; /* Sum: '<S1>/Sum1' */ rtwdemo_async_DW.Integrator_PREV_U += rtwdemo_async_B.Sum[i]; } /* Update for DiscreteIntegrator: '<S1>/Integrator' */ rtwdemo_async_DW.Integrator_SYSTEM_ENABLE = 0U; } /* End of Outputs for S-Function (vxtask1): '<S4>/S-Function' */ /* RateTransition: '<Root>/Protected RT2' */ for (i = 0; i < 60; i++) { rtwdemo_async_DW.ProtectedRT2_Buffer[i + (rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx == 0) * 60] = rtwdemo_async_B.Sum[i]; } rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx = (int8_T) (rtwdemo_async_DW.ProtectedRT2_ActiveBufIdx == 0); /* End of RateTransition: '<Root>/Protected RT2' */ } } } /* 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 */ rtwdemo_async_M->Timing.clockTick3 = tickGet(); /* disable interrupts (system is configured as non-preemptive) */ lock = intLock(); /* save floating point context */ fppSave(&context); /* Call the system: '<Root>/Count' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* Output and update for function-call system: '<Root>/Count' */ if (rtwdemo_async_DW.Count_RESET_ELAPS_T) { rtwdemo_async_DW.Count_ELAPS_T = 0U; } else { rtwdemo_async_DW.Count_ELAPS_T = rtwdemo_async_M->Timing.clockTick3 - rtwdemo_async_DW.Count_PREV_T; } rtwdemo_async_DW.Count_PREV_T = rtwdemo_async_M->Timing.clockTick3; rtwdemo_async_DW.Count_RESET_ELAPS_T = false; /* DiscreteIntegrator: '<S2>/Integrator' */ if (rtwdemo_async_DW.Integrator_SYSTEM_ENABLE_h == 0) { /* DiscreteIntegrator: '<S2>/Integrator' */ rtwdemo_async_DW.Integrator_DSTATE_l += 0.016666666666666666 * (real_T) rtwdemo_async_DW.Count_ELAPS_T * rtwdemo_async_DW.Integrator_PREV_U_o; } /* End of DiscreteIntegrator: '<S2>/Integrator' */ /* Outport: '<Root>/Out1' incorporates: * SignalConversion generated from: '<S2>/Out' */ rtwdemo_async_Y.Out1 = rtwdemo_async_DW.Integrator_DSTATE_l; /* Update for DiscreteIntegrator: '<S2>/Integrator' incorporates: * Constant: '<S2>/Constant' */ rtwdemo_async_DW.Integrator_SYSTEM_ENABLE_h = 0U; rtwdemo_async_DW.Integrator_PREV_U_o = 1.0; /* End of Outputs for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ } /* restore floating point context */ fppRestore(&context); /* re-enable interrupts */ intUnlock(lock); } /* VxWorks Interrupt Block: '<Root>/Async Interrupt' */
タスク終了コードのレビュー
Task Sync ブロックは、次の終了コードを生成します。
static void rtwdemo_async_terminate(void) { /* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* 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); /* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' incorporates: * SubSystem: '<S3>/Subsystem' */ /* Termination for function-call system: '<S3>/Subsystem' */ /* Terminate for S-Function (vxtask1): '<S4>/S-Function' */ /* VxWorks Task Block: '<S4>/S-Function' (vxtask1) */ /* Destroy task: Task0 */ taskDelete(rtwdemo_async_DW.SFunction_IWORK.TaskID); /* End of Terminate for S-Function (vxtask1): '<S4>/S-Function' */ /* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ }