exponenta event banner

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

Для некоторых приложений для управления размещением данных (глобальных переменных) и определений функций в памяти можно использовать прагматики и другие декорации кода. Например, файл конфигурации компоновщика может определять именованные разделы в SECTIONS и сопоставить каждый раздел с диапазоном адресов памяти. В код C включаются прагматики, которые назначают глобальные переменные и функции этим именованным разделам и, по расширению, диапазонам памяти. Управляя размещением памяти, можно:

  • Создайте код, который будет эффективнее для вашего оборудования.

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

Разделы Embedded Coder ® и памяти позволяют:

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

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

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

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

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

Вставка прагматиков с помощью разделов памяти

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

Изучение примерной модели и проверка созданного по умолчанию кода

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

    open_system('rtwdemo_roll')
    

    Модель сконфигурирована для создания эффективного производственного кода. Например, параметр конфигурации Default parameter behavior имеет значение Inlined.

  2. В коллекции Приложения в разделе Создание кода щелкните Встроенный кодер. Откроется вкладка Код C (C Code). Создайте код из модели.

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

    /* Block signals and states (default storage) for system '<Root>' */
    typedef struct {
      real32_T FixPtUnitDelay1_DSTATE;     /* '<S7>/FixPt Unit Delay1' */
      real32_T Integrator_DSTATE;          /* '<S1>/Integrator' */
      int8_T Integrator_PrevResetState;    /* '<S1>/Integrator' */
    } DW;
    

    Файл также объявляет функции точек входа для модели.

    /* Model entry point functions */
    extern void rtwdemo_roll_initialize(void);
    extern void rtwdemo_roll_step(void);
  4. Осмотреть rtwdemo_roll.c. Этот файл определяет переменные глобальной структуры для хранения данных. Файл также определяет функции.

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

  • Для глобальной переменной с именем myVar, синтаксис прагматики:

    #pragma SEC_MYALGORITHM_DATA("myVar")
    
    double myVar;

  • Для функции с именем myFunction, синтаксис pragma тот же, за исключением имени раздела:

    #pragma SEC_MYALGORITHM_CODE("myFunction")
    
    void myFunction(void)

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

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

  1. Откройте приложение Embedded Coder. На вкладке C Code выберите Code Interface > Embedded Coder Dictionary.

  2. В диалоговом окне Embedded Coder Dictionary выберите вкладку Memory Sections и нажмите кнопку Add.

  3. Для нового раздела памяти установите следующие параметры:

    • Имя для MYALGORITHM_DATA.

    • Заявления окружают Each variable.

    • Предварительная выписка по #pragma SEC_MYALGORITHM_DATA("$N"). Символ $N имя каждой переменной, использующей раздел памяти.

  4. Создать другой, похожий раздел памяти, соответствующий MYALGORITHM_CODE.

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

  1. На вкладке Код C выберите Интерфейс кода > Сопоставления кодов по умолчанию или Интерфейс кода > Сопоставления кодов отдельных элементов

  2. На вкладке «Значения по умолчанию» разверните узлы «Порты ввода и вывода», «Сигналы и параметры».

  3. В таблице выберите строку Inports.

  4. В инспекторе свойств задайте для параметра «Раздел памяти» значение MYALGORITHM_DATA.

  5. Для остальных строк в таблице установите для параметра «Раздел памяти» значение MYALGORITHM_DATA.

  6. В разделе «Параметры функции по умолчанию» для каждой строки в таблице установите для параметра «Раздел памяти» значение MYALGORITHM_CODE.

  7. В текущей папке удалите существующую slprj папка.

  8. Настройте модель для генерации только кода. Выберите параметр конфигурации Параметры конфигурации > Только генерировать код.

  9. Щелкните Создать код (Generate Code).

Теперь, rtwdemo_roll.c файл применяет прагматики к определениям структурных переменных и функций. Для каждой категории данных и функций, настроенных в редакторе сопоставлений кода, код применяет прагматику. Например, код применяет MYALGORITHM_DATA pragma для каждой из структур, которые хранят состояния блоков, входы корневого уровня и выходы корневого уровня.

