Обработайте переходы уровня

Переходы уровня

Два периодических перехода частоты дискретизации могут существовать в модели:

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

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

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

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

Переходы быстрого не спешения проиллюстрированы в следующей фигуре.

Примечание

Несмотря на то, что блок Rate Transition предлагает надмножество возможностей блока Unit Delay (для переходов быстрого не спешения) и блока Zero-Order Hold (для быстрых-к-медленному переходов), необходимо использовать блок Rate Transition вместо этих блоков.

Проблемы передачи данных

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

  • Целостность данных: проблема целостности данных существует, когда вход с блоком изменяется во время выполнения того блока. Проблемы целостности данных могут быть вызваны вытеснением.

    Рассмотрите следующий сценарий:

    • Более быстрый блок подает входной сигнал с более медленным блоком.

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

    • Расчеты вытесняются другим выполнением более быстрого блока, который вычисляет новое выходное значение V2.

    • Проблема целостности данных теперь возникает: когда более медленный блок возобновляет выполнение, он продолжает свои расчеты, теперь с помощью “нового” входного значения V2.

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

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

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

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

Можно использовать блок Rate Transition, чтобы защитить передачи данных в приложении и сделать их детерминированными. Эти характеристики рассматриваются желательными в большинстве приложений. Однако блок Rate Transition поддерживает гибкие опции, которые позволяют вам ставить под угрозу целостность данных и детерминизм в пользу более низкой задержки. Следующий раздел обобщает эти опции.

Предположения передачи данных

При обработке передач данных между задачами генератор кода делает эти предположения:

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

  • Чтение или запись переменной размера байта являются атомарными.

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

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

  • Все задачи работают на одном процессоре. Квантование времени не позволено.

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

Опции блока перехода уровня

Несколько параметров блока Rate Transition относятся к его использованию в генерации кода для выполнения в реальном времени, как обсуждено ниже. Для полного описания блока смотрите Rate Transition.

Блок Rate Transition обрабатывает периодический (быстро, чтобы замедлиться и замедлиться к быстрому) и асинхронные переходы. Когда вставлено между двумя блоками отличающихся частот дискретизации, блок Rate Transition автоматически конфигурирует свои частоты дискретизации ввода и вывода для типа перехода; вы не должны задавать, является ли переход быстрым не спешением или быстрый-к-медленному (низкий-к-высокому или высокий к низким приоритетам для асинхронных задач).

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

  • Ensure data integrity during data transfer: Когда вы выбираете этот параметр, данные, переданные между уровнями, обеспечивают свою целостность (передача данных защищена). Когда вы очищаете этот параметр, данные не могут обеспечить свою целостность (передача данных незащищена). По умолчанию параметр Ensure data integrity during data transfer выбран.

  • Ensure deterministic data transfer (maximum delay): Этот параметр поддерживается для периодических задач со смещением нуля и высоких и низких скоростей, которые являются множителями друг друга. Выберите этот параметр для защищенных передач данных (когда Ensure data integrity during data transfer будет выбран). Когда этот параметр очищен, блок Rate Transition ведет себя как блок Zero-Order Hold (для быстро, чтобы замедлить переходы) или блок Unit Delay (для медленного к быстрым переходам). Блок Rate Transition управляет синхронизацией передачи данных абсолютно предсказуемым способом. Когда этот параметр очищен, передача данных недетерминирована. По умолчанию Ensure deterministic data transfer (maximum delay) выбран для переходов между периодическими уровнями со смещением нуля; для асинхронных переходов это не может быть выбрано.

