В этом примере показано, как симулировать и сгенерировать код для асинхронных событий в многозадачной системе реального времени. Модель содержит блок Async Rerupt, блок Task Sync, асинхронно выполненные подсистемы Count
и Algorithm
, и блоки Rate Transition. Блок Async Conrupt создает две стандартные программы обслуживания прерывания (ISR) Versa Module Eurocard (VME), которые передают сигналы прерывания в подсистему Count
и Task Sync блока. | Count | выполняется на уровне
прерывания. Algorithm
выполняется как асинхронная задача. Код, который генератор кода производит для подсистем, адаптирован для операционной системы VxWorks ®.
Откройте пример модели rtwdemo_async
.
Можно поместить блок Async Conrupt между моделируемым источником прерывания и одним из следующих элементов модели:
Подсистема вызова функции
Блок Task Sync
Диаграмма Stateflow ®, сконфигурированная для входного события вызова функции
Модель-ссылка с блоком Inport, который соединяется с одним из предыдущих элементов модели
Блоки Async Seprupt и Task Sync позволяют подсистемам выполняться асинхронно. Перенастройте блоки Async Seprupt и Task Sync, чтобы сгенерировать код для альтернативного окружения во время выполнения.
Count
представляет простую стандартную программу обработки прерывания (ISR), которая выполняется на уровне прерывания. Лучше всего держать ISR максимально простыми. Эта подсистема включает только блок Интегратора Дискретного Времени.
Algorithm
включает больше вещества. Он включает несколько блоков и создает два выходных значения. Выполнение больших подсистем на уровне прерывания может существенно повлиять на время отклика для прерываний равного и низкого приоритета в системе. Лучшим решением для больших подсистем является использование блока Task Sync для представления ISR для подсистемы вызова функций.
Блок Async Seprupt генерирует вызовы к ISR. Поместите блок между моделируемым источником прерывания и одним из следующих:
Подсистема вызова функции
Блок Task Sync
Диаграмма Stateflow ®, сконфигурированная для входного события вызова функции
Для каждого заданного уровня прерывания блок генерирует ISR Versa Module Eurocard (VME), который выполняет подключенную подсистему, блок Task Sync или график.
В модели примера блок Async Rerupt сконфигурирован для прерываний 1 и 2 VME с помощью смещений 192 и 193 векторов прерывания. Прерывание 1 соединяется непосредственно с подсистемой Count
. Прерывание 2 соединяется с блоком Task Sync, который служит ISR для Algorithm
. Поместите блок Task Sync в одно из следующих местоположений:
Между блоком Async Seprupt и подсистемой вызова функций или графиком Stateflow ®.
В выходном порте диаграммы Stateflow, которая имеет событие, Output to Simulink
, который вы конфигурируете как вызов функции.
В модели примера блок Task Sync находится между блоком Async Прерывание и подсистемой вызова функций Algorithm
. Блок Task Sync сконфигурирован с именем задачи Task()
, приоритет 50, размер стека 8192 и передача данных задачи, синхронизированной с задачей вызывающего абонента. Порожденная задача использует семафор, чтобы синхронизировать выполнение задачи. Блок Async Conrupt запускает релиз семафора задачи.
Четыре блока перехода скорости обрабатывают передачи данных между портами, которые работают с различными скоростями. В двух образцах блоки Protected Rate Transition защищают передачу данных (препятствуют их упреждению и повреждению). В других двух образцах блоки Unprotected Rate Transition не вводят специального поведения. Их присутствие информирует Simulink ® о переходе со скоростью.
Код, сгенерированный для блоков Async Rerupt и Task Sync, адаптирован для примера RTOS (VxWorks ®). Однако можно изменить блоки, чтобы сгенерировать код, специфичный для вашего окружения во время выполнения.
Передача данных происходит между одной задачей чтения и одной задачей записи.
Операция чтения или записи переменной размера байта является атомарной.
Когда две задачи взаимодействуют, только одна может превентировать другую.
Для периодических задач задача с более высокой частотой имеет более высокий приоритет, чем задача с более низкой частотой. Задача с более высокой скоростью прерывает задачи с более медленными скоростями.
Задачи выполняются на одном процессоре. Квантование времени не разрешено.
Процессы не останавливаются и не перезапускаются, особенно в то время как данные передаются между задачами.
Симулируйте модель. По умолчанию модель сконфигурирована так, чтобы показывать шаги расчета в разных цветах. Дискретные шаги расчета для входа и выхода выглядят красным и зеленым, соответственно. Константы красновато-голубые. Асинхронные прерывания и задачи фиолетовые. Блоки Rate Transition Blocks, которые являются гибридной частотой (их входной и выходной шаги расчета могут различаться), являются желтыми.
Сгенерируйте код и отчет о генерации кода для модели. Сгенерированный код для блоков Async Seprupt и 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 7.4748s
Откройте сгенерированный исходный файл 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): '<S5>/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. Соединяет и включает isr_num1_vec192
ISR для прерывания 1 и ISR
isr_num2_vec193
для прерывания 2.
{ 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: '<S4>/Subsystem' */ /* System initialize for function-call system: '<S4>/Subsystem' */ /* SystemInitialize for S-Function (vxtask1): '<S5>/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): '<S5>/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: '<S4>/Subsystem' */ /* Enable for function-call system: '<S4>/Subsystem' */ /* Enable for S-Function (vxtask1): '<S5>/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): '<S5>/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: '<S4>/Subsystem' */ /* Termination for function-call system: '<S4>/Subsystem' */ /* Terminate for S-Function (vxtask1): '<S5>/S-Function' */ /* VxWorks Task Block: '<S5>/S-Function' (vxtask1) */ /* Destroy task: Task0 */ taskDelete(rtwdemo_async_DW.SFunction_IWORK.TaskID); /* End of Terminate for S-Function (vxtask1): '<S5>/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; 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((void *)&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 = (20);/* Number of blocks */ rtwdemo_async_M->Sizes.numBlockIO = (7);/* Number of block outputs */ return rtwdemo_async_M; } /*========================================================================* * End of Classic call interface * *========================================================================*/
Порядок этих операций очень важен. Прежде чем генератор кода включит прерывание, которое активирует задачу, он должен породить задачу.
В сгенерированном исходном файле rtwdemo_async.c
, проверьте код синхронизации задачи и задачи.
Генератор кода производит код для функции Task0
из блока Task Sync. Эта функция включает небольшое количество кода уровня прерывания и запускается как задача RTOS.
Задача ждет в бесконечном for
цикл до тех пор, пока система не отпустит семафор синхронизации. Если система освобождает семафор, функция обновляет таймер своей задачи и вызывает код, сгенерированный для Algorithm
подсистема.
В модели примера устанавливается параметр Синхронизация передачи данных этой задачи с параметром задачи вызывающего абонента для блока Task Sync. Эта установка параметра обновляет таймер, сопоставленный с блоком Task Sync (rtM->Timing.clockTick2
) со значением таймера, который блокирует Async Seprupt (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): '<S5>/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): '<S5>/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: '<S4>/Subsystem' */ { /* S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ /* Output and update for function-call system: '<S4>/Subsystem' */ /* S-Function (vxtask1): '<S5>/S-Function' */ /* VxWorks Task Block: '<S5>/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): '<S5>/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): '<S5>/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): '<S5>/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: '<S4>/Subsystem' */ /* Termination for function-call system: '<S4>/Subsystem' */ /* Terminate for S-Function (vxtask1): '<S5>/S-Function' */ /* VxWorks Task Block: '<S5>/S-Function' (vxtask1) */ /* Destroy task: Task0 */ taskDelete(rtwdemo_async_DW.SFunction_IWORK.TaskID); /* End of Terminate for S-Function (vxtask1): '<S5>/S-Function' */ /* End of Terminate for S-Function (vxinterrupt1): '<Root>/Async Interrupt' */ }