exponenta event banner

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

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

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

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

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

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

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

Чтобы использовать функцию с отдельным параметром данных,

  • Настройте модель с помощью целевого файла системы на основе ERT.

  • Настройте подсистему как атомарную или условно выполненную.

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

Чтобы настроить подсистему для создания модульного кода функции, вызовите диалоговое окно «Параметры подсистемы» и выберите ряд параметров для отображения и включения опции «Функция с отдельными данными». Для получения дополнительной информации см. раздел Настройка подсистемы для генерации кода модульной функции и кода модульной функции для невиртуальных подсистем. Ограничения, которые применяются, см. в разделе Ограничения кода модульной функции непровиртуальной подсистемы.

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

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

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

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

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

  4. Для параметра Function packaging выберите Nonreusable function. После выбора этого параметра отображается параметр Функция с отдельными данными.

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

  5. Выберите функцию с отдельным параметром данных. Появятся дополнительные параметры.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  3. Щелкните правой кнопкой мыши подсистему SS1, выберите в контекстном меню «Параметры блока (подсистема)» и проверьте настройки. Simulink ® и генератор кода могут избежать «искусственных» алгебраических циклов, когда подсистема атомарна с параметром подсистемы Минимизировать вхождения алгебраических циклов.

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

    1. В диалоговом окне «Параметры подсистемы»

      • На вкладке Главная (Main) выберите Обработать как атомную единицу (Treat as atomic unit).

      • На закладке Создание кода:

        • Установить упаковку функций в Nonreusable function.

        • Задайте для параметров имени функции значение User specified.

        • Задать для имени функции значение myfun.

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

      Не выбирайте функцию с отдельным параметром данных.

    2. Нажмите кнопку Применить (Apply), чтобы применить изменения, и кнопку ОК, чтобы выйти из диалогового окна.

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

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

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

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

    3. На холсте модели щелкните правой кнопкой мыши подсистему SS1 и выберите «Параметры блока (подсистема)». В диалоговом окне «Параметры подсистемы»

      • На вкладке Главная (Main) выберите Обработать как атомную единицу (Treat as atomic unit).

      • На закладке Создание кода:

        • Установить упаковку функций в Nonreusable function.

        • Задайте для параметров имени функции значение User specified.

        • Задать для имени функции значение myfun.

        • Задать для параметров имени файла значение Use function name.

        • Выберите Функция с отдельными данными.

    4. Нажмите кнопку Применить (Apply), чтобы применить изменение, и кнопку ОК, чтобы выйти из диалогового окна.

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

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

  7. Сравните model.c/.h и myfun.c/.h файлы, созданные для двух моделей. Описание сравнения кода см. в разделах Различия файлов H для разделения данных функции невиртуальной подсистемы и Различия файлов C для разделения данных функции невиртуальной подсистемы.

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

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

  • При выборе функции с отдельными данными генератор кода помещает определения типов для данных подсистемы в myfun.h файл для rtwdemo_atomic2:

    /* Block states (default storage) for system '<Root>/SS1' */
    typedef struct {
      real_T Integrator_DSTATE;            /* '<S1>/Integrator' */
    } DW_myfun_T;

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

    /* Block signals (default storage) */
    typedef struct {
      real_T Sum;                          /* '<Root>/Sum' */
    } B_rtwdemo_atomic_1_T;
    
    /* Block states (default storage) for system '<Root>' */
    typedef struct {
      real_T Integrator_DSTATE;            /* '<S1>/Integrator' */
    } DW_rtwdemo_atomic_1_T;
  • При выборе функции с отдельными данными создаются следующие внешние объявления в myfun.h файл для rtwdemo_atomic2:

    /* Extern declarations of internal data for system '<Root>/SS1' */
    extern DW_myfun_T myfun_DW;
    extern void myfun_Update(void);
    extern void myfun(void);

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

    /* Block signals (default storage) */
    extern B_rtwdemo_atomic_1_T rtwdemo_atomic_1_B;
    
    /* Block states (default storage) */
    extern DW_rtwdemo_atomic_1_T rtwdemo_atomic_1_DW;

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

  • При выборе функции с отдельными данными инициализируется отдельная функция подсистемы, 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;
    ...
    }
  • При выборе функции с отдельными данными в myfun.c файл для rtwdemo_atomic2:

    /* Declare variables for internal data of system '<Root>/SS1' */
    DW_myfun_T myfun_DW;

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

    /* Block signals (default storage) */
    B_rtwdemo_atomic_1_T rtwdemo_atomic_1_B;
    
    /* Block states (default storage) */
    DW_rtwdemo_atomic_1_T rtwdemo_atomic_1_DW;
  • При выборе функции с отдельными данными генерируется именование идентификаторов, отражающее ориентацию элементов данных подсистемы. Ссылки на данные подсистемы в функциях подсистемы, таких как myfun и myfun_update, находятся в модели model_step функция. Например, сравните этот код с myfun для rtwdemo_atomic2

    /*  DiscreteIntegrator: '<S1>/Integrator' */
      rtwdemo_atomic_2_Y.Out1 = myfun_DW.Integrator_DSTATE;

    в соответствующий код из myfun для rtwdemo_atomic1.

    /* DiscreteIntegrator: '<S1>/Integrator' */
    rtwdemo_atomic_1_Y.Out1 = rtwdemo_atomic_1_DW.Integrator_DSTATE;

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

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