Блок Rate Transition предлагает три режима работы относительно передачи данных. В порядке уровня безопасности:

  • Protected/Deterministic (default): Это - самый безопасный режим. Недостаток этого режима - то, что он вводит детерминированную задержку в систему для случая быстрого не спешения периодические переходы уровня. Для того случая задержка, введенная блоком Rate Transition, является одним периодом расчета более медленной задачи. Для случая быстрых-к-медленному периодических переходов уровня блок Rate Transition вводит, не вводит дополнительную задержку.

  • Protected/NonDeterministic: В этом режиме, для быстрого не спешения периодические переходы уровня, целостность данных защищена данными двойной буферизации, переданными между уровнями. Для быстрых-к-медленному периодических переходов уровня используется семафорный флаг. Блоки ниже блока Rate Transition используют последние доступные данные из блока, который управляет блоком Rate Transition. Максимальная задержка меньше чем или равна одному периоду расчета более быстрой задачи.

    Недостатки этого режима являются его недетерминированной синхронизацией. Преимуществом этого режима является своя низкая задержка.

  • Unprotected/NonDeterministic: Этот режим не рекомендуется для критически важных для миссии приложений. Задержка этого режима эквивалентна для режима Protected/NonDeterministic, но требования к памяти уменьшаются, ни начиная с требуются двойная буферизация, ни начиная с семафоры. Таким образом, блок Rate Transition ничего не делает в этом режиме кроме передать сигналы через; это просто существует, чтобы уведомить вас, что переход уровня существует (и может заставить сгенерированный код вычислять неправильные ответы). Выбор этого режима, однако, генерирует наименьшее количество объема кода.

    Примечание

    В незащищенном режиме (Ensure data integrity during data transfer выбран), блок Rate Transition делает ничто кроме не позволяет переходу уровня существовать в модели.

Блоки перехода уровня и непрерывное время

Шаг расчета в выходном порту блока Rate Transition может только быть дискретен или фиксирован в незначительном временном шаге. Это означает, что, когда блок Rate Transition наследовал время непрерывной выборки от своего целевого блока, это обрабатывает наследованный шаг расчета как Фиксированный в Незначительном Временном шаге. Поэтому выходная функция блока Rate Transition запускается только на главных временных шагах. Если целевой шаг расчета блока непрерывен, блок Rate Transition, выходной шаг расчета является шагом расчета базовой ставки (если решатель является фиксированным шагом), или нулевой порядок содержит время непрерывной выборки (если решатель является переменным шагом).

Автоматический переход уровня

Механизм Simulink может обнаружить переходы уровня, которым не соответствуют, в многозадачной модели во время схемы обновления и автоматически вставить блоки Перехода Уровня, чтобы обработать их. Чтобы включить это, выберите параметр конфигурации модели Automatically handle rate transition for data transfer. По умолчанию этот параметр очищен. Когда вы выбираете этот параметр:

  • Simulink обрабатывает переходы между периодическими шагами расчета и асинхронными задачами.

  • Simulink вставляет скрытые блоки Перехода Уровня в блок-схему.

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

  • Автоматически вставленные блоки Перехода Уровня действуют в защищенном режиме для периодических задач и асинхронных задач. Вы не можете изменить это поведение. Для периодических задач автоматически вставленные блоки Перехода Уровня управляют с уровнем детерминизма, заданного параметром конфигурации модели Deterministic data transfer. Настройкой по умолчанию является Whenever possible, который включает детерминизм для передач данных между периодическими шагами расчета, которые связаны целым числом несколько. Для получения дополнительной информации смотрите Детерминированную передачу данных (Simulink). Чтобы использовать другие режимы, необходимо вставить блоки Перехода Уровня и установить их режимы вручную.

Например, в этой модели, SineWave2 имеет шаг расчета 2, и SineWave3 имеет шаг расчета 3.

Когда вы выбираете параметр конфигурации модели Automatically handle rate transition for data transfer, Simulink вставляет блок Rate Transition между каждым блоком Sine Wave и блоком продукта. Вставленные блоки имеют значения параметров, чтобы согласовать шаги расчета блока Sine Wave.

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

Визуализируйте вставленные блоки перехода уровня

