生成并同步 RTOS 任务的执行
此示例说明如何在实时多任务系统上仿真和生成异步事件的代码。该模型包含 Async Interrupt 模块、Task Sync 模块、异步执行子系统 Count
和 Algorithm
以及 Rate Transition 模块。Async Interrupt 模块会创建两个 Versa Module Eurocard (VME) 中断服务例程 (ISR),它们将中断信号传递给子系统 Count
和 Task Sync 模块。Count
在中断级别执行。Algorithm
作为异步任务执行。代码生成器为子系统生成的代码是针对 VxWorks® 操作系统的。
关于示例模型
打开示例模型 rtwdemo_async
。
您可以在仿真的中断源与下列模型元素之一之间放置一个 Async Interrupt 模块:
函数调用子系统
Task Sync 模块
为函数调用输入事件配置的 Stateflow® 图
具有连接到前述模型元素之一的 Inport 模块的引用模型
Async Interrupt 和 Task Sync 模块使子系统能够异步执行。重新配置 Async Interrupt 和 Task Sync 模块,以便为另一个运行时环境生成代码。
Count
表示在中断级别执行的一个简单中断服务例程 (ISR)。最好让 ISR 尽可能简单。此子系统仅包含一个 Discrete-Time Integrator 模块。
Algorithm
包含更多内容。它包含多个模块并产生两个输出值。在中断级别执行较大的子系统会对系统中同等优先级和更低优先级中断的响应时间产生重大影响。对于较大的子系统,更好的解决方案是使用 Task Sync 模块来表示函数调用子系统的 ISR。
Async Interrupt 模块生成对 ISR 的调用。将该模块放在仿真的中断源与下列项之一之间:
函数调用子系统
Task Sync 模块
为函数调用输入事件配置的 Stateflow 图
对于每个指定的中断级别,该模块生成一个 Versa Module Eurocard (VME) ISR,用于执行连接的子系统、Task Sync 模块或图。
在示例模型中,通过使用中断向量偏移 192 和 193,针对 VME Interrupt 1 和 2 配置 Async Interrupt 模块。Interrupt 1 直接连接到子系统 Count
。Interrupt 2 连接到 Task Sync 模块,该模块充当 Algorithm
的 ISR。将 Task Sync 模块放在以下位置之一:
Async Interrupt 模块与函数调用子系统或 Stateflow 图之间。
具有事件
Output to Simulink
(该事件被配置为函数调用)的 Stateflow 图的输出端口上。
在示例模型中,Task Sync 模块位于 Async Interrupt 模块与函数调用子系统 Algorithm
之间。Task Sync 模块配置为使用任务名称 Task()
,优先级为 50,堆栈大小为 8192,任务的数据传输与调用方任务同步。生成的任务使用信号量来同步任务执行。Async Interrupt 模块会触发任务信号量的释放。
四个 Rate Transition 模块会处理以不同速率工作的端口之间的数据传输。在两个实例中,受保护 Rate Transition 模块用于保护数据传输(防止它们被抢占和损坏)。在另外两个实例中,非受保护 Rate Transition 模块不会引入特殊行为。它们用于通知 Simulink® 发生速率转换。
为 Async Interrupt 和 Task Sync 模块生成的代码是专门用于示例 RTOS (VxWorks) 的。但是,您可以修改这些模块来生成特定于您的运行时环境的代码。
数据传输假设
数据传输发生在一个读取任务与一个写入任务之间。
对以字节为单位的变量的读取或写入操作是原子级别的。
当两个任务交互时,只有其中一个任务可以抢占另一个任务。
对于周期性任务,速率较快的任务优先于速率较慢的任务。速率较快的任务可以抢占速率较慢的任务。
这些任务在单个处理器上运行。不允许分时。
进程不会停止和重启,尤其是在各任务间传输数据时。
对模型进行仿真
对模型进行仿真。默认情况下,模型配置为以不同颜色显示采样时间。输入和输出的离散采样时间分别以红色和绿色显示。常量以红蓝色显示。异步中断和任务以紫色显示。具有混合速率的 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 16.982s
查看初始化代码
打开生成的源文件 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.为 Interrupt 1 连接并启用 ISR isr_num1_vec192
,为 Interrupt 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 模块设置了将此任务的数据传输与调用方任务同步参数。该参数设置使用 Async Interrupt 模块维护的计时器 (rtM->Timing.clockTick3
) 的值更新与 Task Sync 模块相关联的计时器 (rtM->Timing.clockTick2
)。因此,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' */ { real_T Sum; 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' */ Sum = rtwdemo_async_B.ProtectedRT1[i] + 1.25; rtwdemo_async_B.Sum[i] = Sum; /* Sum: '<S1>/Sum1' */ rtwdemo_async_DW.Integrator_PREV_U += Sum; } /* 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' */ { real_T Sum; 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' */ Sum = rtwdemo_async_B.ProtectedRT1[i] + 1.25; rtwdemo_async_B.Sum[i] = Sum; /* Sum: '<S1>/Sum1' */ rtwdemo_async_DW.Integrator_PREV_U += Sum; } /* 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' */ }