Породите и синхронизируйте выполнение задачи RTOS

В этом примере показано, как симулировать и сгенерировать код для асинхронных событий в многозадачной системе в реальном времени. Модель содержит блок Async Interrupt, блок Task Sync, асинхронно выполнил подсистемы Count и Algorithm, и блоки Перехода Уровня. Блок Async Interrupt создает две процедуры обработки прерывания Еврокарты модуля Versa (VME) (ISRs), которые передают сигналы прерывания подсистеме Count и блок Task Sync. | количество | выполняется на уровне прерывания. Algorithm выполняется как асинхронная задача. Код, который генератор кода производит для подсистем, адаптируется для операционной системы VxWorks®.

О модели в качестве примера

Откройте модель rtwdemo_async в качестве примера.

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

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

  • Блок Task Sync

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

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

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

Count представляет простую процедуру обработки прерывания (ISR), которая выполняется на уровне прерывания. Лучше сохранять ISRs максимально простым. Эта подсистема включает только блок Discrete-Time Integrator.

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

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

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

  • Блок Task Sync

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

Для каждого заданного уровня прерывания блок генерирует ISR Еврокарты модуля Versa (VME), который выполняет связанную подсистему, блок Task Sync или график.

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

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

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

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

Четыре Перехода Уровня блокируют передачи данных указателя между портами, которые действуют на различных уровнях. В двух экземплярах Защищенные блоки Перехода Уровня защищают передачи данных (препятствуйте тому, чтобы они были вытеснены и повреждены). В других двух экземплярах Незащищенные блоки Перехода Уровня не вводят специального поведения. Их присутствие сообщает 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.2219s

Рассмотрите код инициализации

Откройте сгенерированный исходный файл 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 от блока Task Sync. Эта функция включает небольшое количество кода уровня прерывания и запускается как задача 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): '<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_num1_vec192 ISRs и 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' */
}

Сопутствующая информация

Похожие темы