Создайте классы памяти при помощи Custom Storage Class Designer

Для контроля внешнего вида данных в сгенерированном коде можно использовать встроенные классы памяти, такие как ExportToFile (см. «Организация данных параметров в структуру при помощи класса Памяти»). Если встроенные классы памяти не соответствуют вашим требованиям, можно создать собственные классы памяти. Чтобы создать класс памяти, который можно применить к объектам данных, создайте класс памяти в пакете с помощью Custom Storage Class Designer. Смотрите раздел «Определение классов памяти, разделов памяти и шаблонов функций» для программной архитектуры.

Чтобы определить класс памяти, который можно применить в модели с помощью редактора Отображения, используйте Embedded Coder Dictionary. Или создайте класс памяти в пакете и обратитесь к пакету из словаря Embedded Coder.

Пакет также определяет Signal и Parameter классы данных. См. раздел Объекты данных. Объект данных из пакета, такого как Simulink может использовать классы памяти, определенные в этом пакете, но не классы памяти, определенные в других пакетах.

Для получения информации об использовании Custom Storage Class Designer для создания разделов памяти, смотрите Control Data and Function Placement in Memory by Inserting Pragmas.

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

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

Исследуйте модель примера

Откройте rtwdemo_cscpredef модели. Можно управлять кодом, сгенерированным из этой модели, путем определения собственных классов данных и создания собственных классов памяти.

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

Создайте пакет класса данных

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

  1. Создайте свой собственный пакет класса данных путем копирования папки с примером +SimulinkDemos. Перейдите к папке с примером пакета.

    % Remember the current folder path
    currentPath = pwd;
    
    % Navigate to the example package folder
    demoPath = '\toolbox\simulink\simdemos\dataclasses';
    cd([matlabroot,demoPath])
    

  2. Скопируйте +SimulinkDemos папка в буфер обмена.

  3. Вернитесь в рабочую папку.

    cd(currentPath)

  4. Вставьте +SimulinkDemos папка из буфера обмена в рабочую папку. Переименуйте скопированную папку в +myPackage.

  5. Перемещайтесь внутри +myPackage папка в файл Signal.m для редактирования определения Signal класс.

  6. Раскомментируйте methods раздел, который определяет метод setupCoderInfo. При вызове функции useLocalCustomStorageClasses, заменить 'packageName' с 'myPackage'. Когда вы заканчиваете, раздел появляется следующим образом:

      methods
        function setupCoderInfo(h)
          % Use custom storage classes from this package
          useLocalCustomStorageClasses(h, 'myPackage');
        end
      end % methods

    Функция useLocalCustomStorageClasses позволяет применять классы памяти, которые myPackage задает объекты данных, которые вы создаете из myPackage.

  7. Сохраните и закройте файл.

  8. Перемещайтесь внутри +myPackage папка в файл Parameter.m для редактирования определения Parameter класс. Раскомментируйте methods раздел, который определяет метод setupCoderInfo и замените 'packageName' с 'myPackage'.

  9. Сохраните и закройте файл.

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

Можно использовать Custom Storage Class Designer для создания или редактирования классов памяти, заданных пакетом класса данных.

  1. Установите текущую папку в папку, содержащую пакет myPackage.

  2. Откройте Custom Storage Class Designer.

    cscdesigner('myPackage')
  3. Выберите класс памяти ExportToFile.

  4. В поле Name переименуйте класс памяти в ExportToGlobal.

  5. В раскрывающемся списке Header file измените выбор из Instance specific на Specify. В новом поле укажите имя файла заголовка global.h.

  6. В раскрывающемся списке Definition file измените выбор из Instance specific на Specify. В новом поле укажите имя файла определения global.c.

  7. Нажмите OK. Щелкните Yes, чтобы сохранить изменения в пакете классов данных myPackage.

