Сгенерируйте модульный функциональный код для невиртуальных подсистем

О невиртуальной генерации кода подсистемы

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

Чтобы сгенерировать модульный функциональный код для невиртуальных подсистем, включая атомарные подсистемы и условно выполняемые подсистемы, используют параметры блоков подсистемы Function with separate data. Эти параметры блоков дают генератору кода команду производить структуру данных блока I/O и DWork для невиртуальной функции подсистемы, которая независима от структур данных родительской модели. В результате сгенерированный код для подсистемы:

  • Легче проследить.

  • Легче протестировать.

  • Уменьшает размер структур глобальных данных модели.

Использовать параметр Function with separate data,

  • Сконфигурируйте модель с основанным на ERT системным конечным файлом.

  • Сконфигурируйте подсистему, чтобы быть атомарными или условно выполненными.

  • Установите параметры блоков подсистемы Function packaging на Nonreusable function.

Чтобы сконфигурировать вашу подсистему для генерации модульного функционального кода, вызовите диалоговое окно Subsystem Parameters и сделайте ряд выборов, чтобы отобразить и включить опцию Function with separate data. Смотрите Конфигурируют Подсистему для Генерации Модульного Функционального Кода и Модульного Функционального Кода для Невиртуальных Подсистем для деталей. Для ограничений, которые применяются, смотрите Невиртуальную Подсистему Модульные Функциональные Ограничения Кода.

Для получения дополнительной информации о генерации кода для атомарных подсистем, смотрите Генерацию Управления разделами Функций для Подсистем (Simulink Coder) и Сгенерируйте Код и Исполняемые файлы для Отдельных Подсистем (Simulink Coder).

Сконфигурируйте подсистему для генерации модульного функционального кода

  1. Проверьте, что модель, содержащая подсистему, использует основанный на ERT системный конечный файл.

  2. Выберите подсистему, для которой вы хотите сгенерировать модульный функциональный код и открыть диалоговое окно Subsystem Parameters. Диалоговое окно для атомарной подсистемы показывают ниже. (В диалоговом окне для условно выполняемой подсистемы опция диалогового окна отображается серым Treat as atomic unit, и можно пропустить Шаг 3.)

  3. Если параметры блоков, Treat as atomic unit доступен для выбора, но не выбранный, подсистема, не являются ни атомарными, ни условно выполнены. Выберите параметр Treat as atomic unit, который включает параметр Function packaging на вкладке Code Generation. Выберите вкладку Code Generation.

  4. Для параметра Function packaging выберите Nonreusable function. После того, как вы сделаете этот выбор, параметр Function with separate data отображен.

    Прежде чем вы будете генерировать код для невиртуальной подсистемы выбранным параметром Function with separate data, будете считать код производящей функции параметром очищенным и будете сохранять сгенерированный функциональный .c и .h файлы в отдельной директории для более позднего сравнения.

  5. Выберите параметр Function with separate data. Появляются дополнительные параметры.

    Чтобы управлять именованием сгенерированной функции подсистемы и файлов подсистемы, измените параметры подсистемы Function name options и File name options.

  6. Сохраните свои изменения параметра подсистемы и выйдите из диалогового окна путем нажатия на OK.

  7. Сгенерируйте код для подсистемы и исследуйте сгенерированные файлы, включая функциональный .c и .h файлы с именем согласно вашим спецификациям параметра подсистемы.

Для получения дополнительной информации о генерации кода для невиртуальных подсистем смотрите Генерацию Управления Функций для Подсистем (Simulink Coder). Для примеров сгенерированного кода функции подсистемы см. Модульный Функциональный Код для Невиртуальных Подсистем.

Модульный функциональный код для невиртуальных подсистем

