Можно повторно использовать сгенерированный код для идентичных подсистем, которые происходят в нескольких образцах в модели и между ссылочными моделями. Для получения дополнительной информации о генерации кода подсистем для повторного использования кода, смотрите, Генерация управления функций для подсистем.
Чтобы использовать 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-функции установите оба следующих флага:
SS_OPTION_WORKS_WITH_CODE_REUSE флаг в ssSetOptions функция
ssSetSupportedForCodeReuseAcrossModels установлено на 1 или true
Если вы используете 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-функции с помощью Legacy Code Tool. Используйте следующие команды в окне Команда 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. Сгенерируйте код для модели. На вкладке Кода С нажатия кнопки 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-функции установите 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:
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. Сгенерируйте код для модели. На вкладке Кода С нажатия кнопки 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;