exponenta event banner

Выполнение кода, созданного из модели

Генератор кода создает алгоритмический код, определенный в модели. Внешний (например, пользовательский или устаревший) код можно включить в модель с помощью методов, описанных в разделе Выбор потока операций интеграции внешнего кода.

Генератор кода также предоставляет интерфейс, который выполняет сгенерированный код модели. Интерфейс и код модели компилируются вместе для создания исполняемой программы. На следующем рисунке показан объектно-ориентированный вид исполняемого файла высокого уровня.

Объектно-ориентированный вид программы в реальном времени

В целом концептуальный дизайн драйвера исполнения модели не меняется между быстрым прототипированием и встроенным стилем генерируемого кода. В следующих разделах описывается выполнение модели для однозадачных и многозадачных сред как для моделирования (не в реальном времени), так и для реального времени. Для большинства модельных кодов многозадачная среда обеспечивает наиболее эффективное выполнение модели (то есть наиболее высокую частоту дискретизации).

Следующие понятия полезны при описании выполнения кода модели.

  • Инициализация: model_initialize инициализирует код интерфейса и код модели.

  • ModelOutputs: вызывает в модели блоки, у которых в текущий момент времени имеется пробный удар, и выводит их. model_output может быть выполнено в основных или второстепенных временных шагах. В основных временных шагах выходные данные являются заданным временным шагом моделирования. Во второстепенных временных шагах интерфейс интегрирует производные для обновления непрерывных состояний.

  • ModelUpdate: model_update вызывает блоки, которые имеют выборку попаданий в текущий момент времени и которые обновляют свои дискретные состояния или объекты аналогичного типа.

  • ModelDerivatives: вызывает в модели блоки с непрерывными состояниями и обновляет их производные. model_derivatives вызывается только во второстепенных временных шагах.

  • ModelTerminate: model_terminate завершает программу, если она предназначена для выполнения в течение конечного времени. Он разрушает структуру данных модели в реальном времени, освобождает память и может записывать данные в файл.

Выполнение программы

Программа реального времени не может требовать 100% времени ЦП. Это требование предоставляет возможность выполнения фоновых задач в свободное время.

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

Однако важно, чтобы программа была способна предвосхищать фоновую задачу, чтобы код модели мог выполняться в реальном времени.

Способ управления задачами программы зависит от возможностей среды, в которой она работает.

Программная синхронизация

Программы реального времени требуют тщательной синхронизации вызовов задачи (либо с помощью прерывания, либо с помощью примитива задания операционной системы в реальном времени), чтобы код модели выполнялся до завершения, прежде чем произойдет другой вызов задачи. Синхронизация включает в себя время на считывание и запись данных во внешние аппаратные средства и из них.

На следующем рисунке показана синхронизация прерывания.

Тайминг задачи

Интервал выборки должен быть достаточно длинным, чтобы разрешить выполнение кода модели между вызовами задачи.

На рисунке выше время между двумя соседними вертикальными стрелками является интервалом выборки. Пустые поля на верхней диаграмме показывают пример программы, которая может выполнить один шаг в пределах интервала и по-прежнему выделять время для фоновой задачи. Серый прямоугольник на нижней диаграмме показывает, что происходит, если интервал выборки слишком короткий. Еще один вызов задачи происходит до ее завершения. Такая синхронизация приводит к ошибке выполнения.

Если программа в реальном времени предназначена для работы вечно (то есть, конечное время равно 0 или бесконечно, так что while loop never exits), то код отключения не выполняется.

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

Связь во внешнем режиме

Внешний режим обеспечивает связь между блок-схемой Simulink ® и автономной программой, созданной на основе сгенерированного кода. В этом режиме программа реального времени функционирует как сервер межпроцессной связи, отвечая на запросы от механизма Simulink .

Регистрация данных в однозадачной и многозадачной модели

Настройка модели для отладки объясняет, как можно сохранить состояния системы, выходные данные и время в MAT-файле по завершении выполнения модели. LogTXY функция, выполняющая регистрацию данных, работает по-разному в однозадачных и многозадачных средах.