В этом примере показано, как сгенерировать невиртуальный код функции подсистемы параметром Function with separate data, очищенным и выбранным, и сравнивает результаты.

  1. Открытая модель rtwdemo_atomic в качестве примера. Затем откройте приложение Embedded Coder. Измените системный конечный файл в ert.tlc.

    Эта модель показывает, как сохранить контур виртуальной подсистемы. Когда вы выбираете параметры блоков подсистемы Treat as atomic unit, код, который генератор кода производит для подсистемы, выполняется как атомарный модуль. Когда сконфигурировано как атомарные, можно задать, как генератор кода представляет подсистему путем установки параметра Function Packaging на вкладке Code Generation. Можно указать, что подсистема переводится в один из этих типов реализации:

    • Inline: Встроенный код подсистемы на сайтах вызова.

    • Function: void/void функция с вводом-выводом и внутренними данными в структуре глобальных данных модели.

    • Reusable Function: Повторно используемая функция с данными, переданными в как аргументы функции.

    • Auto: Генератор кода оптимизирует реализацию на основе контекста.

  2. Дважды кликните подсистему SS1 и исследуйте содержимое.

    Затем закройте окно подсистемы.

  3. Щелкните правой кнопкой по подсистеме SS1, выберите Block Parameters (Subsystem) из контекстного меню и исследуйте настройки. Simulink® и генератор кода могут избежать "искусственных" алгебраических циклов, когда вы делаете подсистему атомарной параметром подсистемы Minimize algebraic loop occurrences.

  4. Создайте вариант rtwdemo_atomic это показывает функциональный код без разделения данных.

    1. В диалоговом окне Subsystem Parameters,

      • Во вкладке the Main выберите Treat as atomic unit.

      • Во вкладке Code Generation:

        • Установите Function packaging на Nonreusable function.

        • Установите Function name options на User specified.

        • Установите Function name на myfun.

        • Установите File name options на Use function name. Эта установка является дополнительной, но упрощает более позднюю задачу сравнения кода, заставляя код функции атомарной подсистемы быть сгенерированной в файлы myfun.c и myfun.h.

      Не выбирайте параметр Function with separate data.

    2. Нажмите Apply, чтобы применить изменения и нажать OK, чтобы выйти из диалогового окна.

    3. Сохраните вариант модели с уникальным именем файла (например, rtwdemo_atomic1) к перезаписываемому местоположению.

  5. Создайте вариант rtwdemo_atomic это показывает функциональный код с разделением данных.

    1. Открытая модель rtwdemo_atomic.

    2. Откройте приложение Embedded Coder. Измените системный конечный файл в ert.tlc.

    3. В холсте модели щелкните правой кнопкой по подсистеме SS1 и выберите Block Parameters (Subsystem). В диалоговом окне Subsystem Parameters,

      • Во вкладке Main выберите Treat as atomic unit.

      • Во вкладке Code Generation:

        • Установите Function packaging на Nonreusable function.

        • Установите Function name options на User specified.

        • Установите Function name на myfun.

        • Установите File name options на Use function name.

        • Выберите Function with separate data.

    4. Нажмите Apply, чтобы применить изменение и нажать OK, чтобы выйти из диалогового окна.

    5. Сохраните вариант модели с уникальным именем файла (например, rtwdemo_atomic2) к перезаписываемому местоположению.

  6. Сгенерируйте код для каждой модели (например, rtwdemo_atomic1 и rtwdemo_atomic2).

  7. Сравните modelCH и myfun.cH файлы сгенерированы для этих двух моделей. Для обсуждения сравнения кода см. Различия в Файле H для Невиртуального Разделения Данных о Функции Подсистемы и Различия в Файле C для Невиртуального Разделения Данных о Функции Подсистемы.

    В этом примере нет существенных различий в сгенерированных вариантах ert_main.c, model_private.h, model_types.h, или rtwtypes.h.

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

  • Выбор Function with separate data заставляет генератор кода помещать определения типа для данных о подсистеме в myfun.h файл для rtwdemo_atomic2:

    /* Block signals for system '<Root>/SS1' */
    typedef struct {
      real_T Integrator;                    /* '<S1>/Integrator' */
    } rtB_myfun;
    
    /* Block states (auto storage) for system '<Root>/SS1' */
    typedef struct {
      real_T Integrator_DSTATE;             /* '<S1>/Integrator' */
    } rtDW_myfun;

    Для rtwdemo_atomic1, введите определения для данных о подсистеме, принадлежат модели и появляются в rtwdemo_atomic1.h:

    /* Block signals (auto storage) */
    typedef struct {
    ...
        real_T Integrator;                  /* '<S1>/Integrator' */
    } BlockIO_rtwdemo_atomic1;
    
    /* Block states (auto storage) for system '<Root>' */
    typedef struct {
      real_T Integrator_DSTATE;             /* '<S1>/Integrator' */
    } D_Work_rtwdemo_atomic1;
  • Выбор Function with separate data генерирует следующие внешние объявления в myfun.h файл для rtwdemo_atomic2:

    /* Extern declarations of internal data for 'system '<Root>/SS1'' */
    extern rtB_myfun rtwdemo_atomic2_myfunB;
    
    extern rtDW_myfun rtwdemo_atomic2_myfunDW;
    
    extern void myfun_initialize(void);

    В отличие от этого, сгенерированный код для rtwdemo_atomic1 содержит внешние объявления уровня модели для подсистемы BlockIO и D_Work данные, в rtwdemo_atomic1.h:

    /* Block signals (auto storage) */
    extern BlockIO_rtwdemo_atomic1 rtwdemo_atomic1_B;
    
    /* Block states (auto storage) */
    extern D_Work_rtwdemo_atomic1 rtwdemo_atomic1_DWork;

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

  • Выбор причин Function with separate data отдельная подсистема инициализирует функцию, myfun_initialize, быть сгенерированным в myfun.c файл для rtwdemo_atomic2:

    void myfun_initialize(void) {
      {
        ((real_T*)&rtwdemo_atomic2_myfunB.Integrator)[0] = 0.0;
      }
      rtwdemo_atomic2_myfunDW.Integrator_DSTATE = 0.0;
    }

    Подсистема инициализирует функцию в myfun.c вызывается моделью, инициализируют функцию в rtwdemo_atomic2.c:

    /* Model initialize function */
    
    void rtwdemo_atomic2_initialize(void)
    {
    ...
    
      /* Initialize subsystem data */
      myfun_initialize();
    }

    В отличие от этого, для rtwdemo_atomic1, данные о подсистеме инициализируются моделью, инициализируют функцию в rtwdemo_atomic1.c:

    /* Model initialize function */
    
    void rtwdemo_atomic1_initialize(void)
    {
    ...
      /* block I/O */
      {
     ...
        ((real_T*)&rtwdemo_atomic1_B.Integrator)[0] = 0.0;
      }
    
      /* states (dwork) */
    
      rtwdemo_atomic1_DWork.Integrator_DSTATE = 0.0;
    ...
    }
  • Выбор Function with separate data генерирует следующие объявления в myfun.c файл для rtwdemo_atomic2:

    /* Declare variables for internal data of system '<Root>/SS1' */
    rtB_myfun rtwdemo_atomic2_myfunB;
    
    rtDW_myfun rtwdemo_atomic2_myfunDW;

    В отличие от этого, сгенерированный код для rtwdemo_atomic1 содержит объявления уровня модели для подсистем BlockIO и D_Work данные, в rtwdemo_atomic1.c:

    /* Block signals (auto storage) */
    BlockIO_rtwdemo_atomic1 rtwdemo_atomic1_B;
    
    /* Block states (auto storage) */
    D_Work_rtwdemo_atomic1 rtwdemo_atomic1_DWork;
  • Выбор Function with separate data генерирует идентификатор, называющий, который отражает ориентацию подсистемы элементов данных. Ссылки на данные о подсистеме в функциях подсистемы, таких как myfun и myfun_update, находятся в модели modelшаг функция. Например, сравните этот код от myfun для rtwdemo_atomic2

    /* DiscreteIntegrator: '<S1>/Integrator' */
    rtwdemo_atomic2_myfunB.Integrator = rtwdemo_atomic2_myfunDW.Integrator_DSTATE;

    к соответствующему коду от myfun для rtwdemo_atomic1.

    /* DiscreteIntegrator: '<S1>/Integrator' */
    rtwdemo_atomic1_B.Integrator = rtwdemo_atomic1_DWork.Integrator_DSTATE;

