exponenta event banner

Создание и синхронизация выполнения задачи RTOS

В этом примере показано, как моделировать и генерировать код для асинхронных событий в многозадачной системе реального времени. Модель содержит блок асинхронного прерывания, блок синхронизации задач, асинхронно выполняемые подсистемы Count и Algorithmи блоки Rate Transition. Блок асинхронных прерываний создает две подпрограммы обслуживания прерываний (ISR) модуля Versa Eurocard (VME), которые передают сигналы прерываний в подсистему Count и блок синхронизации задач. | Count | выполняется на уровне прерываний.Algorithm выполняется как асинхронная задача. Код, создаваемый генератором кода для подсистем, адаптирован для операционной системы VxWorks ®.

Сведения о примерной модели

Открыть пример модели rtwdemo_async.

Можно поместить блок асинхронного прерывания между моделируемым источником прерывания и одним из следующих элементов модели:

  • Подсистема вызова функций

  • Блок синхронизации задач

  • Диаграмма Stateflow ®, настроенная для события ввода вызова функции

  • Ссылочная модель с блоком Inport, который соединяется с одним из предыдущих элементов модели

Блоки асинхронного прерывания и синхронизации задач позволяют подсистемам выполнять асинхронно. Реконфигурируйте блоки асинхронного прерывания и синхронизации задач для создания кода для альтернативной среды выполнения.

Count представляет простую подпрограмму обслуживания прерываний (ISR), которая выполняется на уровне прерываний. Лучше всего максимально упростить ISR. Эта подсистема включает только блок интегратора дискретного времени.

Algorithm содержит больше вещества. Она включает в себя несколько блоков и выдает два выходных значения. Выполнение более крупных подсистем на уровне прерываний может существенно повлиять на время отклика для прерываний равного и более низкого приоритета в системе. Лучшим решением для больших подсистем является использование блока синхронизации задач для представления ISR для подсистемы вызова функций.

Блок асинхронного прерывания генерирует вызовы для ISR. Поместите блок между моделируемым источником прерывания и одним из следующих:

  • Подсистема вызова функций

  • Блок синхронизации задач

  • Диаграмма Stateflow ®, настроенная для события ввода вызова функции

Для каждого указанного уровня прерывания блок генерирует ISR модуля Versa Eurocard (VME), который выполняет подключенную подсистему, блок синхронизации задач или диаграмму.

В примерной модели блок асинхронных прерываний конфигурируется для прерываний 1 и 2 VME с использованием смещений 192 и 193 векторов прерываний. Прерывание 1 подключается непосредственно к подсистеме Count. Прерывание 2 подключается к блоку синхронизации задач, который служит ISR для Algorithm. Поместите блок синхронизации задач в одно из следующих расположений:

  • Между блоком асинхронного прерывания и подсистемой функционального вызова или диаграммой Stateflow ®.

  • В выходном порту диаграммы Stateflow ®, имеющей событие ,Output to Simulink, который настраивается как вызов функции.

В примерной модели блок синхронизации задач находится между блоком асинхронного прерывания и подсистемой функционального вызова. Algorithm. Блок синхронизации задач настроен с именем задачи Task()приоритет 50, размер стека 8192 и передача данных задачи, синхронизированной с задачей вызывающего абонента. Порожденная задача использует семафор для синхронизации выполнения задачи. Блок асинхронного прерывания запускает освобождение семафора задачи.

Блоки четырехскоростного перехода обрабатывают передачу данных между портами, работающими на разных скоростях. В двух случаях блоки Protected Rate Transition защищают передачу данных (предотвращают их вытеснение и повреждение). В двух других случаях в блоках незащищенного перехода скорости отсутствует специальное поведение. Их присутствие информирует Simulink ® о переходе скорости.

Код, генерируемый для блоков асинхронного прерывания и синхронизации задач, адаптирован для примера RTOS (VxWorks ®). Однако блоки можно изменить для создания кода, специфичного для среды выполнения.

Допущения переноса данных

  • Передача данных происходит между одной задачей чтения и одной задачей записи.

  • Операция чтения или записи для переменной размера байта является атомной.

  • При взаимодействии двух задач только одна из них может вытеснить другую.

  • Для периодических задач задача с более высокой скоростью имеет более высокий приоритет, чем задача с более низкой скоростью. Задача с более высокой скоростью вытесняет задачи с более низкой скоростью.

  • Задачи выполняются на одном процессоре. Квантирование времени не допускается.

  • Процессы не останавливаются и не перезапускаются, особенно во время передачи данных между задачами.

Моделирование модели

Моделирование модели. По умолчанию модель настроена на отображение времени образца в различных цветах. Дискретное время выборки для ввода и вывода отображается красным и зеленым соответственно. Константы красновато-синие. Асинхронные прерывания и задачи фиолетовые. Блоки изменения скорости, которые представляют собой гибридную скорость (их входное и выходное время выборки может отличаться), имеют желтый цвет.

Создание кода и отчета

Создание кода и отчета о создании кода для модели. Сгенерированным кодом для блоков асинхронного прерывания и синхронизации задач является, например, 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 isr_num1_vec192 для прерывания 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 из блока синхронизации задач. Эта функция включает небольшое количество кода уровня прерывания и выполняется как задача RTOS.

Задача ждет в бесконечном for цикл до тех пор, пока система не освободит семафор синхронизации. Если система освобождает семафор, функция обновляет таймер задачи и вызывает код, сгенерированный для Algorithm подсистема.

В примерной модели устанавливается параметр Синхронизировать передачу данных этой задачи с параметром вызывающей задачи для блока Синхронизация задач. Этот параметр обновляет таймер, связанный с блоком синхронизации задач (rtM->Timing.clockTick2) со значением таймера, который является блоком асинхронного прерывания (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' */

Проверка кода завершения задачи

Блок синхронизации задач генерирует следующий код окончания.

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' */
}

Связанная информация

Связанные темы