Если вы посмотрите, как LogTXY вызывается в однозадачных и многозадачных средах, обратите внимание, что для однозадачных LogTXY вызывается после ModelOutputs. Во время этого ModelOutputs вызов, блоки, которые имеют попадание в момент времени t выполнения, в то время как в многозадачности, LogTXY вызывается после ModelOutputs(tid=0), который выполняет только блоки, имеющие совпадение в момент времени t и идентификатор задачи 0. Это приводит к различиям в записанных значениях между однозадачным и многозадачным протоколированием. В частности, рассмотрим модель с двумя временами выборки, более быстрым временем выборки, имеющим период 1,0 секунды, и более медленным временем выборки, имеющим период 10,0 секунды. В момент времени t = k * 10, k = 0,1,2... оба быстрых (tid=0) и медленно (tid=1) блоки выполняются. При выполнении в многозадачном режиме, когда LogTXY вызывается, медленные блоки выполняются, но регистрируется предыдущее значение, в то время как в однозадачном режиме регистрируется текущее значение.

Другое различие возникает при регистрации данных в включенной подсистеме. Рассмотрим включенную подсистему, которая имеет медленный сигнал, управляющий разрешающим портом и быстрыми блоками в разрешенной подсистеме. В этом случае оценка сигнала разрешения происходит в медленной задаче, и быстрые блоки видят задержку в один период выборки; таким образом, регистрируемые значения будут показывать эти различия.

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

  • Корневой выходной блок имеет время выборки, более медленное, чем самое быстрое время выборки

  • Блок с состояниями имеет время выборки, более медленное, чем самое быстрое время выборки

  • Блок в разрешенной подсистеме, где сигнал, управляющий разрешенным портом, медленнее скорости блоков в разрешенной подсистеме

В первых двух случаях, несмотря на то, что значения в журнале различаются между однозадачностью и многозадачностью, результаты модели не отличаются. Единственная реальная разница заключается в том, где (в какой момент времени) производится регистрация. Третий случай (включенная подсистема) приводит к задержке, которую можно увидеть в среде реального времени.

Однозадачные системы не реального времени

Этот псевдокод показывает выполнение модели для однозадачной системы не реального времени.

main()
{
  Initialization
  While (time < final time)
    ModelOutputs     -- Major time step.
    LogTXY           -- Log time, states and root outports.
    ModelUpdate      -- Major time step.
    Integrate        -- Integration in minor time step for 
                     -- models with continuous states.
      ModelDerivatives
      Do 0 or more
        ModelOutputs
        ModelDerivatives
      EndDo -- Number of iterations depends upon the solver
      Integrate derivatives to update continuous states.
    EndIntegrate
  EndWhile
  Termination
}

Сначала начинается этап инициализации. Это состоит из инициализации состояний модели и настройки механизма выполнения. Затем модель выполняется по одному шагу. Сначала ModelOutputs выполняется в момент времени t, затем регистрируются данные ввода-вывода рабочей области, а затем ModelUpdate обновляет дискретные состояния. Далее, если модель имеет непрерывные состояния, ModelDerivatives интегрирует производные непрерывных состояний для генерации состояний для времени tnew = t + h, где h - размер шага. Затем время переходит на tnew, и процесс повторяется.

Во время ModelOutputs и ModelUpdate фазы выполнения модели, выполняются только блоки, достигающие текущего момента времени.

Многозадачные системы не реального времени

Этот псевдокод показывает выполнение модели для многозадачной системы, работающей не в реальном времени.

main()
{
  Initialization
  While (time < final time)
    ModelOutputs(tid=0)   -- Major time step.
    LogTXY                -- Log time, states, and root 
                          -- outports.
    ModelUpdate(tid=0)    -- Major time step.
    Integrate       -- Integration in minor time step for 
                    -- models with continuous states.
      ModelDerivatives
      Do 0 or more
        ModelOutputs(tid=0)
        ModelDerivatives
      EndDo (Number of iterations depends upon the solver.)
      Integrate derivatives to update continuous states.
    EndIntegrate
    For i=1:NumTids
      ModelOutputs(tid=i) -- Major time step.
      ModelUpdate(tid=i)  -- Major time step.
    EndFor
  EndWhile
  Termination
  }

Многозадачность более сложна, чем однозадачность, поскольку функции вывода и обновления подразделяются на идентификаторы задач (tid), который передается в эти функции. Это позволяет выполнять несколько вызовов этих функций с различными идентификаторами задач, используя перекрывающиеся прерывания, или для нескольких задач при использовании операционной системы реального времени. При моделировании несколько задач эмулируются путем выполнения кода в порядке, который имел бы место, если бы в системе реального времени не существовало преимущественного освобождения.