Функции раздела в сгенерированном коде

В этом примере показано, как сопоставить подсистемы в модели с именами функций и файлами.

Узнать, как к:

  • Задайте функцию и имена файлов в сгенерированном коде.

  • Идентифицируйте части сгенерированного кода, которые требуются для интегрирования.

  • Сгенерируйте код для атомарных подсистем.

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

Для получения информации о модели в качестве примера и других примерах в этом ряду, смотрите, Генерируют код С от Алгоритма управления для Встраиваемой системы.

Атомарные и виртуальные подсистемы

Модели в качестве примера в Генерируют код С от Алгоритма управления для Встраиваемой системы и Конфигурируют Интерфейс Данных в виртуальных подсистемах использования Сгенерированного кода. Виртуальные подсистемы визуально организуют блоки, но не влияют на функциональность модели. Атомарные подсистемы оценивают блоки, включенные в модель как модуль. С атомарными подсистемами можно указать дополнительную информацию разделения функции. В модели атомарные подсистемы появляются с полужирной границей.

Просмотрите изменения в архитектуре модели

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

Сохраните копию модели к перезаписываемой папке.

В этом примере показано, как заменить виртуальные подсистемы на подсистемы вызова функций. Function-Call подсистемы:

  • Атомарные подсистемы

  • Позвольте вам управлять порядком выполнения подсистемы

  • Выполнитесь, когда вызов функции будет сигнализировать о триггерах

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

