exponenta event banner

S-функции для повторного использования кода

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

Требования к повторному использованию кода S-функции

Чтобы использовать S-функцию для повторного использования кода для подсистемы, S-функция должна удовлетворять следующим требованиям:

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

  • Код, созданный из S-функции, не должен использовать статические переменные.

  • S-функция должна инициализировать рабочий вектор указателя только в mdlStart и не раньше.

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

  • S-функция должна регистрировать свои параметры как параметры времени выполнения в mdlSetWorkWidths. Для этого S-функция не должна использовать ssWriteRTWParameters в своем mdlRTW функция.

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

Кроме того, ваша S-функция должна установить SS_OPTION_WORKS_WITH_CODE_REUSE в функции ssSetOptions. Этот флаг указывает, что функция S соответствует требованиям для повторного использования кода подсистемы. Если флажок установлен и функция S не соответствует требованиям, генератор кода не создает функцию многократного использования, и появляется предупреждение.

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

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

Если вы используете legacy_code инструмент для создания S-функции, опция S-функции supportCodeReuseAcrossModels определяет повторное использование кода в моделях для подсистемы, содержащей S-функцию.

Настройте S-функцию для повторного использования кода в моделях только в том случае, если S-функция не имеет доступа к структурам данных, специфичным для модели. Эта конфигурация необходима, поскольку созданный код в _sharedutils папка компилируется отдельно от созданного кода в model_ert_rtw folder. Код повторно используемой библиотечной подсистемы, сгенерированный в _sharedutils папка не имеет доступа к типам и макросам, объявленным в model.h. Код повторно используемой библиотечной подсистемы должен быть независимым. Дополнительные сведения см. в разделе Создание многократно используемого кода из библиотечных подсистем, совместно используемых в моделях.

Если функция S использует пользовательские функции, определенные в файлах внешних заголовков, добавьте функцию LibAddtoSystemCustomIncludes (system, incFileName) в файл TLC функции S. Например, при добавленииLibAddtoSystemCustomIncludes("company_math.h") в вашем .tlc файл, повторно используемый код библиотечной подсистемы в _sharedutils папка включает в себя #company_math.h файл заголовка.

1. Создайте новую рабочую папку MATLAB. В окне команд MATLAB скопируйте следующие внешние файлы кода в текущую рабочую папку MATLAB:

currentDir = pwd;
[~,cgDir] = rtwdemodir();
copyfile(fullfile(matlabroot,'toolbox','rtw','rtwdemos','doubleIt.c'));
copyfile(fullfile(matlabroot,'toolbox','rtw','rtwdemos','doubleIt.h'));

2. Открыть пример модели rtwdemo_sfcn_rls. В этом примере модели используются два экземпляра повторно используемой библиотечной подсистемы. rtwdemo_sfcn_rls_lib. S-функция sfun_mySrc внутри повторно используемой библиотечной подсистемы используются внешние файлы doubleIt.c и doubleIt.h.

rtwdemo_sfcn_rls;

3. Создайте код S-функции с помощью устаревшего инструмента кода. Используйте следующие команды в окне команды MATLAB:

def = legacy_code('initialize');
def.SFunctionName = 'sfun_mySrc';
def.SourceFiles = {'doubleIt.c'};
def.HeaderFiles = {'doubleIt.h'};
def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';

4. Укажите S-функцию для повторного использования кода:

def.Options.supportCodeReuseAcrossModels = true;

5. Создайте файл блока TLC кода S-функции. Затем скомпилируйте S-функцию.

legacy_code('sfcn_tlc_generate',def);
legacy_code('sfcn_cmex_generate', def);
legacy_code('compile', def);
### Start Compiling sfun_mySrc
    mex('-I/tmp/BR2021ad_1640230_185635/publish_examples0/tpf04d3736_4e5d_4505_8a34_093e4a511912/coderdemo', '-c', '-outdir', '/tmp/BR2021ad_1640230_185635/publish_examples0/tpc01b2f48_4d70_4f18_9c4b_7490c1380e4b', '/tmp/BR2021ad_1640230_185635/publish_examples0/tpf04d3736_4e5d_4505_8a34_093e4a511912/coderdemo/doubleIt.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sfun_mySrc.c', '-I/tmp/BR2021ad_1640230_185635/publish_examples0/tpf04d3736_4e5d_4505_8a34_093e4a511912/coderdemo', '/tmp/BR2021ad_1640230_185635/publish_examples0/tpc01b2f48_4d70_4f18_9c4b_7490c1380e4b/doubleIt.o')