/* Block signals and states (default storage) */
#pragma SEC_MYALGORITHM_DATA("rtDW")

DW rtDW;

/* External inputs (root inport signals with default storage) */
#pragma SEC_MYALGORITHM_DATA("rtU")

ExtU rtU;

/* External outputs (root outports fed by signals with default storage) */
#pragma SEC_MYALGORITHM_DATA("rtY")

ExtY rtY;

Сохранить раздел памяти по умолчанию после применения класса хранения по умолчанию или шаблона функции

В редакторе сопоставлений кодов можно использовать столбцы Класс хранилища и Шаблон настройки функций для управления внешним видом данных и функций в сгенерированном коде по умолчанию. При использовании этих столбцов для применения параметра, отличного от Defaultредактор сопоставлений кода отбрасывает раздел памяти, примененный в Инспекторе свойств. Чтобы сохранить раздел памяти, используйте Embedded Coder Dictionary для создания класса хранения или шаблона функции, а затем примените раздел памяти к этому классу хранения или шаблону функции.

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

  1. В словаре встроенного кодера для модели выберите вкладку Классы хранения и нажмите кнопку Добавить.

  2. Для нового класса хранения установите:

    • Имя для STRUCT_DATA.

    • Тип склада для Structured.

    • Раздел памяти для MYALGORITHM_DATA.

  3. В редакторе сопоставлений кодов в разделе «Значения по умолчанию» в столбце «Класс хранения» выберите STRUCT_DATA для этих строк:

    • Inports

    • Вспомогательные порты

    • Сигналы, состояния и внутренние данные

  4. Создайте код из модели.

  5. Осмотреть rtwdemo_roll.c. Теперь файл определяет одну структурную переменную, которая содержит непараметрические данные, применяя прагматику к этой переменной.

    /* Storage class 'STRUCT_DATA' */
    #pragma SEC_MYALGORITHM_DATA("STRUCT_DATA_rtwdemo_roll")
    
    rtwdemo_roll_STRUCT_DATA STRUCT_DATA_rtwdemo_roll;

Включение секции памяти по умолчанию в класс хранения для индивидуального отображения

Чтобы переопределить классы хранения по умолчанию, указанные в разделе Сопоставления кода - C > Значения по умолчанию, примените класс хранения непосредственно к элементу данных с помощью редактора Сопоставления кода. Прямое применение класса хранения, отличного от Auto или Model default обходит раздел памяти по умолчанию, указанный в параметрах данных по умолчанию. Чтобы сохранить раздел памяти, создайте класс хранения в словаре встроенного кодера и примените к нему требуемый раздел памяти. Затем примените класс хранения к отдельным элементам данных в редакторе сопоставлений кодов. Другие модели не могут получить доступ к классу хранения и разделу памяти, определенным в словаре встроенного кодера. Чтобы совместно использовать классы хранения и разделы памяти среди других моделей, сохраните Embedded Coder Dictionary в данных Simulink Data Dictionary (sldd) за пределами модели. Затем разделите словарь между целевыми моделями. Дополнительные сведения см. в разделе Перенос определений из файла модели в словарь общих данных.