Фигура идентифицирует подсистемы вызова функции (1) PI_ctrl_1, PI_ctrl_2, и Pos_Command_Arbitration.

Эта версия модели содержит новую подсистему Execution_Order_Control (2), который содержит график Stateflow®, который моделирует функциональность вызова планировщика. Подсистема управляет порядком выполнения подсистем вызова функции через сигналы вызова функции (3). Позже в этом примере, вы исследуете, как изменение порядка выполнения может изменить результаты симуляции.

Эта версия модели содержит новые блоки Преобразования Сигнала (4) при выходных параметрах ПИ-контроллеров. С этими дополнительными блоками на месте, генератор кода может сгенерировать одну повторно используемую функцию для ПИ-контроллеров.

Местоположение функции управления и размещение файла в сгенерированном коде

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

Рисунок показывает параметры подсистемы для PI_ctrl_1.

Обработайте как атомарный модуль

  • Включает другие подменю. Для атомарных подсистем этот параметр автоматически выбран и отключен.

'SampleTime'

  • Задает шаг расчета для выполнения. Не доступный для подсистем вызова функций.

Функция упаковочные опции

  • Auto - Определяет, как подсистема появляется в сгенерированном коде. Это значение является значением по умолчанию.

  • Inline - Помещает код подсистемы, встроенный с остальной частью типового кодекса.

  • Function - Генерирует код для подсистемы как функция.

  • Reusable function - Генерирует допускающую повторное использование (повторно используемую) функцию от подсистемы. Функция передает все входные и выходные данные через формальные параметры. Функция непосредственно не получает доступ к глобальным переменным.

Опции имени функции

  • Выбор Function или Reusable function поскольку Функциональная упаковка включает опции имени функции.

  • Auto - Определяет функцию.

  • Use subsystem name - Основывает функцию на имени подсистемы.

  • User specified - Применяет заданное имя файла.

Опции имени файла

  • Выбор Function или Reusable function поскольку Функциональная упаковка включает опции имени файла.

  • Auto - Помещает функциональное определение в модуль, сгенерированный для родительской системы, или, если корень модели является родительским элементом в model.c.

  • Use subsystem name - Генерирует отдельный файл. Имя файла является именем подсистемы или библиотечного блока.

  • Use function name - Генерирует отдельный файл. Имя файла является именем, которое вы задаете с опциями Имени функции.

  • User specified - Применяет заданное, уникальное имя файла.

Функция с отдельными данными

  • Enabled, когда вы упаковка функции множества к Function. Когда выбрано, генератор кода разделяет внутренние данные подсистемы (например, сигналы) из данных родительской модели. Подсистема владеет этими отдельными данными.

Сгенерируйте повторно используемый код

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

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

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

Cause                                     Solution
Subsystem output feeds global signal      Add a Signal Conversion block between the 
data                                      subsystem and the global signal.
Generated function receives data          Select Configuration Parameters >
(formal parameters) through pointers      Model Referencing > Pass fixed-size scalar root
                                          inputs by value for code generation.           
Subsystem uses global signal data         Use a port to pass the global data in and out 
in internal algorithm                     of the subsystem.

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

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

В этой версии модели, подсистемы PI_ctrl_1 и PI_ctrl_2 маскируются. В каждой маске, значениях P и I усиления установлены объектами данных, такими как I_Gain_2 и P_Gain_2.