Когда вы выбираете параметр конфигурации модели Automatically handle rate transition for data transfer, Simulink вставляет блоки Перехода Уровня в пути, которые не соответствовали уровням перехода. Эти блоки скрыты по умолчанию. Чтобы визуализировать вставленные блоки, обновите схему. Метки значка появляются в модели и указывают, где Simulink вставил блоки Перехода Уровня во время фазы компиляции. Например, в этой модели, три блока Перехода Уровня были вставлены между двумя блоками Sine wave и Мультиплексором и Интегратором, когда модель скомпилировала. ZOH и метки значка DbBuf указывают на эти блоки.

Можно показать или скрыть метки значка. Откройте вкладку Debug. В разделе Diagnostics Information Overlays/Sample Time галерея выбирают или ясный Hidden Rate Transition Block Indicator.

Чтобы сконфигурировать скрытые блоки Перехода Уровня так, чтобы блоки отобразились, щелкните правой кнопкой по метке значка и нажмите Insert rate transition block.

Когда вы делаете скрытые блоки Перехода Уровня видимыми:

  • Вы видите тип вставленного блока Rate Transition и местоположение блока в модели.

  • Можно установить параметры блоков Initial Conditions.

  • Можно изменить настройки параметров блоков для передачи уровня.

Подтвердите изменения в своей модели путем обновления схемы.

Отображение вставленных блоков Перехода Уровня не совместимо с:

  • Среда параллельного выполнения

  • Модели экспорта функций

Чтобы узнать больше о типах блоков Перехода Уровня, смотрите Rate Transition.

Периодические переходы частоты дискретизации

Эти разделы описывают случаи, в которых блоки Перехода Уровня требуются для периодических переходов частоты дискретизации. Обсуждение и синхронизирующие схемы в этих разделах основаны на предположении, что блок Rate Transition используется в (защищенном/детерминированном) режиме его значения по умолчанию. Параметры конфигурации модели Ensure data integrity during data transfer и Ensure deterministic data transfer (maximum delay) выбраны. Это настройки, используемые в автоматически вставленных блоках Перехода Уровня.

Быстрее к более медленным переходам в модели Simulink

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

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

Быстрее к более медленным переходам в режиме реального времени

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

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

Чтобы избежать этой ситуации, механизм Simulink должен содержать выходные параметры 1 секунды (быстрее) блокируются, пока 2-секундные (медленнее) не блокируют выполнение концов. Способ выполнить это путем вставки блока Rate Transition между 1 вторым и 2-секундным блоком. Вход с более медленным блоком не изменяется во время его выполнения, обеспечивая целостность данных.

Это принято, что блок Rate Transition используется в (защищенном/детерминированном) режиме его значения по умолчанию.

Блок Rate Transition выполняется на уровне частоты дискретизации более медленного блока, но с приоритетом более быстрого блока.

Когда вы добавляете блок Rate Transition, блок выполняется перед 2-секундным блоком (его приоритет выше) и его выходным значением считается постоянным, в то время как 2-секундный блок выполняется (это выполняется на уровне более медленной частоты дискретизации).

Медленнее к более быстрым переходам в модели Simulink

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

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

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

Медленнее к более быстрым переходам в режиме реального времени

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

Эта схема синхронизации иллюстрирует две проблемы:

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

  • Более быстрый блок выполняется перед более медленным блоком (который является обратным от способа, которым симуляция Simulink действует). В этом случае 1 второй блок выполняется сначала; но входные параметры к более быстрой задаче не были вычислены. Это может вызвать непредсказуемые результаты.

Чтобы устранить эти проблемы, необходимо вставить блок Rate Transition между медленнее и более быстрые блоки.

Это принято, что блок Rate Transition используется в (защищенном/детерминированном) режиме его значения по умолчанию.

Следующий рисунок показывает последовательность синхронизации, которая заканчивается с добавленным блоком Rate Transition.