Building with 'gcc'.
MEX completed successfully.
### Finish Compiling sfun_mySrc
### Exit

6. Генератор кода создает файл S-функции sfun_mySrc.c и его файл TLC sfun_mySrc.tlc в рабочей папке MATLAB. В sfun_mySrc.c файл, генератор кода добавляет следующие спецификации:

file = fullfile('sfun_mySrc.c');
rtwdemodbtype(file,'* All options have the form SS_OPTION_<name>', ...
    'ssSetSupportedForCodeReuseAcrossModels(S, 1);',1,1);
     * All options have the form SS_OPTION_<name> and are documented in
     * matlabroot/simulink/include/simstruc.h. The options should be
     * bitwise or'd together as in
     *    ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2))
     */
    ssSetOptions(S,
        SS_OPTION_USE_TLC_WITH_ACCELERATOR |
        SS_OPTION_CAN_BE_CALLED_CONDITIONALLY |
        SS_OPTION_EXCEPTION_FREE_CODE |
        SS_OPTION_WORKS_WITH_CODE_REUSE |
        SS_OPTION_SFUNCTION_INLINED_FOR_RTW |
        SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME
    );
    ssSetSupportedForCodeReuseAcrossModels(S, 1);

В sfun_mySrc.c, SS_OPTION_WORKS_WITH_CODE_REUSE флаг установлен в ssSetOptions функции и ssSetSupportedForCodeReuseAcrossModels имеет значение true.

7. На панели инструментов Simulink откройте приложение Embedded Coder или Simulink Coder.

8. Создайте код для модели. На вкладке C Code нажмите кнопку Build.

evalc('slbuild(''rtwdemo_sfcn_rls'')');

Генератор кода создает повторно используемую функцию, которая может быть повторно использована в моделях в _sharedutils папка. Модели в иерархии ссылок модели имеют общий доступ к этому _sharedutils для повторного использования кода. В этом примере повторно используемая функция генерируется в slprj/grt/_sharedutils/sfunc.c файл:

file = fullfile('slprj','grt','_sharedutils','sfunc.c');
rtwdemodbtype(file,'Output and update for atomic system', ...
    'rtb_sfun_mySrc',1,1);
 * Output and update for atomic system:
 *    'ReusableSubsystem' ('rtwdemo_sfcn_rls_lib:60')
 *    'ReusableSubsystem' ('rtwdemo_sfcn_rls_lib:60')
 */