Узнайте, как:

  • Укажите имена функций и файлов в созданном коде.

  • Определите части созданного кода, необходимые для интеграции.

  • Создание кода для атомных подсистем.

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

Сведения о модели примера и других примерах этой серии см. в разделе Подготовка модели алгоритма управления для генерации кода C.

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

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

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

Откройте пример rtwdemo_PCG_Eval_P3 модели.

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

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

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

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

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

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

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

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

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

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

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

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

Рассматривать как атомную единицу

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

Время выборки

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

Варианты упаковки функций

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

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

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

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

Параметры имени функции

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

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

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

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

Параметры имени файла

  • Выбор Function или Reusable function для Function packaging включает параметры имени файла.

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

  • Use subsystem name - Создает отдельный файл. Имя файла - это имя подсистемы или блока библиотеки.

  • Use function name - Создает отдельный файл. Имя файла - это имя, указанное опциями Имя функции (Function name).

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

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

  • Включено, если для параметра Function packaging установлено значение Function. При выборе этого параметра генератор кода отделяет внутренние данные подсистемы (например, сигналы) от данных родительской модели. Подсистема владеет этими отдельными данными.

Создание кода повторного ввода

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

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

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

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.

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

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

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

  1. Build This Subsystem: Рассматривает подсистему как отдельный режим и создает полный набор исходных C-файлов и заголовочных файлов. Эта опция не поддерживает подсистемы вызова функций.

  2. Generate S-Function: Генерирует код C для подсистемы и создает оболочку S-Function. Затем можно смоделировать код в исходной модели. Эта опция не поддерживает подсистемы вызова функций.

  3. Функции экспорта: создает код C без кода планирования, поставляемого с опцией «Построить эту подсистему». Эта опция используется для построения подсистем, использующих триггеры, например, подсистемы вызова функций.

Либо откройте приложение Embedded Coder, выберите подсистему и на вкладке 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: Нет, данные оценки не используются на диаграмме

(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 имеет две конфигурации, которые управляют порядком выполнения. Для выбора конфигурации используйте контекстное меню подсистемы.

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

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

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

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

Параметр блока невиртуальной подсистемы Функция с отдельными данными имеет следующие ограничения:

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

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

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

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

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

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

  • Этот параметр несовместим с параметром классического интерфейса вызова. При выборе обоих параметров возникает ошибка.

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

  • При выборе параметра для подсистемы модель, содержащая подсистему, не может содержать блок памяти хранилища данных с выбранным параметром «Общий доступ» для всех экземпляров модели. См. раздел Память хранилища данных.

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