Применить класс памяти

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

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

    % Parameters
    templimit = myPackage.Parameter(202);
    pressurelimit = myPackage.Parameter(45.2);
    O2limit = myPackage.Parameter(0.96);
    rpmlimit = myPackage.Parameter(7400);
    
    % Signals
    tempalarm = myPackage.Signal;
    pressurealarm = myPackage.Signal;
    O2alarm = myPackage.Signal;
    rpmalarm = myPackage.Signal;
  2. Установите класс памяти каждого объекта равным ExportToGlobal.

    % Parameters
    templimit.CoderInfo.StorageClass = 'Custom';
    templimit.CoderInfo.CustomStorageClass = 'ExportToGlobal';
    pressurelimit.CoderInfo.StorageClass = 'Custom';
    pressurelimit.CoderInfo.CustomStorageClass = 'ExportToGlobal';
    O2limit.CoderInfo.StorageClass = 'Custom';
    O2limit.CoderInfo.CustomStorageClass = 'ExportToGlobal';
    rpmlimit.CoderInfo.StorageClass = 'Custom';
    rpmlimit.CoderInfo.CustomStorageClass = 'ExportToGlobal';
    
    % Signals 
    tempalarm.CoderInfo.StorageClass = 'Custom';
    tempalarm.CoderInfo.CustomStorageClass = 'ExportToGlobal';
    pressurealarm.CoderInfo.StorageClass = 'Custom';
    pressurealarm.CoderInfo.CustomStorageClass = 'ExportToGlobal';
    O2alarm.CoderInfo.StorageClass = 'Custom';
    O2alarm.CoderInfo.CustomStorageClass = 'ExportToGlobal';
    rpmalarm.CoderInfo.StorageClass = 'Custom';
    rpmalarm.CoderInfo.CustomStorageClass = 'ExportToGlobal';
    
  3. Выберите опцию Signal name must resolve to Simulink signal object для каждого из целевых сигналов в модели. Выбрать опцию можно с помощью диалогового окна Свойства сигнала (Signal Properties), столбца Resolve в Редакторе данных модели (Model Data Editor) или с помощью командной строки.

    % Signal tempalarm
    portHandles = get_param('rtwdemo_cscpredef/RelOp1','PortHandles');
    outputPortHandle = portHandles.Outport;
    set_param(outputPortHandle,'MustResolveToSignalObject','on')
    
    % Signal pressurealarm
    portHandles = get_param('rtwdemo_cscpredef/RelOp2','PortHandles');
    outputPortHandle = portHandles.Outport;
    set_param(outputPortHandle,'MustResolveToSignalObject','on')
    
    % Signal O2alarm
    portHandles = get_param('rtwdemo_cscpredef/RelOp3','PortHandles');
    outputPortHandle = portHandles.Outport;
    set_param(outputPortHandle,'MustResolveToSignalObject','on')
    
    % Signal rpmalarm
    portHandles = get_param('rtwdemo_cscpredef/RelOp4','PortHandles');
    outputPortHandle = portHandles.Outport;
    set_param(outputPortHandle,'MustResolveToSignalObject','on')
    

Сгенерируйте код

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

    slbuild('rtwdemo_cscpredef')
  2. В представлении кода для модели просмотрите сгенерированный заголовочный файл global.h. Файл содержит extern объявления сигналов модели и параметров, которые используют класс памяти ExportToGlobal.

    /* Declaration for custom storage class: ExportToGlobal */
    extern boolean_T O2alarm;
    extern real_T O2limit;
    extern boolean_T pressurealarm;
    extern real_T pressurelimit;
    extern boolean_T rpmalarm;
    extern real_T rpmlimit;
    extern boolean_T tempalarm;
    extern real_T templimit;

  3. Просмотрите сгенерированный файл global.c. Файл содержит определения сигналов модели и параметров, которые используют класс памяти ExportToGlobal.

    /* Definition for custom storage class: ExportToGlobal */
    boolean_T O2alarm;
    real_T O2limit = 0.96;
    boolean_T pressurealarm;
    real_T pressurelimit = 45.2;
    boolean_T rpmalarm;
    real_T rpmlimit = 7400.0;
    boolean_T tempalarm;
    real_T templimit = 202.0;

Изменение встроенного Класса памяти