Три ключевых пункта о переходах в этой схеме (относятся к окруженным числам):

  1. Блок Rate Transition вывел запуски в 1 второй задаче, но на более медленном уровне (2 секунды). Выход блока Rate Transition питает 1 второй блок задачи.

  2. Обновление Перехода Уровня использует выход 2 вторых задач обновить ее внутреннее состояние.

  3. Выход Rate Transition в 1 второй задаче использует состояние Перехода Уровня, который был обновлен в 2 вторых задачах.

Первая проблема облегчена, потому что блок Rate Transition обновляется на более медленном уровне и на приоритете более медленного блока. Вход с блоком Rate Transition (который является выходом более медленного блока) читается после того, как более медленный блок завершает выполнение.

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

Примечание

Это использование блока Rate Transition изменяет модель. Выход более медленного блока теперь задерживается одним временным шагом по сравнению с выходом без блока Rate Transition.

Защитите целостность данных с volatile Ключевое слово

Когда вы выбираете параметр конфигурации модели Ensure data integrity during data transfer, код, сгенерированный для блока Rate Transition, задает глобальные буферы и семафоры и использует их, чтобы защитить целостность переданных данных.

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

С Embedded Coder® можно явным образом применить volatile к переданным данным путем применения встроенного пользовательского класса памяти Volatile к входу блока Rate Transition. Например, можно использовать этот метод, чтобы помочь защитить целостность данных, которые внешний код совместно использует со сгенерированным кодом.

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

Для получения дополнительной информации о применении volatile, смотрите Защищают Глобальные данные с const и энергозависимыми Спецификаторами Типа (Embedded Coder). Для получения дополнительной информации о GetSet, см. Доступ к данным Через Функции с Классом памяти GetSet (Embedded Coder).

Отдельный уровень блочный код Transtion и данные из кода алгоритма и данные

Можно задать, встраивает ли генератор кода код и данные, которые это производит для блоков Перехода Уровня с типовым кодексом или помещает код и данные в отдельных функциях, которые вызывает типовой кодекс. Вы управляете этим путем выбора параметра блочного кода Перехода Уровня. Разделение блочного кода Перехода Уровня и данных из кода алгоритма и данных позволяет вам независимо анализировать, оптимизировать, и протестировать блок Rate Transition и код алгоритма. По умолчанию блочный код Перехода Уровня установлен встроенный с кодом алгоритма и данными. Можно разделить код и данные так, чтобы сгенерированный код содержал отдельный get и set функции, что model_step вызов функций и специализированная структура для данных состояния. Сгенерированный код также содержит отдельный start и initialize функции, что model_initialize вызовы функции.

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

Откройте модель <matlab:rtwdemo_ratetrans rtwdemo_ratetrans>. Эта многоскоростная, многозадачная модель содержит несколько блоков Перехода Уровня, действующих в различных режимах.

open_system('rtwdemo_ratetrans');
set_param('rtwdemo_ratetrans','SystemTargetFile','ert.tlc');
set_param('rtwdemo_ratetrans','GenerateComments', 'Off');

Отдельный Код для блоков Перехода Уровня

В диалоговом окне Configuration Parameters параметр блочного кода Перехода Уровня устанавливается на Function. Сгенерируйте код для модели. Код находится в файлах rtwdemo_ratetrans.c и rtwdemo_ratetrans.h.

currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild('rtwdemo_ratetrans');
### Starting build procedure for model: rtwdemo_ratetrans
### Successful completion of build procedure for model: rtwdemo_ratetrans
hfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.h');
rtwdemodbtype(hfile,'typedef struct {','} DW;', 1, 1);
typedef struct {
  real_T OutportBufferForOut3[20];
  real_T Integrator1_DSTATE[20];
  real_T Integrator2_DSTATE[20];
  real_T Integrator3_DSTATE[20];
  real_T Integrator1_PREV_U[20];
  real_T Integrator2_PREV_U[20];
  real_T Integrator3_PREV_U[20];
  uint32_T Algorithm_PREV_T;
  struct {
    uint_T Algorithm_RESET_ELAPS_T:1;
  } bitsForTID1;

  uint8_T Integrator1_SYSTEM_ENABLE;
  uint8_T Integrator2_SYSTEM_ENABLE;
  uint8_T Integrator3_SYSTEM_ENABLE;
} DW;