Выполнение в многозадачном режиме предполагает, что скорости выполнения задач кратны базовой скорости. Продукт Simulink обеспечивает это при создании многозадачной модели с фиксированным шагом. Цикл выполнения многозадачности очень похож на цикл однозадачности, за исключением использования идентификатора задачи (tid) аргумент для ModelOutputs и ModelUpdate.

Вы не можете использовать tid значения из кода, созданного целевым файлом, а не Simulink Coder™. Simulink Coder отслеживает использование tid при создании кода для определенной подсистемы или типа функции. При создании кода в целевом файле этот аргумент не может быть отслежен, поскольку в области отсутствует подсистема или тип функции. Поэтому tid становится неопределенной переменной, и конечный файл не может быть скомпилирован.

Однозадачные системы реального времени

Этот псевдокод показывает выполнение модели в однозадачной системе реального времени, где модель выполняется на уровне прерывания.

rtOneStep()
{
  Check for interrupt overflow
  Enable "rtOneStep" interrupt
  ModelOutputs    -- Major time step.
  LogTXY          -- Log time, states and root outports.
  ModelUpdate     -- Major time step.
  Integrate       -- Integration in minor time step for models 
                  -- with continuous states.
     ModelDerivatives
     Do 0 or more 
       ModelOutputs
       ModelDerivatives
     EndDo (Number of iterations depends upon the solver.)
     Integrate derivatives to update continuous states.
  EndIntegrate
}

main()
{
  Initialization (including installation of rtOneStep as an 
  interrupt service routine, ISR, for a real-time clock).
  While(time < final time)
    Background task.
  EndWhile
  Mask interrupts (Disable rtOneStep from executing.)
  Complete any background tasks.
  Shutdown
}

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

В интервале, заданном базовой частотой дискретизации программы, подпрограмма обслуживания прерываний (ISR) прерывает фоновую задачу для выполнения кода модели. Базовая частота выборки является самой быстрой в модели. Если модель имеет непрерывные блоки, то размер шага интегрирования определяет базовую частоту дискретизации.

Например, если код модели представляет собой контроллер, работающий на частоте 100 Гц, то каждые 0,01 секунды фоновая задача прерывается. Во время этого прерывания контроллер считывает свои входы с аналого-цифрового преобразователя (АЦП), вычисляет свои выходы, записывает эти выходы в цифроаналоговый преобразователь (ЦАП) и обновляет его состояния. Затем элемент управления программой возвращается к фоновой задаче. Эти шаги должны быть выполнены до следующего прерывания.

Многозадачные системы реального времени

Этот псевдокод показывает, как модель выполняется в многозадачной системе реального времени, где модель выполняется на уровне прерывания.

rtOneStep()
{
  Check for interrupt overflow
  Enable "rtOneStep" interrupt
  ModelOutputs(tid=0)     -- Major time step.
  LogTXY                  -- Log time, states and root outports.
  ModelUpdate(tid=0)      -- Major time step.
  Integrate               -- Integration in minor time step for 
                          -- models with continuous states.
     ModelDerivatives
     Do 0 or more
       ModelOutputs(tid=0)
       ModelDerivatives
     EndDo (Number of iterations depends upon the solver.)
     Integrate derivatives and update continuous states.
  EndIntegrate
  For i=1:NumTasks
    If (hit in task i)
      ModelOutputs(tid=i)
      ModelUpdate(tid=i)
    EndIf
  EndFor
}

main()
{
  Initialization (including installation of rtOneStep as an 
    interrupt service routine, ISR, for a real-time clock).
  While(time < final time)
    Background task.
  EndWhile
  Mask interrupts (Disable rtOneStep from executing.) 
  Complete any background tasks.
  Shutdown
}

Выполнение моделей на уровне прерываний в многозадачной среде реального времени очень похоже на предыдущую однозадачную среду, за исключением того, что для одновременного выполнения задач используются перекрывающиеся прерывания.

Выполнение модели в однозадачной или многозадачной среде при использовании примитивов задания операционной системы в реальном времени очень похоже на примеры уровня прерывания, рассмотренные выше. Приведенный ниже псевдокод предназначен для однозадачной модели, использующей примитивы задания в реальном времени.