Вы не можете непосредственно изменить встроенный класс памяти, например ExportToFile от Simulink упаковать, но можно создать копию, а затем изменить копию. когда вы создаете новый пакет без csc_registration.m файл, а затем откройте Custom Storage Class Designer впервые в этом пакете, Simulink копирует определения встроенных классов памяти в пакет. Затем в Custom Storage Class Designer можно изменить скопированные определения. Кроме того, чтобы сохранить доступность встроенных классов памяти в пакете, скопируйте один из них, нажав Copy, а затем измените полученную копию.

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

Custom Storage Class Designer является инструментом для создания и управления классами памяти и разделами памяти. Чтобы открыть Custom Storage Class Designer для определенного пакета, например, +mypkg, в командной строке, используйте cscdesigner функция:

cscdesigner('mypkg')

Имя папки, представляющей пакет, начинается со +. Когда вы используете функцию cscdesigner, опускать + от имени целевого пакета.

Чтобы контролировать эффект класса памяти на данные в модели, задайте свойства класса памяти в Custom Storage Class Designer. Чтобы определить, как сгенерировать конкретный вид кода, используйте информацию в таблице.

Вид данных в сгенерированном кодеМетод
СтруктураУстановите Type значение FlatStructure. См. «Генерация структурированных данных».
МакросУстановите Data initialization значение Macro и очистить For signals. См. «Генерация макроса».
УказательУстановите Data access значение Pointer и Data scope к Auto, Imported, или Instance specific. Внешний код должен определять переменную указателя.
static данные (данные с разбивкой по файлам)Установите Data scope значение File.
const или volatile данныеУстановите Memory section в раздел памяти, который задает const, volatile, или и то, и другое. Например, используйте один из встроенных разделов памяти MemConst, MemVolatile, и MemConstVolatile. Чтобы создать свой собственный раздел памяти, смотрите Control Data and Function Placement in Memory by Inserting Pragmas.
Вызовы внешних функций для чтения и записи в данныеСмотрите Функции Пользовательского Accessor Вызова или Макросы Вместо Чтения и Записи в Переменные.

Разрешить пользователям класса памяти задавать значение свойства

Для некоторых свойств класса памяти, таких как Data scope, вместо определения значения в Custom Storage Class Designer можно разрешить пользователям класса памяти задавать значение. Можно создать один, гибкий класс памяти вместо нескольких классов памяти, которые варьируются только по нескольким значениям свойств.

Например, предположим, что вы создаете класс памяти, который приводит к глобальной переменной в сгенерированном коде. Можно сконфигурировать класс памяти, чтобы пользователь мог задать свойство Data scope равным Exported для сигнала в модели и установите свойство на Imported для другого сигнала.

В Custom Storage Class Designer для каждого свойства, которое вы хотите настроить таким образом, установите значение свойства равным Instance specific. Затем, когда пользователь применяет класс памяти к элементу данных, свойство появляется пользователю как пользовательский атрибут для этого элемента данных. Дополнительные сведения о пользовательских атрибутах конкретного экземпляра см. в разделе Свойства класса памяти.

Сгенерируйте макрос

Чтобы создать класс памяти, который дает макрос в генеративном коде, установите Data initialization равным Macro и очистить For signals.

