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

Можно использовать встроенные пользовательские классы памяти, такие как ExportToFile, чтобы управлять внешним видом данных в сгенерированном коде (см., Применяют Пользовательские Классы памяти к Отдельному Сигналу, состоянию и Элементам данных Параметра). Если встроенные пользовательские классы памяти не удовлетворяют ваши требования, можно создать собственные классы памяти. Как описано в Задают Классы памяти, Разделы Памяти, и Шаблоны функций для Программной архитектуры, чтобы создать пользовательский класс памяти, что можно обратиться к отдельным элементам данных (например, в Model Data Editor), необходимо создать класс памяти в пакете при помощи Custom Storage Class Designer.

Чтобы задать класс памяти, который можно применить как класс памяти по умолчанию для категории элементов данных, используйте Embedded Coder Dictionary. Смотрите Конфигурируют генерацию кода C По умолчанию для Категорий Данных модели и Функций.

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

Для получения информации об использовании Custom Storage Class Designer, чтобы создать разделы памяти, смотрите Данные об Управлении и Функциональное Размещение в Памяти Вставкой Прагм.

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

Этот пример показывает как коду системы управления, сгенерированному из модели путем создания и применения собственного класса памяти.

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

Откройте модель 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. Сгенерируйте код для модели в качестве примера.

    rtwbuild('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 classes и memory создания и управления. Чтобы открыть 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 на раздел memory, который задает const, volatile или обоих. Например, используйте один из встроенных разделов памяти MemConst, MemVolatile и MemConstVolatile. Чтобы создать ваш собственный раздел memory, смотрите Данные об Управлении и Функциональное Размещение в Памяти Вставкой Прагм.
Вызовы внешних функций, чтобы читать и записать в данныеСмотрите вызывают пользовательские функции средства доступа или макросы вместо того, чтобы читать и записать в переменные.

Позвольте пользователям пользовательского класса памяти задавать значение свойства

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

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

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

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

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

Когда вы устанавливаете Data initialization на Macro, Definition 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. Смотрите Панель Генерации кода: Пользовательский код: Дополнительная информация о Сборке: Задает (Simulink Coder).

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

Чтобы создать пользовательский класс памяти, который агрегировал элементы данных в плоскую структуру (подобный встроенному пользовательскому классу памяти 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, см. Доступ к данным Через Функции с Пользовательским Классом памяти 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® (см. то, Что Путь поиска файлов MATLAB? MATLAB. Добавление пакета к пути MATLAB позволяет вам использовать пользовательские классы памяти, неважно, где вы устанавливаете свою текущую папку.

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

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

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

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

  2. Использование Выбирать Package, чтобы выбрать пакет ссылки. Пакет должен быть перезаписываем.

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

  4. Нажмите New Reference.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Похожие темы