tSingleRate()
{
  MainLoop:
    If clockSem already "given", then error out due to overflow.
    Wait on clockSem
    ModelOutputs            -- Major time step.
    LogTXY                  -- Log time, states and root 
                            -- outports
    ModelUpdate             -- Major time step
    Integrate               -- Integration in minor time step 
                            -- for models with continuous 
                            -- states.
      ModelDeriviatives
      Do 0 or more
        ModelOutputs
        ModelDerivatives
      EndDo (Number of iterations depends upon the solver.)
      Integrate derivatives to update continuous states.
    EndIntegrate
  EndMainLoop
}

main()
{
  Initialization
  Start/spawn task "tSingleRate".
  Start clock that does a "semGive" on a clockSem semaphore.
  Wait on "model-running" semaphore.
  Shutdown
}

В этой однозадачной среде модель выполняется как примитивы задач операционной системы реального времени. В этой среде создайте одну задачу (tSingleRate) для запуска кода модели. Эта задача вызывается, когда возникает отметка времени. Тик часов дает clockSem (семафор часов) к задаче модели (tSingleRate). Задача модели ожидает семафора перед выполнением. Засечки часов имеют размер основного шага (базовая частота) для модели.

Многозадачные системы, использующие примитивы задания в реальном времени

Этот псевдокод предназначен для многозадачной модели, использующей примитивы задания в реальном времени.

tSubRate(subTaskSem,i)
{
  Loop:
    Wait on semaphore subTaskSem.
    ModelOutputs(tid=i)
    ModelUpdate(tid=i)
  EndLoop
}
tBaseRate()
{
  MainLoop:
    If clockSem already "given", then error out due to overflow.
    Wait on clockSem
    For i=1:NumTasks
      If (hit in task i)
        If task i is currently executing, then error out due to 
          overflow.
        Do a "semGive" on subTaskSem for task i.
      EndIf
    EndFor
    ModelOutputs(tid=0)    -- major time step.
    LogTXY                 -- Log time, states and root outports.
    ModelUpdate(tid=0)     -- major time step.
    Loop:                  -- Integration in minor time step for 
                           -- models with continuous states.
      ModelDeriviatives
      Do 0 or more
        ModelOutputs(tid=0)
        ModelDerivatives
      EndDo (number of iterations depends upon the solver).
      Integrate derivatives to update continuous states.
    EndLoop
  EndMainLoop
}
main()
{
  Initialization
  Start/spawn task "tSubRate".
  Start/spawn task "tBaseRate".

  Start clock that does a "semGive" on a clockSem semaphore.
  Wait on "model-running" semaphore.
  Shutdown
}

В этой многозадачной среде модель выполняется с использованием примитивов задания операционной системы реального времени. Такие среды требуют нескольких задач модели (tBaseRate и несколько tSubRate задачи) для запуска кода модели. Задача базовой ставки (tBaseRate) имеет более высокий приоритет, чем задачи подскоростной передачи. Подскоростная задача для tid=1 имеет более высокий приоритет, чем подскоростная задача для tid=2и так далее. Задача базовой скорости вызывается, когда возникает отметка тактового сигнала. Тик часов дает clockSem кому tBaseRate. Первое, что tBaseRate дает семафоры подзаданиям, которые имеют совпадение в текущий момент времени. Поскольку задача базовой скорости имеет более высокий приоритет, она продолжает выполняться. Далее выполняется самая быстрая задача (tid=0), состоящий из блоков в вашей модели, которые имеют самое быстрое время выборки. После этого выполнения он возобновляет ожидание семафора часов. Такты часов настраиваются так, чтобы они имели размер основного шага для модели.

Быстрое создание прототипов и различия в исполнении встроенных моделей

Структура программы быстрого прототипирования обеспечивает общий интерфейс прикладного программирования (API), который не изменяется между определениями модели.

Продукт Embedded Coder ® предоставляет другую структуру, называемую структурой встраиваемых программ. Встроенная программная платформа обеспечивает оптимизированный API, адаптированный к вашей модели. При использовании встроенного стиля сгенерированного кода выполняется моделирование того, как код должен выполняться во встроенной системе. Поэтому определения, определенные в модели, должны быть специфичными для встроенных целей. Такие элементы, как имя модели, параметр и класс хранения сигналов, включаются как часть API для встроенного стиля кода.

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

Таким образом, код выполнения модели устраняет Loop...EndLoop операторы и группы ModelOutputs, LogTXY, и ModelUpdate в одном операторе, model_step.

Дополнительные сведения о выполнении созданного встроенного кода см. в разделе Настройка генерации кода C для функций точек входа модели.

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