Target Language Compiler 是代码生成工具, Simulink Coder/Embedded Coder 会使用这个工具,去执行 .tlc 文件。 tlc 文件里描述了如何将 .rtw 变成代码。
代码生成用到的 .tlc 文件是一系列,而不是单单是一个或者一类。
%% SYSTLC: STM32F4 Target TMF: ert_default_tmf MAKE: make_rtw EXTMODE: ext_comm
%selectfile NULL_FILE
%assign CodeFormat = "Embedded-C"
%assign TargetType = "RT"
%assign Language = "C"
%include "codegenentry.tlc"
/%
BEGIN_RTW_OPTIONS
%----------------------------------------%
% Configure RTW code generation settings %
%----------------------------------------%
rtwgensettings.BuildDirSuffix = '_stm32f4';
rtwgensettings.DerivedFrom = 'ert.tlc';
rtwgensettings.Version = '1';
END_RTW_OPTIONS
%/
第1行的注释%% SYSTLC: STM32F4 Target TMF: ert_default_tmf MAKE: make_rtw EXTMODE: ext_comm
对属性进行了描述,告诉Simulink环境,该系统目标文件支持哪些功能,这里支持
%selectfile NULL_FILE
,要做一个函数级的或非脚本类型的,写这句。%assign CodeFormat = "Embedded-C"
,定义变量,说明支持生成代码的类型为嵌入式C代码%assign TargetType = "RT"
,生成代码的目标类型为实时硬件%assign Language = "C"
,生成C语言代码另外还有其他的命令,如下:
%assign AutoBuildProcedure = !GenerateSampleERTMain
,不生成模板的ert文件
%include "commontargetlib.tlc"
,将commontargetlib.tlc展开执行
%include "codegenentry.tlc"
,将codegenentry.tlc展开执行
tlc文件的后半部分为宏定义,以/% BEGIN_RTW_OPTIONS
开头,以/% END_RTW_OPTIONS
结束,定义了用户选择该tlc文件后,Code Generation的设置以及该栏下方的Tab栏显示内容。
上面的实例中没有对Tab栏显示内容做修改,下面的例子(ST公司提供的STM32-MAT-TARGET支持包)给出了添加Tab栏显示内容的实例:
%% SYSTLC: stm32 (Embedded Target) TMF: stm32.tmf MAKE: make_rtw \
%% EXTMODE: ext_comm
%selectfile NULL_FILE
%%
%% System Target File for stm32
%%
%% $ stm32.tlc 2009-05-14 dlange $
%%
%assign CodeFormat = "Embedded-C"
%assign TargetType = "RT"
%assign Language = "C"
%include "codegenentry.tlc"
/%
BEGIN_RTW_OPTIONS
oIdx = 1;
rtwoptions(oIdx).prompt = 'STM32 Options';
rtwoptions(oIdx).type = 'Category';
rtwoptions(oIdx).enable = 'on';
rtwoptions(oIdx).default = 8;
rtwoptions(oIdx).popupstrings = '';
rtwoptions(oIdx).tlcvariable = '';
rtwoptions(oIdx).tooltip = '';
rtwoptions(oIdx).callback = '';
rtwoptions(oIdx).makevariable = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Download Application';
rtwoptions(oIdx).type = 'Checkbox';
rtwoptions(oIdx).default = 'on';
rtwoptions(oIdx).tlcvariable = 'DownloadApplication';
rtwoptions(oIdx).makevariable = 'DOWNLOADAPPLICATION';
rtwoptions(oIdx).tooltip = ...
['Select to open STM32 generated project.'];
rtwoptions(oIdx).callback = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'STM32CubeMx Path update';
rtwoptions(oIdx).type = 'Checkbox';
rtwoptions(oIdx).default = 'off';
rtwoptions(oIdx).tlcvariable = 'STM32CubeMxPathUpdate';
rtwoptions(oIdx).makevariable = 'STM32CUBEMXPATHUPDATE';
rtwoptions(oIdx).tooltip = ...
['Get STM32CubeMx path from registry. Uncheck to modify path manually.'];
rtwoptions(oIdx).callback = 'stm32cubemxpath_callback(hDlg, hSrc, ''STM32CubeMxPathUpdate'')';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'STM32CubeMx installation path';
rtwoptions(oIdx).type = 'Edit';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).tlcvariable = 'STM32CubeMxPath';
rtwoptions(oIdx).makevariable = 'STM32CUBEMXPATH';
rtwoptions(oIdx).enable = 'on';
rtwoptions(oIdx).tooltip = ...
['installation path for STM32CubeMx'];
rtwoptions(oIdx).callback = 'stm32cubemxpath_callback(hDlg, hSrc, ''STM32CubeMxPath'')';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Installed Path';
rtwoptions(oIdx).type = 'NonUI';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).tlcvariable = 'Target_Inst_path';
rtwoptions(oIdx).makevariable = 'TARGET_INST_PATH';
rtwoptions(oIdx).enable = 'off';
rtwoptions(oIdx).tooltip = '';
rtwoptions(oIdx).callback = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Installed Full Path';
rtwoptions(oIdx).type = 'Edit';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).tlcvariable = 'Target_Inst_Fullpath';
rtwoptions(oIdx).makevariable = 'TARGET_INST_FULLPATH';
rtwoptions(oIdx).enable = 'off';
rtwoptions(oIdx).tooltip = ...
['Path to package added with pathtool command.'];
rtwoptions(oIdx).callback = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Update installed path';
rtwoptions(oIdx).type = 'Pushbutton';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).tlcvariable = 'UpdateInstalledPath';
rtwoptions(oIdx).makevariable = 'UPDATEINSTALLEDPATH';
rtwoptions(oIdx).tooltip = ...
['Click to automatically update package installation path.'];
rtwoptions(oIdx).callback = 'stm32updatepath_callback(hDlg, hSrc)';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Model configuration (ioc) Full Path';
rtwoptions(oIdx).type = 'Edit';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).tlcvariable = 'Ioc_Fullpath';
rtwoptions(oIdx).makevariable = 'IOC_FULLPATH';
rtwoptions(oIdx).enable = '';
rtwoptions(oIdx).tooltip = ...
['Path to ioc configuration file.'];
rtwoptions(oIdx).callback = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Interrupt Handler Optimization';
rtwoptions(oIdx).type = 'Checkbox';
rtwoptions(oIdx).default = 'on';
rtwoptions(oIdx).tlcvariable = 'IT_Handler_Optim';
rtwoptions(oIdx).makevariable = 'IT_HANDLER_OPTIM';
rtwoptions(oIdx).tooltip = ...
['HAL IRQ Handler not generated from STM32CubeMX. Code is not generated in HAL callback function but directly in IRQ Handler. '];
rtwoptions(oIdx).callback = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'STM32 Project Files';
rtwoptions(oIdx).type = 'Category';
rtwoptions(oIdx).enable = 'on';
rtwoptions(oIdx).default = 5;
rtwoptions(oIdx).popupstrings = '';
rtwoptions(oIdx).tlcvariable = '';
rtwoptions(oIdx).tooltip = '';
rtwoptions(oIdx).callback = '';
rtwoptions(oIdx).makevariable = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Append to list';
rtwoptions(oIdx).type = 'Checkbox';
rtwoptions(oIdx).enable = '';
rtwoptions(oIdx).default = 'on';
rtwoptions(oIdx).popupstrings = '';
rtwoptions(oIdx).tlcvariable = 'STM32AppendToList';
rtwoptions(oIdx).makevariable = '';
rtwoptions(oIdx).tooltip = ...
['Files and paths selected will be appended to the list'];
rtwoptions(oIdx).callback = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Select source files (.c)';
rtwoptions(oIdx).type = 'Pushbutton';
rtwoptions(oIdx).enable = '';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).popupstrings = '';
rtwoptions(oIdx).tlcvariable = 'UpdateCFilelist';
rtwoptions(oIdx).makevariable = '';
rtwoptions(oIdx).tooltip = ...
['Click to open multiselect window'];
rtwoptions(oIdx).callback = 'stm32updateCfileList_callback(hDlg, hSrc, ''STM32AppendToList'')';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'C files included to project';
rtwoptions(oIdx).type = 'Edit';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).tlcvariable = 'CProjectFiles';
rtwoptions(oIdx).makevariable = '';
rtwoptions(oIdx).enable = '';
rtwoptions(oIdx).tooltip = ...
['C files include functions that can be called from Simulink MATLAB Function'];
rtwoptions(oIdx).callback = '';
rtwoptions(oIdx).popupstrings = '';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Select include files (.h)';
rtwoptions(oIdx).type = 'Pushbutton';
rtwoptions(oIdx).enable = '';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).popupstrings = '';
rtwoptions(oIdx).tlcvariable = 'UpdateHPathlist';
rtwoptions(oIdx).makevariable = '';
rtwoptions(oIdx).tooltip = ...
['Click to open multiselect window'];
rtwoptions(oIdx).callback = 'stm32updateHPathList_callback(hDlg, hSrc, ''STM32AppendToList'')';
oIdx = oIdx + 1;
rtwoptions(oIdx).prompt = 'Header files added to project';
rtwoptions(oIdx).type = 'Edit';
rtwoptions(oIdx).default = '';
rtwoptions(oIdx).tlcvariable = 'HPathFiles';
rtwoptions(oIdx).makevariable = '';
rtwoptions(oIdx).enable = '';
rtwoptions(oIdx).tooltip = ...
['Header files included for C functions that can be called from Simulink MATLAB Function'];
rtwoptions(oIdx).callback = '';
rtwoptions(oIdx).popupstrings = '';
%----------------------------------------%
% Configure RTW code generation settings %
%----------------------------------------%
rtwgensettings.DerivedFrom = 'ert.tlc';
rtwgensettings.BuildDirSuffix = '_stm32';
rtwgensettings.Version = '1';
rtwgensettings.SelectCallback = ['stm32_SelectCallback(hDlg, hSrc)'];
%rtwgensettings.ActivateCallback = ['stm32_ActivateCallback(hDlg, hSrc)'];
rtwgensettings.PostApplyCallback = ['stm32_PostApplyCallback(hDlg, hSrc)'];
END_RTW_OPTIONS
%/
%% [EOF]: stm32.tlc
/%
BEGIN_RTW_OPTIONS
%----------------------------------------%
% Configure RTW code generation settings %
%----------------------------------------%
rtwgensettings.BuildDirSuffix = '_stm32f4';
rtwgensettings.DerivedFrom = 'ert.tlc';
rtwgensettings.Version = '1';
END_RTW_OPTIONS
%/
rtwgensettings.BuildDirSuffix = '_stm32f4';
设置代码生成的文件夹名字
rtwgensettings.DerivedFrom = 'ert.tlc';
继承ert.tlc的模板
另外,在 % Configure RTW code generation settings %
中还有回调函数的定义,这里给出autosar.tlc的实例,具体代码段如下:
/%
BEGIN_RTW_OPTIONS
rtwoptions = autosar_rtwoptions_callback('GetOptions', rtwoptions);
rtwgensettings.BuildDirSuffix = '_autosar_rtw';
rtwgensettings.Version = autosarcore.rtwOptions('GetRtwOptionsVersion');
rtwgensettings.SelectCallback = 'autosar_rtwoptions_callback(''SelectCallBack'', hSrc, hDlg)';
rtwgensettings.ActivateCallback = 'autosar_rtwoptions_callback(''ActivateCallBack'', hSrc, hDlg)';
rtwgensettings.DerivedFrom = 'ert.tlc';
END_RTW_OPTIONS
%/
这里出现了两个回调函数
rtwgensettings.SelectCallback = 'autosar_rtwoptions_callback(''SelectCallBack'', hSrc, hDlg)';
rtwgensettings.ActivateCallback = 'autosar_rtwoptions_callback(''ActivateCallBack'', hSrc, hDlg)';
回调函数格式为:
% 在Code Generation的TLC选择框内选择该tlc文件后执行哪些动作
% 这个callback_handler可以由用户自行定义
rtwgensettings.SelectCallback =callback_handler(hDlg,hSrc);
rtwgensettings.ActivateCallback = callback_handler(hDlg,hSrc);
rtwgensettings.PostApplyCallback = callback_handler(hDlg,hSrc);
callback_handler可以以.m的函数文件放置到tlc文件所在路径下。下面给出一个具体的实例(该实例为SCANeR提供的ert_scanerapi_select.m)
function ert_scanerapi_select(hDlg, hSrc)
slConfigUISetVal(hDlg, hSrc, 'StopTime', 'inf');
slConfigUISetVal(hDlg, hSrc, 'SolverType', 'Fixed-step');
slConfigUISetVal(hDlg, hSrc, 'Solver', 'FixedStepDiscrete');
slConfigUISetVal(hDlg, hSrc, 'SupportContinuousTime', 'on');
slConfigUISetVal(hDlg, hSrc, 'SupportNonInlinedSFcns', 'on');
slConfigUISetVal(hDlg, hSrc, 'GenerateSampleERTMain', 'off');
slConfigUISetEnabled(hDlg, hSrc, 'GenerateSampleERTMain', false);
slConfigUISetVal(hDlg, hSrc, 'ModelReferenceCompliant', 'on');
% slConfigUISetEnabled(hDlg, hSrc, 'ModelReferenceCompliant', false);
其中,hDlg
为configuration parameters的句柄,hSrc
为模型的句柄,slConfigUISetVal
为Simulink的built-in函数,一共4个参数,前两个为hDlg
和hSrc
,后面两个为要设置的参数名
和对应的参数值
,slConfigUISetEnabled
同理,设置enabled用。
【提示】要查看参数名,在Configuration Parameters的对话框内需要查看的内容处右键,what’s This?后查看,如图。
点击show more information后可以查看该参数的具体设置:
如果是针对嵌入式开发,callback_handler中可以将下列命令引入:
function ert_example_select(hDlg, hSrc)
% 设置固定点步长,并禁止修改
slConfigUISetVal(hDlg, hSrc, 'SolverType', 'Fixed-step');
slConfigUISetEnabled(hDlg, hSrc, 'SolverType', 'off');
% 设置离散求解器
slConfigUISetVal(hDlg, hSrc, 'Solver', 'FixedStepDiscrete');
% 设置默认采样时间
slConfigUISetVal(hDlg, hSrc, 'FixedStep', '0.1');
% 设置内联参数
% 高版本的MATLAB中这个参数修改为Default parameter behavior ?
slConfigUISetVal(hDlg, hSrc, 'InlineParams', 'on');
% 生成报告
slConfigUISetVal(hDlg, hSrc, 'GenerateReport', 'on');
% 自动打开报告
slConfigUISetVal(hDlg, hSrc, 'LaunchReport', 'on');
% 只生成代码
slConfigUISetVal(hDlg, hSrc, 'GenCodeOnly', 'on');
% 不生成makefile(不生成可执行文件,不需要makefile文件)
slConfigUISetVal(hDlg, hSrc, 'GenerateMakefile', 'off');
% 生成注释
slConfigUISetVal(hDlg, hSrc, 'GenerateComments', 'on');
% 生成A2L文件
slConfigUISetVal(hDlg, hSrc, 'GenerateASAP2', 'on');
使用for循环改写上面的.m回调函数:
function ert_example_select_for_loop(hDlg, hSrc)
configs = {'SolverType','on';
'Solver','FixedStepDiscrete';
'FixedStep', '0.1';
'InlineParams', 'on';
'GenerateReport', 'on';
'LaunchReport', 'on';
'GenCodeOnly', 'on';
'GenerateMakefile', 'off';
'GenerateComments', 'on';
'GenerateASAP2', 'on';};
for i = 1:length(configs)
slfConfigUISetVal(hDlg,hSrc,configs{i,1},configs{i,2});
end
slConfigUISetEnabled(hDlg, hSrc, 'SolverType', 'off');
在实际建模时,可以将修改system target file的命令放置到某个config模块的回调函数中,这样,只要拖入该模块,就可以实现自动将系统目标文件修改的目的。
【注意】 下面两个命令可以在Matlab的command windows中对Simulink模型的system target file进行修改。
disableimplicitsignalresolution(bdroot);
set_param(bdroot,‘SystemTargetFile’,‘ert_example.tlc’)
链接:https://pan.baidu.com/s/1-q1a8Kt4D9SU-AaG-qODIw
提取码:5aax