void sfunc(real_T rtu_In1, B_sfunc_T *localB, DW_sfunc_T *localDW)
{
  /* local block i/o variables */
  real_T rtb_sfun_mySrc;

S-функции, повторно используемые в модели

По умолчанию S-функции в подсистеме не настроены для повторного использования кода в модели. Можно указать S-функции в подсистеме для повторного использования кода в модели. В файле S-функции установите SS_OPTION_WORKS_WITH_CODE_REUSE флаг в ssSetOptions функция. Этот флаг указывает, что функция S соответствует требованиям для повторного использования кода подсистемы и сконфигурирована для повторного использования кода. Если флажок установлен и функция S не соответствует требованиям, генератор кода не создает функцию многократного использования, и появляется предупреждение.

1. Создайте новую рабочую папку MATLAB и скопируйте эти внешние файлы кода в текущую рабочую папку MATLAB:

currentDir = pwd;
[~,cgDir] = rtwdemodir();
copyfile(fullfile(matlabroot,'toolbox','rtw','rtwdemos','doubleIt.c'));
copyfile(fullfile(matlabroot,'toolbox','rtw','rtwdemos','doubleIt.h'));

2. Для примера модели rtwdemo_sfcn_rls, создайте код S-функции с помощью устаревшего инструмента кода. Не включать опцию S-функции supportCodeReuseAcrossModels. Используйте следующие команды в окне команды MATLAB:

def = legacy_code('initialize');
def.SFunctionName = 'sfun_mySrc';
def.SourceFiles = {'doubleIt.c'};
def.HeaderFiles = {'doubleIt.h'};
def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';

3. Создайте файл блока TLC кода S-функции. Затем скомпилируйте S-функцию.

legacy_code('sfcn_tlc_generate',def);
legacy_code('sfcn_cmex_generate', def);
legacy_code('compile', def);
### Start Compiling sfun_mySrc
    mex('-I/tmp/BR2021ad_1640230_185635/publish_examples0/tp8a393614_6b24_45e7_b39f_f305a55f9966/coderdemo', '-c', '-outdir', '/tmp/BR2021ad_1640230_185635/publish_examples0/tp3827e55f_3739_4000_b4c7_513a2b1b8b31', '/tmp/BR2021ad_1640230_185635/publish_examples0/tp8a393614_6b24_45e7_b39f_f305a55f9966/coderdemo/doubleIt.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sfun_mySrc.c', '-I/tmp/BR2021ad_1640230_185635/publish_examples0/tp8a393614_6b24_45e7_b39f_f305a55f9966/coderdemo', '/tmp/BR2021ad_1640230_185635/publish_examples0/tp3827e55f_3739_4000_b4c7_513a2b1b8b31/doubleIt.o')
Building with 'gcc'.
MEX completed successfully.
### Finish Compiling sfun_mySrc
### Exit

4. Генератор кода создает файл S-функции sfun_mySrc.c и его файл TLC sfun_mySrc.tlc в рабочей папке MATLAB.

file = fullfile('sfun_mySrc.c');
rtwdemodbtype(file,'* All options have the form SS_OPTION_<name>', ...
    'SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME',1,1);
     * All options have the form SS_OPTION_<name> and are documented in
     * matlabroot/simulink/include/simstruc.h. The options should be
     * bitwise or'd together as in
     *    ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2))
     */
    ssSetOptions(S,
        SS_OPTION_USE_TLC_WITH_ACCELERATOR |
        SS_OPTION_CAN_BE_CALLED_CONDITIONALLY |
        SS_OPTION_EXCEPTION_FREE_CODE |
        SS_OPTION_WORKS_WITH_CODE_REUSE |
        SS_OPTION_SFUNCTION_INLINED_FOR_RTW |
        SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME

В sfun_mySrc.c файл, генератор кода добавляет SS_OPTION_WORKS_WITH_CODE_REUSE флаг в ssSetOptions функция по умолчанию, но не включает ssSetSupportedForCodeReuseAcrossModels спецификация, которая предотвращает повторное использование S-функции в моделях.

5. На панели инструментов Simulink откройте приложение Embedded Coder или Simulink Coder.

6. Создайте код для модели. На вкладке C Code нажмите кнопку Build.

evalc('slbuild(''rtwdemo_sfcn_rls'')');

Генератор кода создает повторно используемую функцию для подсистемы в rtwdemo_sfcn_rls.c файл, который находится вне _sharedutils папка. Этот код может быть повторно использован в модели, но не в иерархии ссылок на модель:

file = fullfile('rtwdemo_sfcn_rls_grt_rtw','rtwdemo_sfcn_rls.c');
rtwdemodbtype(file,'void sfunc', ...
    'localDW->UnitDelay_DSTATE = rtb_sfun_mySrc;',1,1);
void sfunc_Init(DW_sfunc_T *localDW)
{
  /* InitializeConditions for UnitDelay: '<S1>/Unit Delay' */
  localDW->UnitDelay_DSTATE = 0.0;
}

/*
 * Output and update for atomic system:
 *    '<Root>/ReusableSubsystem1'
 *    '<Root>/ReusableSubsystem2'
 */
void sfunc(real_T rtu_In1, B_sfunc_T *localB, DW_sfunc_T *localDW)
{
  /* local block i/o variables */
  real_T rtb_sfun_mySrc;

  /* UnitDelay: '<S1>/Unit Delay' */
  localB->UnitDelay = localDW->UnitDelay_DSTATE;

  /* S-Function (sfun_mySrc): '<S1>/sfun_mySrc' */
  rtb_sfun_mySrc = doubleIt(rtu_In1);

  /* Update for UnitDelay: '<S1>/Unit Delay' */
  localDW->UnitDelay_DSTATE = rtb_sfun_mySrc;

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