Для блоков Перехода Уровня данные состояния не находятся в глобальной структуре состояния, DW_rtwdemo_ratetrans_T. Эти данные находятся в его собственной структуре в файле rtwdemo_ratetrans_rtb.h.

Этот код находится в файле rtwdemo_ratetrans.c.

cfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.c');
rtwdemodbtype(cfile,'void rtwdemo_ratetrans_step0','void rtwdemo_ratetrans_terminate(void)', 1, 0);
void rtwdemo_ratetrans_step0(void)
{
  (rtM->Timing.RateInteraction.TID0_1)++;
  if ((rtM->Timing.RateInteraction.TID0_1) > 1) {
    rtM->Timing.RateInteraction.TID0_1 = 0;
  }

  rtwdemo_rate_DetAndIntegS2F_get(rtY.Out1);
  rtwdemo_ratetr_IntegOnlyS2F_get(rtY.Out2);
  memcpy(&rtY.Out3[0], &rtDW.OutportBufferForOut3[0], 20U * sizeof(real_T));
  rtwdemo_rate_DetAndIntegF2S_set(rtU.In1);
  rtwdemo_ratetr_IntegOnlyF2S_set(rtU.In2);
}

void rtwdemo_ratetrans_step1(void)
{
  real_T rtb_DetAndIntegF2S[20];
  real_T rtb_IntegOnlyF2S[20];
  uint32_T Algorithm_ELAPS_T;
  int32_T i;
  real_T tmp;
  rtwdemo_rate_DetAndIntegF2S_get(rtb_DetAndIntegF2S);
  rtwdemo_ratetr_IntegOnlyF2S_get(rtb_IntegOnlyF2S);
  if (rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T) {
    Algorithm_ELAPS_T = 0U;
  } else {
    Algorithm_ELAPS_T = rtM->Timing.clockTick1 - rtDW.Algorithm_PREV_T;
  }

  rtDW.Algorithm_PREV_T = rtM->Timing.clockTick1;
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = false;
  tmp = 0.001 * (real_T)Algorithm_ELAPS_T;
  for (i = 0; i < 20; i++) {
    if (rtDW.Integrator1_SYSTEM_ENABLE == 0) {
      rtDW.Integrator1_DSTATE[i] += tmp * rtDW.Integrator1_PREV_U[i];
    }

    if (rtDW.Integrator2_SYSTEM_ENABLE == 0) {
      rtDW.Integrator2_DSTATE[i] += tmp * rtDW.Integrator2_PREV_U[i];
    }

    if (rtDW.Integrator3_SYSTEM_ENABLE == 0) {
      rtDW.Integrator3_DSTATE[i] += tmp * rtDW.Integrator3_PREV_U[i];
    }

    rtDW.OutportBufferForOut3[i] = rtDW.Integrator3_DSTATE[i];
    rtDW.Integrator1_PREV_U[i] = rtb_DetAndIntegF2S[i];
    rtDW.Integrator2_PREV_U[i] = rtb_IntegOnlyF2S[i];
    rtDW.Integrator3_PREV_U[i] = rtU.In3[i];
  }

  rtDW.Integrator1_SYSTEM_ENABLE = 0U;
  rtDW.Integrator2_SYSTEM_ENABLE = 0U;
  rtDW.Integrator3_SYSTEM_ENABLE = 0U;
  rtwdemo_rate_DetAndIntegS2F_set(rtDW.Integrator1_DSTATE);
  rtwdemo_ratetr_IntegOnlyS2F_set(rtDW.Integrator2_DSTATE);
  rtM->Timing.clockTick1++;
}