Когда вы задаете Data initialization MacroDefinition file не имеет никакого смысла. Чтобы запретить пользователям класса памяти указывать файл определения без смысла, в Custom Storage Class Designer задайте Definition file Specify и оставьте текстовое поле пустым.

  • Определение макроса в заголовочном файле (#define), укажите имя файла заголовка со свойством Header file.

  • Чтобы предоставить определение макроса в качестве опции компилятора или флага компилятора, установите Data access равным Imported и Header file к Specify. Оставьте Header file текстовое поле пустым. Затем сгенерированный код не определяет макрос и не включает (#include) файл заголовка.

    Чтобы задать опцию компилятора или флаг, используйте параметр конфигурации модели Configuration Parameters > Code Generation > Custom Code > Additional build information > Defines. Смотрите Панель Генерации кода: Пользовательский код: Дополнительная информация о сборке: Определяет.

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

Чтобы создать класс памяти, которая агрегирует элементы данных в плоскую структуру (подобную встроенному классу памяти Struct), установите Type равным FlatStructure. Появится вкладка Structure Attributes.

  • Чтобы управлять именем глобальной переменной структуры, которая появляется в сгенерированном коде, используйте свойство Struct name и текстовое поле.

  • Если вы задаете Struct name Instance specificпользователи класса памяти задают имя структурной переменной. В этом случае генератор кода выводит имя типа структуры из имени переменной.

    Чтобы более точно управлять именем и другими характеристиками типа структуры, установите Struct name равным Specify. Управляйте характеристиками типа с помощью появившихся дополнительных свойств.

  • Чтобы сгенерировать структуру с битовыми полями (подобными встроенному классу памяти BitField), выберите Bit-pack booleans. Элементы данных, которые используют тип данных boolean появится в сгенерированном коде в виде битовых полей структуры.

Управление присвоением начального значения в сгенерированном коде

  • Как использовать Simulink по умолчанию® Coder™ стратегии инициализации установите Data initialization значение по умолчанию, Auto.

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

    • Сгенерированный код динамически инициализирует сигнал и данные о состоянии как часть функции инициализации модели (имя model_initialize по умолчанию).

  • Чтобы статически инициализировать данные, установите Data initialization равным Static.

  • Чтобы динамически инициализировать данные, установите Data initialization равным Dynamic.

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

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

Использование встроенного класса памяти GetSet, можно сгенерировать код, который вызывает ваши внешние, пользовательские функции вместо прямого взаимодействия с переменными. Для получения общей информации о GetSet, см. «Доступ к данным через функции с класс памяти».

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

  • Укажите имена внешних функций.

    • Применить ту же get или set схема именования функций для элементов данных, которые используют класс памяти, устанавливают Get function и Set function на Specify. Затем в текстовых полях задайте схему именования функций, например get_myData_$N. Используйте лексему $N в схеме именования, которая представляет имя каждого элемента данных. Если вы не используете лексему, каждый элемент данных использует тот же самый заданный get или set имя функции, поэтому модель генерирует ошибку, когда вы генерируете код.

    • Чтобы задать другое get или set имя функции для каждого элемента данных, установите Get function или Set function равными Instance specific. Позже, когда вы создаете элемент данных и применяете класс памяти, задайте имя функции путем конфигурирования пользовательских атрибутов элемента данных.

  • Укажите имя файла заголовка, который объявляет get и set функций со свойством Header file. В этом случае Definition file не имеет никакого смысла. Чтобы запретить пользователям класса памяти указывать файл определения без смысла, задайте Definition file Specify и оставьте текстовое поле пустым.

  • Если вы реализуете get механизм для скалярных данных или данных массива как макроса вместо функции, можно сгенерировать код, который опускает круглые скобки при чтении этих данных. На вкладке Access Function Attributes выберите Get data through macro (omit parentheses).

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

Когда внешний код определяет данные, чтобы избежать генерации повторяющегося определения, необходимо сконфигурировать сгенерированный код для чтения и записи в существующие данные. В Custom Storage Class Designer задайте Data scope Imported. Генератор кода не генерирует определение для глобальной переменной или макроса.

  • Если ваш код определяет переменную указателя, чтобы сгенерировать код, который взаимодействует с указателем, установите Data access на Pointer.

  • Если вы генерируете структурированные данные путем установки Type на FlatStructureкод должен определять тип структуры и глобальную переменную структуры.

  • Если ваш код инициализирует состояние или данные о сигнале, можно предотвратить перезапись инициализации сгенерированным кодом путем установки значения Data initialization None. Смотрите Предотвращение Дублирования Кода Инициализации для Глобальных Переменных

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

Чтобы настроить комментарии, которые появляются в сгенерированном коде, на вкладке Comments задайте Comment rules Specify. Чтобы задать комментарий, который появляется с объявлением каждого элемента данных, используйте поле Declaration comment. Чтобы задать комментарий, который появляется с определением, используйте поле Definition comment.

Для структурированных данных (вы устанавливаете Type равным FlatStructure), чтобы задать комментарий, который появляется с определением типа структуры, используйте поле Type comment.

Избегайте ошибок во время генерации кода путем проверки строения класса памяти

Когда вы конфигурируете класс памяти в Custom Storage Class Designer, чтобы проверить возможные ошибки в строении, нажмите Validate.

Например, проверка класса памяти предупреждает вас, если вы случайно установили для Data initialization значение Macro с For signals выбранным. Сигнал не может появиться в сгенерированном коде как макрос.

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

Чтобы использовать созданный класс памяти, необходимо сделать определяющий пакет доступным. Либо установите текущую папку в папку, содержащую пакет, либо добавьте папку, содержащую папку пакета, в MATLAB® path (см. «Что такой MATLAB Пути поиска файлов?»). Добавление пакета к пути MATLAB позволяет использовать классы памяти независимо от места установки текущей папки.

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

Чтобы использовать классы памяти на основе пакетов в редакторе Отображения, обратитесь к пакету из словаря Embedded Coder. Чтобы настроить словарь Embedded Coder Dictionary для обращения к пакету, смотрите раздел "См". "Определения генерации кода в пакете" ".

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

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

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

  1. В Custom Storage Class Designer выберите вкладку Custom Storage Class.

  2. Чтобы выбрать пакет-ссылку, используйте команду Выбрать пакет. Пакет должен быть доступным для записи.

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

  4. Щелкните Создать ссылку (New Reference).

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

  5. Используйте команду «Имя», чтобы задать имя для новой ссылки. Имя должно быть уникальным в импортирующем пакете, но может дублировать имя в исходном пакете. Имя не может быть ключевым словом TLC.

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

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

  8. Нажмите кнопку ОК или Применить. Чтобы сохранить изменения навсегда, нажмите кнопку Save.

Управление внешним видом раскрывающегося списка классов памяти

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

  • Чтобы контролировать порядок пользовательских классов памяти в списке, в Custom Storage Class Designer используйте кнопки Up и Down. Порядок классов памяти в раскрывающихся списках совпадает с порядком, заданным в Custom Storage Class Designer.

  • Чтобы препятствовать тому, чтобы пользователь класса памяти применил класс памяти к данным параметра или предупредил и заявил данные, используйте флажки <reservedrangesplaceholder1> and <reservedrangesplaceholder0>. При удалении одного из этих свойств для соответствующего типа данных класс памяти не отображается в раскрывающемся списке.

    Для примера, если ваш класс памяти дает макрос в сгенерированном коде, потому что вы задаете Data initialization Macro, чтобы предотвратить применение пользователями класса памяти к сигнальным данным, очистите For signals.

Защита определений пользовательских классов памяти

При нажатии кнопки Save в Custom Storage Class Designer, Designer сохраняет определения раздела памяти и класса памяти в csc_registration.m файл в папке пакета. Чтобы определить местоположение этого файла, в Custom Storage Class Designer проверьте значение Filename.

Можно предотвратить изменения в определениях классов памяти всего пакета путем преобразования csc_registration.m файл из файла MATLAB в P-файл. Используйте pcode функция.

Лучшая практика - сохранить csc_registration.m и csc_registration.p в папке пакета. Таким образом, если вы изменяете классы памяти с помощью Designer, можно удалить csc_registration.p а затем перегенерируйте его после завершения изменений. Поскольку P-кодированная версия файла имеет приоритет, когда оба файла существуют в пакете, классы памяти защищены, и вы не можете изменять их в Custom Storage Class Designer.

Дальнейшая настройка сгенерированного кода путем записи TLC-кода

Если создание собственного класса памяти путем манипулирования свойствами в Custom Storage Class Designer не соответствует вашим требованиям, можно тонко управлять сгенерированным кодом, записав TLC-код для класса памяти. Используйте расширенный режим Custom Storage Class Designer и для класса памяти установите Type значение Other. Смотрите Представление Данных Мелкого Управления путем Записи Кода TLC для Класса памяти.

Похожие темы