В rtwdemo_roll, в BasicRollMode три блока усиления представляют параметры алгоритма управления PID. В разделе Сохранить память по умолчанию после применения класса хранения по умолчанию или шаблона функции настройте отображение непараметрических данных модели, таких как сигналы и состояния, в одной структуре путем применения класса хранения по умолчанию. STRUCT_DATA. В этом примере выходные сигналы блоков усиления настраиваются таким образом, чтобы сгенерированный код распределял для них память в MYALGORITHM_DATA раздел не отображается в структуре класса хранения по умолчанию. Определение нового класса хранения myStore в словаре встроенного кодера и применить требуемый раздел памяти MYALGORITHM_DATA к нему. Затем непосредственно примените класс хранения к выходным сигналам блоков усиления.

  1. В словаре Embedded Coder модели выберите вкладку Storage Classes и нажмите кнопку Add.

  2. Для нового класса хранения установите:

    • Имя для myStore.

    • Тип склада для Structured.

    • Раздел памяти для MYALGORITHM_DATA.

  3. В модели перейдите в папку BasicRollMode подсистема. Сигналы подсистемы не заносятся автоматически в редактор сопоставлений кода. Чтобы открыть панель действий, необходимо вручную добавить сигналы, приостановив многоточие над или под линией сигнала. Нажмите кнопку Add Signal (Добавить сигнал). Эта кнопка также доступна в редакторе сопоставлений кодов на вкладке «Сигналы/Состояния».

  4. После добавления выходных сигналов блоков усиления строки сигналов отображаются на вкладке Сопоставления кодов -C > Сигналы/состояния. Откройте инспектор свойств, выбрав строки сигнала. В разделе «Код» задайте следующие свойства:

    • Класс хранения для myStore.

    • Идентификатор имен блоков.

  5. Создайте код из модели.

  6. Проверка созданного файла rtwdemo_roll.c. Файл определяет структурную переменную myStore_rtwdemo_roll и применяет прагматику к переменной.

    /* Storage class 'myStore' */
    #pragma SEC_MYALGORITHM_DATA("myStore_rtwdemo_roll")
    
    rtwdemo_roll_myStore myStore_rtwdemo_roll;

  7. Проверка созданного файла rtwdemo_roll.h. Структурная переменная содержит выходные сигналы блоков усиления. Выходные сигналы теперь находятся в другой структуре, но хранятся в той же самой структуре. MYALGORITHM_DATA раздел памяти.

/* Storage class 'myStore', for system '<Root>' */
typedef struct {
  real32_T DispGain;                   /* '<S1>/DispGain' */
  real32_T RateGain;                   /* '<S1>/RateGain' */
  real32_T IntGain;                    /* '<S1>/IntGain' */
} rtwdemo_roll_myStore;

Настройка Pragma для окружающих групп определений

Если для создания инструментальной цепочки требуется, чтобы прагматика или другое оформление окружали сразу несколько определений переменных или функций, в словаре Embedded Coder Dictionary или Custom Storage Class Designer установите параметр Операторы окружают Group of variables (значение по умолчанию в конструкторе пользовательских классов хранения).

Переопределить размещение памяти по умолчанию для отдельных элементов данных

После настройки параметров раздела памяти по умолчанию в редакторе сопоставлений кода (см. раздел Настройка генерации кода C по умолчанию для категорий элементов и функций данных), чтобы переопределить эти параметры по умолчанию для отдельных элементов данных (сигналов, параметров и состояний), создайте класс хранения и все необходимые разделы памяти с помощью словаря Embedded Coder. Дополнительные сведения см. в разделе Определение раздела «Выбор места для создания и сохранения памяти». При создании класса хранения установите для свойства раздела памяти соответствующий раздел памяти. Затем с помощью редактора сопоставлений кодов примените класс хранения к отдельным элементам данных.

Выберите, где создать и сохранить определение раздела памяти

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

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

    Если необходимо использовать раздел памяти только в редакторе сопоставлений кодов и использовать его совместно с другими моделями, определите раздел памяти в словаре данных Simulink ® (sldd). Дополнительные сведения см. в разделе Совместное определение словаря встроенного кодера между моделями.

  • Если необходимо использовать раздел памяти вне редактора сопоставлений кода, определите раздел памяти в пакете. Например, определите разделы памяти в пакете для настройки разделов памяти атомной подсистемы. Дополнительные сведения см. в разделе Переопределение памяти для атомной подсистемы.

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

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

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

Переопределить раздел памяти для атомной подсистемы

Разделы памяти, заданные для подсистемы, переопределяют значения по умолчанию на уровне модели, заданные в редакторе сопоставлений кодов. Этот метод используется для объединения данных и кода команд для подпрограмм или подкомпонентов (представленных подсистемами) в различные области памяти. Чтобы применить раздел памяти непосредственно к атомной подсистеме, определите раздел памяти в пакете с помощью Custom Storage Class Designer. Невозможно использовать раздел памяти, определенный в словаре встроенного кодера. Затем загрузите пакет в модель и настройте параметры блока подсистемы, чтобы указать раздел памяти.