void rtwdemo_ratetrans_initialize(void)
{
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = true;
  rtDW.Integrator1_SYSTEM_ENABLE = 1U;
  rtDW.Integrator2_SYSTEM_ENABLE = 1U;
  rtDW.Integrator3_SYSTEM_ENABLE = 1U;
}

rtwdemo_ratetrans_step0 и rtwdemo_ratetrans_step1 функции содержат вызовы get и set функции. Эти функции содержат блочный код Перехода Уровня. Эти функциональные определения находятся в файле rtwdemo_ratetrans_rtb.c.

Сгенерируйте Встроенный Код для блоков Перехода Уровня

В диалоговом окне Configuration Parameters, установленном параметр блочного кода Перехода Уровня на Inline. Сгенерируйте код для модели. Код находится в файлах rtwdemo_ratetrans.c и rtwdemo_ratetrans.h.

set_param('rtwdemo_ratetrans','RateTransitionBlockCode','Inline');
rtwbuild('rtwdemo_ratetrans')
### Starting build procedure for model: rtwdemo_ratetrans
### Successful completion of build procedure for model: rtwdemo_ratetrans

Этот код находится теперь в файле rtwdemo_ratetrans.h.

hfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.h');
rtwdemodbtype(hfile, 'typedef struct {', '} DW;', 1, 1);
typedef struct {
  real_T Integrator1_DSTATE[20];
  real_T Integrator2_DSTATE[20];
  real_T Integrator3_DSTATE[20];
  real_T DetAndIntegS2F_Buffer0[20];
  volatile real_T IntegOnlyS2F_Buffer[40];
  real_T DetAndIntegF2S_Buffer[20];
  volatile real_T IntegOnlyF2S_Buffer0[20];
  real_T Integrator1_PREV_U[20];
  real_T Integrator2_PREV_U[20];
  real_T Integrator3_PREV_U[20];
  uint32_T Algorithm_PREV_T;
  struct {
    uint_T Algorithm_RESET_ELAPS_T:1;
  } bitsForTID1;

  volatile int8_T IntegOnlyS2F_ActiveBufIdx;
  volatile int8_T IntegOnlyF2S_semaphoreTaken;
  uint8_T Integrator1_SYSTEM_ENABLE;
  uint8_T Integrator2_SYSTEM_ENABLE;
  uint8_T Integrator3_SYSTEM_ENABLE;
} DW;

Для блоков Перехода Уровня данные состояния не находятся в глобальной структуре состояния, DW_rtwdemo_ratetrans_T. Эти данные находятся в его собственной структуре в файле rtwdemo_ratetrans_rtb.h.

Этот код находится теперь в файле rtwdemo_ratetrans_rtb.c.

cfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.c');
rtwdemodbtype(cfile,'void rtwdemo_ratetrans_step0','void rtwdemo_ratetrans_terminate(void)', 1, 0);
void rtwdemo_ratetrans_step0(void)
{
  int32_T i;
  int32_T i_0;
  (rtM->Timing.RateInteraction.TID0_1)++;
  if ((rtM->Timing.RateInteraction.TID0_1) > 1) {
    rtM->Timing.RateInteraction.TID0_1 = 0;
  }

  if (rtM->Timing.RateInteraction.TID0_1 == 1) {
    memcpy(&rtY.Out1[0], &rtDW.DetAndIntegS2F_Buffer0[0], 20U * sizeof(real_T));
  }

  i = rtDW.IntegOnlyS2F_ActiveBufIdx * 20;
  for (i_0 = 0; i_0 < 20; i_0++) {
    rtY.Out2[i_0] = rtDW.IntegOnlyS2F_Buffer[i_0 + i];
  }

  if (rtM->Timing.RateInteraction.TID0_1 == 1) {
    memcpy(&rtDW.DetAndIntegF2S_Buffer[0], &rtU.In1[0], 20U * sizeof(real_T));
  }

  if (rtDW.IntegOnlyF2S_semaphoreTaken == 0) {
    for (i = 0; i < 20; i++) {
      rtDW.IntegOnlyF2S_Buffer0[i] = rtU.In2[i];
    }
  }
}

