Сконфигурируйте блоки Inport корневого уровня для генерации кода C

Чтобы использовать код, который вы генерируете из модели, вы вызываете сгенерированные функции точки входа. Вызывающее окружение и сгенерированные функции обмениваются входными и выходными данными, для примера, как глобальные переменные или аргументы функции. Блоки Inport корневого уровня (inports) составляют входные данные интерфейса. Чтобы интегрировать и развернуть сгенерированный код в приложениях, можно настроить, как генератор кода производит код интерфейса, включая то, как объявляются и обрабатываются входные данные. Индивидуальные настройки могут:

  • Минимизируйте изменения, которые вы должны внести в существующий код.

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

  • Сгенерируйте код, который обменивается данными более эффективно (для примера, с помощью указателей и аргументов pass-by-reference для нескалярных данных).

Для генерации кода примеры показывают, как настроить интерфейс inport для модели rtwdemo_configrpinterface . Можно сконфигурировать отображения кода с помощью Code Mappings editor или отображений кода API (coder.mapping.api.CodeMapping).

Выберите опции индивидуальной настройки для интерфейса Inport

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

  • Настройка ли строения по умолчанию

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

  • Как объявить и обработать входные данные корневого уровня в сгенерированном интерфейсе

    • Как отдельные глобальные переменные

    • Чтобы считать входные данные из глобальных переменных, определенных во внешнем коде

    • Для ссылочных моделей входных портов как глобальных переменных (void-void)

    • Как вызовы для доступа к функциям. Требуется Embedded Coder®

    • Как аргументы функции точки входа. Требуется Embedded Coder

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

Другие факторы включают в себя вопрос о том, следует ли:

  • Назовите входные порты в сгенерированном коде при помощи меток блоков Inport которые появляются в модели или при помощи уникальных идентификаторов кода.

  • Включите volatile type qualifier в определениях и объявлениях глобальных переменных. Требуется Embedded Coder. Смотрите Protect Global Data with const and volatile Type Qualifiers (Embedded Coder).

  • Поместите данные, считанные в определенную область памяти. Требуется Embedded Coder. Смотрите Control Data and Function Placement in Memory by Inserting Pragmas (Embedded Coder).

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

Для примера модели rtwdemo_configrpinterface, требования к интерфейсам входных портов:

  • Получите данные для входных портов корневого уровня In1, In2, In3, и In4 из внешнего файла заголовка. Данные считываются с In1 используется для вычисления значения, которое хранится в памяти, а затем используется в условии if-else кода, сгенерированного для блока Switch. Данные, считанные из трех других входных портов, используются в интерполяционных таблицах Table1 и Table2.

  • Данные для входных In1 должно быть передано значением.

  • Данные для входных портов In2, In3, и In4 должен быть передан по ссылке.

  • Переменные, представляющие входные порты в сгенерированном коде, должны быть именованы input1, input2, input3, и input4.

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

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

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

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

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

  1. Откройте пример модели rtwdemo_configrpinterface. Сохраните копию модели в месте с возможностью записи.

    Simulink model to use for learning how to configure signals for code generation.

  2. Откройте приложение Simulink Coder.

  3. На вкладке C Code выберите Code Interface > Default Code Mappings.

  4. В редакторе Отображения в разделе Inports and Outports выберите Inports категории. Установите класс памяти по умолчанию равным ImportedExternPointer.

    Code Mappings editor with Data Defaults tab selected, Inports and Outports tree node expanded, and storage class for Inports set to ImportedExternPointer.

  5. Сохраните модель.

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

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

