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 (система, incFileName) функция в файле вашей S-функции TLC. Например, когда вы добавляете 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-функции при помощи Legacy Code Tool. Используйте эти команды в своем окне MATLAB Command:

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/BR2021bd_1724986_151598/publish_examples7/tp70d3319e_84eb_45d9_8a29_5f6618c7351a/coderdemo', '-c', '-outdir', '/tmp/BR2021bd_1724986_151598/publish_examples7/tp3ebd6c31_73b0_4eaa_bd53_bc2a968bd630', '/tmp/BR2021bd_1724986_151598/publish_examples7/tp70d3319e_84eb_45d9_8a29_5f6618c7351a/coderdemo/doubleIt.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sfun_mySrc.c', '-I/tmp/BR2021bd_1724986_151598/publish_examples7/tp70d3319e_84eb_45d9_8a29_5f6618c7351a/coderdemo', '/tmp/BR2021bd_1724986_151598/publish_examples7/tp3ebd6c31_73b0_4eaa_bd53_bc2a968bd630/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 установлен в истину.

7. На панели инструментов Simulink откройте приложение Simulink Coder или Embedded 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-функции при помощи Legacy Code Tool. Не включайте опцию S-функции supportCodeReuseAcrossModels. Используйте эти команды в своем окне MATLAB Command:

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/BR2021bd_1724986_151598/publish_examples7/tp8992dc32_36b8_435a_ad90_f27aa696f149/coderdemo', '-c', '-outdir', '/tmp/BR2021bd_1724986_151598/publish_examples7/tp36d20b1d_97b8_4fd1_9319_a91685ba27b7', '/tmp/BR2021bd_1724986_151598/publish_examples7/tp8992dc32_36b8_435a_ad90_f27aa696f149/coderdemo/doubleIt.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sfun_mySrc.c', '-I/tmp/BR2021bd_1724986_151598/publish_examples7/tp8992dc32_36b8_435a_ad90_f27aa696f149/coderdemo', '/tmp/BR2021bd_1724986_151598/publish_examples7/tp36d20b1d_97b8_4fd1_9319_a91685ba27b7/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 откройте приложение Simulink Coder или Embedded 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;

Похожие темы

Для просмотра документации необходимо авторизоваться на сайте