void rtwdemo_ratetrans_step1(void)
{
  real_T rtb_IntegOnlyF2S[20];
  uint32_T Algorithm_ELAPS_T;
  int32_T i;
  real_T tmp;
  rtDW.IntegOnlyF2S_semaphoreTaken = 1;
  for (i = 0; i < 20; i++) {
    rtb_IntegOnlyF2S[i] = rtDW.IntegOnlyF2S_Buffer0[i];
  }

  rtDW.IntegOnlyF2S_semaphoreTaken = 0;
  if (rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T) {
    Algorithm_ELAPS_T = 0U;
  } else {
    Algorithm_ELAPS_T = rtM->Timing.clockTick1 - rtDW.Algorithm_PREV_T;
  }

  rtDW.Algorithm_PREV_T = rtM->Timing.clockTick1;
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = false;
  tmp = 0.001 * (real_T)Algorithm_ELAPS_T;
  for (i = 0; i < 20; i++) {
    if (rtDW.Integrator1_SYSTEM_ENABLE == 0) {
      rtDW.Integrator1_DSTATE[i] += tmp * rtDW.Integrator1_PREV_U[i];
    }

    if (rtDW.Integrator2_SYSTEM_ENABLE == 0) {
      rtDW.Integrator2_DSTATE[i] += tmp * rtDW.Integrator2_PREV_U[i];
    }

    if (rtDW.Integrator3_SYSTEM_ENABLE != 0) {
      rtY.Out3[i] = rtDW.Integrator3_DSTATE[i];
    } else {
      rtY.Out3[i] = tmp * rtDW.Integrator3_PREV_U[i] + rtDW.Integrator3_DSTATE[i];
    }

    rtDW.Integrator1_PREV_U[i] = rtDW.DetAndIntegF2S_Buffer[i];
    rtDW.Integrator2_PREV_U[i] = rtb_IntegOnlyF2S[i];
    rtDW.Integrator3_DSTATE[i] = rtY.Out3[i];
    rtDW.Integrator3_PREV_U[i] = rtU.In3[i];
    rtDW.DetAndIntegS2F_Buffer0[i] = rtDW.Integrator1_DSTATE[i];
  }

  rtDW.Integrator1_SYSTEM_ENABLE = 0U;
  rtDW.Integrator2_SYSTEM_ENABLE = 0U;
  rtDW.Integrator3_SYSTEM_ENABLE = 0U;
  for (i = 0; i < 20; i++) {
    rtDW.IntegOnlyS2F_Buffer[i + (rtDW.IntegOnlyS2F_ActiveBufIdx == 0) * 20] =
      rtDW.Integrator2_DSTATE[i];
  }

  rtDW.IntegOnlyS2F_ActiveBufIdx = (int8_T)(rtDW.IntegOnlyS2F_ActiveBufIdx == 0);
  rtM->Timing.clockTick1++;
}

void rtwdemo_ratetrans_initialize(void)
{
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = true;
  rtDW.Integrator1_SYSTEM_ENABLE = 1U;
  rtDW.Integrator2_SYSTEM_ENABLE = 1U;
  rtDW.Integrator3_SYSTEM_ENABLE = 1U;
}

Код встраивается в функциях rtwdemo_ratetrans_step0 и rtwdemo_ratetrans_step1.

Ограничение

Генератор кода не разделяет код и данные для блоков Перехода Уровня, которые имеют сигналы переменного размера или являются в Для Каждого блока Subsystem.

Смотрите также

bdclose('rtwdemo_ratetrans');
rtwdemoclean;
cd(currentDir)

Похожие темы