Если ваша модель соответствует хотя бы одному из следующих критериев, рассмотрите настройку настроек генерации кода для входных портов корневого уровня индивидуально:

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

  • Использует немного входных портов.

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

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

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

  1. Если вы еще не сделали этого, выполните действия в разделе «Настройка настроек генерации кода по умолчанию для входных портов корневого уровня».

  2. В редакторе Отображения перейдите на вкладку Inports. Редактор перечисляет имена блоков Inport и элементов шины, которые находятся в модели. Если порт разрешается к объекту сигнала, справа от имени элемента появляется значок разрешения к объекту сигнала. Класс памяти для каждого входного порта установлен на Auto, что означает, что генератор кода может исключить или изменить представление соответствующего кода в целях оптимизации. Если оптимизация невозможна, генератор кода применяет строение модели по умолчанию. В данном примере строение модели по умолчанию задаёт класс памяти ImportedExternPointer.

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

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

  3. Сконфигурируйте генератор кода, чтобы применить настройку класса памяти по умолчанию к входным портам In2, In3, и In4. Выберите строки для трех входных портов. Затем для одного из выбранных входных портов установите класс памяти равным Model default: ImportedExternPointer.

    Code Mappings editor with Inports tab selected, signals In2, In3, and In4 selected, and storage class being set to Model default: ImportedExternPointer.

    Класс памяти для трех выбранных входных портов изменяется на Model default: ImportedExternPointer.

  4. Для входных In1, переопределите настройку класса памяти по умолчанию. Установите класс памяти равным ImportedExtern.

    Code Mappings editor with Inports tab selected, signal In1 selected, and storage class being set to ImportedExtern

  5. Сконфигурируйте идентификаторы кода для входных портов так, чтобы имена аргумента интерфейса в сгенерированном коде совпадали с именами интерфейсов во внешних файлах заголовка и определения. В редакторе Отображения выберите строку для каждого входного порта. В Property Inspector установите свойство Identifier на эти значения.

    InportИдентификатор кода
    In1input1
    In2input2
    In3input3
    In4input4
  6. Сохраните модель.

  7. Сгенерируйте и просмотрите код. Для примера, в rtwdemo_configrpinterface.c найти, где переменные input1, input2, input3, и input4 используются в функции точки входа шага.

    void rtwdemo_configrpinterface_step(void)
    {
      mode = ((input1 > rtwdemo_configrpinterface_UPPER) || (input1 <
               rtwdemo_configrpinterface_LOWER));
    
      dout_Table1 = look1_binlc((*input2), (&(mp_Table1.BP[0])),
        (&(mp_Table1.Table[0])), 10U);
    .
    .
    . 
      dout_Table2 = look2_binlc((*input3), (*input4), (&(mp_Table2.BP1[0])),
        (&(mp_Table2.BP2[0])), (&(mp_Table2.Table[0])),
        (&(rtwdemo_configr_Table2_maxIndex[0])), 3U);
    	
      dstate_X = dout_Table2;
    } 
    }

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

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

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

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

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

    open_system('rtwdemo_configrpinterface')
    
  2. Создайте объект cm вызовом функции coder.mapping.api.get. Объект хранит строение генерации кода данных для модели rtwdemo_configrpinterface.

    cm = coder.mapping.api.get('rtwdemo_configrpinterface');
  3. Сконфигурируйте настройки по умолчанию для входных портов путем вызова функции setDataDefault. Для аргументов задайте следующие значения:

    • Объект, возвращенный coder.mapping.api.get

    • Inports для категории по умолчанию

    • Имя свойства StorageClass со значением свойства ImportedExternPointer

    setDataDefault(cm,'Inports','StorageClass','ImportedExternPointer')
  4. Проверьте строение по умолчанию для входных портов. Выполните вызов для getDataDefault который задает объект, возвращенный coder.mapping.api.get, категория Inports, и StorageClass.

    getDataDefault(cm,'Inports','StorageClass')
    
    ans =
    
        'ImportedExternPointer'
    
  5. Переопределите строение входного порта по умолчанию для входного In1. Требования к этому входному порту отличаются от требований к другим трем входным портам.

    По умолчанию Simulink устанавливает класс памяти для отдельных входных портов равным Auto. Когда класс памяти Auto, генератор кода:

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

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

    Чтобы управлять строением класса памяти для входного порта, сконфигурируйте настройки для входного порта с функцией setInport. Сконфигурируйте код, сгенерированный для inport In1 считывание входных данных из глобальных переменных, определенных во внешнем файле, как указано в требованиях. Выполните вызов функции setInport который задает объект, возвращенный coder.mapping.api.get, Inport блок с именем In1, имя свойства StorageClass, и значение свойства ImportedExtern.

    setInport(cm,'In1','StorageClass','ImportedExtern')
    
  6. Проверьте свои строения на наличие In1 вызовом функции getInport.

    getInport(cm,'In1','StorageClass')
    
    ans =
    
        'ImportedExtern'
    
  7. Сконфигурируйте генератор кода, чтобы применить настройки входного порта по умолчанию к входным портам In2, In3, и In4. Для каждого входного порта вызовите функцию setInport. Задайте объект, возвращенный coder.mapping.api.get, имя Inport блока, имя свойства StorageClass, и значение свойства Model default.

    setInport(cm,'In2','StorageClass','Model default')
    setInport(cm,'In3','StorageClass','Model default')
    setInport(cm,'In4','StorageClass','Model default')
    
  8. Проверьте изменения строения для входных портов In2, In3, и In4 с вызовами функции getInport.

    getInport(cm,'In2','StorageClass')
    
    ans =
    
        'Model default'
    
    getInport(cm,'In3','StorageClass')
    
    ans =
    
        'Model default'
    
    
    getInport(cm,'In4','StorageClass')
    
    ans =
    
        'Model default'
  9. Сконфигурируйте идентификаторы кода для входных портов так, чтобы глобальные переменные, представляющие входные порты в сгенерированном коде, совпадали с именами переменных во внешнем файле определения. Для каждого входного порта вызовите функцию setInport. Задайте объект, возвращенный coder.mapping.api.get, имя Inport блока, имя свойства Identifier, и одно из этих значений свойств.

    InportИдентификатор кода
    In1input1
    In2input2
    In3input3
    In4input4
    setInport(cm,'In1','Identifier','input1');
    setInport(cm,'In2','Identifier','input2');
    setInport(cm,'In3','Identifier','input3');
    setInport(cm,'In4','Identifier','input4');
    
  10. Проверьте свои изменения строения для входных портов при помощи вызовов для функционирования getInport.

    getInport(cm,'In1','Identifier')
    
    ans =
    
        'input1'
    
    getInport(cm,'In2','Identifier')
    
    ans =
    
        'input2'
    
    getInport(cm,'In3','Identifier')
    
    ans =
    
        'input3'
    
    
    getInport(cm,'In4','Identifier')
    
    ans =
    
        'input4'
    
  11. Сохраните модель.

  12. Сгенерируйте и просмотрите код. Для примера, в rtwdemo_configrpinterface.c найти, где переменные input1, input2, input3, и input4 используются в функции точки входа шага.

    void rtwdemo_configrpinterface_step(void)
    {
      mode = ((input1 > rtwdemo_configrpinterface_UPPER) || (input1 <
               rtwdemo_configrpinterface_LOWER));
    
      dout_Table1 = look1_binlc((*input2), (&(mp_Table1.BP[0])),
        (&(mp_Table1.Table[0])), 10U);
    .
    .
    . 
      dout_Table2 = look2_binlc((*input3), (*input4), (&(mp_Table2.BP1[0])),
        (&(mp_Table2.BP2[0])), (&(mp_Table2.Table[0])),
        (&(rtwdemo_configr_Table2_maxIndex[0])), 3U);
    	
      dstate_X = dout_Table2;
    } 
    }

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

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

ТребованияКласс памяти
Включите оптимизацию, потенциально создавая более эффективный код.Авто (только для отдельных отображений)
Для элементов данных, которые не могут быть оптимизированы, представьте данные как поле стандартной структуры данных.По умолчанию (только для отображения по умолчанию)
Предотвратите устранение оптимизации системы хранения данных для элемента данных и используйте отображение по умолчанию для категории элемента данных.Модель по умолчанию (только для отдельных отображений), Dictionary Default (Только отдельные отображения)
Сгенерируйте глобальное определение переменной и объявление.ExportedGlobal
Сгенерируйте код, который читается и записывается в глобальную переменную или глобальный указатель переменной, заданный вашим внешним кодом.ImportedExtern, ImportedExternPointer

Список доступных классов памяти может включать другие специфичные для проекта классы памяти, определенные в словаре Embedded Coder Dictionary. Если у вас есть особые требования, не удовлетворяющие перечисленным классам памяти, и вы имеете программное обеспечение Embedded Coder, можно задать класс памяти. Смотрите «Определение классов памяти», «Разделы памяти» и «Шаблоны функций» для программной архитектуры (Embedded Coder).

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

См. также

|

Похожие темы