Сгенерируйте код для атомарной подсистемы

В Генерируют код С от Алгоритма управления для Встраиваемой системы и Конфигурируют Интерфейс Данных в Сгенерированном коде, вы генерируете код на корневом уровне модели. В качестве альтернативы можно создать определенную подсистему.

Чтобы инициировать сборку подсистемы, используйте контекстное меню. Можно выбрать из этих опций:

  1. Создайте Эту Подсистему: Обрабатывает подсистему как отдельный режим и создает полный набор источника C файлы и заголовочные файлы. Эта опция не поддерживает подсистемы вызова функций.

  2. Сгенерируйте S-функцию: Генерирует код С для подсистемы и создает обертку S-функции. Можно затем симулировать код в исходной модели. Эта опция не поддерживает подсистемы вызова функций.

  3. Экспорты функций: Генерирует код С без кода планирования, который идет со Сборкой Эта опция Подсистемы. Используйте эту опцию, чтобы создать подсистемы, которые используют триггеры, такие как подсистемы вызова функций.

В качестве альтернативы выберите подсистему и на вкладке C Code, нажмите Build.

Исследуйте сгенерированный код

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

Запустите скрипт сборки для этих трех опций. Затем исследуйте сгенерированные файлы путем нажатия на гиперссылки.

rtwdemo_PCG_Eval_P3.c

  • Полная сборка: Да, Ступенчатая функция

  • PI_ctrl_1: нет

  • Pos_Command_Arbitration: нет

PI_ctrl_1.c

  • Полная сборка: нет

  • PI_ctrl_1: Да, Триггерная функция

  • Pos_Command_Arbitration: нет

Pos_Command_Arbitration.c

  • Полная сборка: нет

  • PI_ctrl_1: нет

  • Pos_Command_Arbitration: да, Init и функция

PI_Ctrl_Reusable.c

  • Полная сборка: да

  • PI_ctrl_1: да

  • Pos_Command_Arbitration: нет

ert_main.c

  • Полная сборка: да

  • PI_ctrl_1: да

  • Pos_Command_Arbitration: да

eval_data.c

  • Полная сборка: да (1)

  • PI_ctrl_1: да (1)

  • Pos_Command_Arbitration: Нет, данные о Eval, не используемые в схеме

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

Данные маскированные в сгенерированном коде

В файле rtwdemo_PCG_Eval_P3.c, сайты вызова повторно используемой функции используют объекты данных P_Gain, I_Gain, P_Gain_2, и I_Gain_2 в качестве аргументов.

Эффект порядка выполнения на результатах симуляции

По умолчанию Simulink® выполняет подсистемы в этом порядке:

  1. PI_ctrl_1

  2. PI_ctrl_2

  3. Pos_Command_Arbitration

В данном примере можно задать один из двух альтернативных порядков выполнения. Можно затем использовать тестовую обвязку, чтобы наблюдать эффект порядка выполнения на результатах симуляции. Подсистема Execution_Order_Control имеет две настройки, которые управляют порядком выполнения. Чтобы выбрать настройку, используйте контекстное меню подсистемы.

Измените порядок выполнения и наблюдайте результаты.

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

Для следующего примера в этом ряду смотрите Вызов Внешний код С из Типового кодекса и Сгенерированного кода.

Невиртуальная подсистема модульные функциональные ограничения кода

Невиртуальные параметры блоков подсистемы Function with separate data имеют нижеследующие ограничения:

  • Параметр доступен для моделей, сконфигурированных с основанным на ERT системным конечным файлом.

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

  • Невиртуальная подсистема не может содержать непрерывные состояния.

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

  • Невиртуальная подсистема не может содержать невстроенные S-функции.

  • Сгенерированные файлы для невиртуальной подсистемы сошлются на заголовочные файлы всей модели, такие как modelH и model_private.h.

  • Параметр несовместим параметром Classic call interface. Выбор обоих параметров генерирует ошибку.

  • Параметр несовместим с Reusable function установка для параметра конфигурации модели Code interface packaging. Выбор обоих параметров генерирует ошибку.

  • Когда вы выбираете параметр для подсистемы, модель, которая содержит подсистему, не может содержать блок Data Store Memory с выбранным Share across model instances. Смотрите Data Store Memory.

Похожие темы