Чтобы создать раздел памяти:

  1. В текущей папке создайте папку с именем +myPackage. Папка определяет пакет с именем myPackage. Дополнительные сведения см. в разделе Создание пакета классов данных.

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

  2. Откройте конструктор пользовательских классов хранения.

    cscdesigner('myPackage');
    
  3. В конструкторе пользовательских классов хранения выберите вкладку «Раздел памяти».

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

  5. Для нового раздела памяти установите следующие параметры:

    • Имя для MYALGORITHM_DATA.

    • Заявления окружают Each variable.

    • Предварительная выписка по #pragma SEC_MYALGORITHM_DATA("$N").

  6. Щелкните Применить (Apply) и Сохранить (Save).

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

Чтобы применить раздел памяти в атомной подсистеме:

  1. Сконфигурируйте Embedded Coder Dictionary модели для загрузки целевого пакета, как описано в разделе Описание генерации кода в пакете.

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

    • Установить упаковку функций в Nonreusable function или Reusable function (для кода повторного ввода).

    • Если для параметра Function packaging установлено значение Nonreusable function, чтобы включить настройку разделов памяти для данных подсистемы, выберите Функцию с отдельными данными. Если не выбрана Функция с отдельными данными, данные подсистемы наследуют разделы памяти из модели или, если применимо, родительской подсистемы.

    • Применение MYALGORITHM_DATA раздел памяти непосредственно к функциям подсистемы и данным, используйте следующие параметры блока:

      • Раздел памяти для инициализации/завершения функций

      • Раздел памяти для выполнения функций

      • Раздел памяти для констант

      • Раздел памяти для внутренних данных

      • Раздел памяти для параметров

Укажите, что атомарная подсистема не использует раздел памяти

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

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

  • Раздел памяти для инициализации/завершения функций

  • Раздел памяти для выполнения функций

  • Раздел памяти для констант

  • Раздел памяти для внутренних данных

  • Раздел памяти для параметров

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

Ограничения и другие соображения

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

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

Раздел совместного использования памяти между пакетами (только разделы памяти пакетов)

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

Настройка пакета для обращения к разделу памяти, определенному в другом пакете:

  1. Откройте конструктор классов настраиваемых хранилищ. В командной строке введите cscdesigner.

  2. Выберите вкладку «Раздел памяти».

  3. Используйте команду Выбрать пакет (Select Package), чтобы выбрать пакет, в котором требуется сослаться на класс или раздел, определенный в каком-либо другом пакете.

  4. На панели Определения разделов памяти (Memory section definitions) выберите существующее определение, под которым требуется вставить ссылку.

  5. Щелкните Создать привязку (New Reference).

    Новая ссылка с именем и свойствами по умолчанию появится под ранее выбранным определением. Новая привязка будет выбрана, и появится вкладка Привязка (Reference), на которой будут показаны исходные свойства привязки.

  6. Используйте поле Наименование (Name), чтобы ввести имя для новой ссылки. Имя должно быть уникальным в импортирующем пакете, но может дублировать имя в исходном пакете.

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

  8. Задайте для раздела «Память» значение «Ссылка», чтобы указать раздел памяти, на который следует ссылаться.

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

Раскрывающийся список управления внешним видом секции памяти (только секции памяти пакета)

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

Определения защиты разделов памяти пакета (только разделы памяти пакета)

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

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

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

.

Ограничения

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

    • ExportedGlobal

    • ImportedExtern

    • ImportedExternPointer

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

    • ExportedGlobal

    • ImportedExtern

    • ImportedExternPointer

    Генератор кода пропускает квалификатор из других категорий данных.

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

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

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

Изучение примера модели

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

open_system('rtwdemo_memsec')

  1. Чтобы просмотреть разделы памяти в пакете ECoderDemos, нажмите кнопку «Определения разделов памяти» в модели, а затем выберите вкладку «Разделы памяти».

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

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

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

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