This example shows you the process of generating a simple source (.c
or
.cpp
) and header (.h
) file using the example CFP
template. Then, it examines the template and the code generated by the template.
The example CFP template,
,
demonstrates some of the capabilities of the code template API, includingmatlabroot
/toolbox/rtw/targets/ecoder/example_file_process.tlc
Generation of simple source (.c
or .cpp
) and
header (.h
) files
Use of buffers to generate file sections for includes, functions, and so on
Generation of includes, defines, into the standard generated files (for example,
)model
.h
Generation of a main program module
This section sets up a CFP template and configures a model to use the template in code
generation. The template generates (in addition to the standard model files) a source file
(timestwo.c
or .cpp
) and a header file
(timestwo.h
).
Follow the steps below to become acquainted with the use of CFP templates:
Copy the example CFP template,
,
to a folder outside of the MATLAB® folder structure (that is, not under
matlabroot
/toolbox/rtw/targets/ecoder/example_file_process.tlc
). If the folder is not on
the MATLAB path or the TLC path, then add it to the MATLAB path. It is good practice to locate the CFP template in the same folder as
your system target file, which is on the TLC path.matlabroot
Rename the copied example_file_process.tlc
to
test_example_file_process.tlc
.
Open test_example_file_process.tlc
into the
MATLAB editor.
Uncomment the following line:
%% %assign ERTCustomFileTest = TLC_TRUE
It now reads:
%assign ERTCustomFileTest = TLC_TRUE
If ERTCustomFileTest
is not assigned as shown, the CFP template
is ignored in code generation.
Save your changes to the file. Keep
test_example_file_process.tlc
open, so you can refer to it
later.
Open the rtwdemo_udt
model.
Open the Simulink® Model Explorer. Select the active configuration set of the model, and open the Code Generation pane of the active configuration set.
On the Templates tab, in the File
customization template field, specify
test_example_file_process.tlc
. This is the file you previously
edited and is now the specified CFP template for your model.
On the General tab, select the Generate code only check box.
Click Apply.
In the model window, press Ctrl+B. During code generation, notice the following message in the Diagnostic Viewer:
Warning: Overriding example ert_main.c!
This message is displayed because test_example_file_process.tlc
generates the main program module, overriding the default action of the ERT target. This
is explained in greater detail below.
The rtwdemo_udt
model is configured to generate
an HTML code generation report. After code generation is complete, view the
report.
Notice that the Generated Code list contains the following files:
Under Main file, ert_main.c
.
Under Other files, timestwo.c
and
timestwo.h
.
The files were generated by the CFP template. The next section examines the template to learn how this was done.
Keep the model, the code generation report, and the
test_example_file_process.tlc
file open so you can refer to them in
the next section.
This section examines excerpts from test_example_file_process.tlc
and
some of the code it generates. Refer to the comments in
while reading the following discussion.matlabroot
/rtw/c/tlc/mw/codetemplatelib.tlc
Source (.c
or .cpp
) and header
(.h
) files are created by calling
LibCreateSourceFile
, as in the following excerpts:
%assign cFile = LibCreateSourceFile("Source", "Custom", "timestwo") ... %assign hFile = LibCreateSourceFile("Header", "Custom", "timestwo")
Subsequent code refers to the files by the file reference returned from
LibCreateSourceFile
.
The code template API lets you partition the code generated to each file into
sections, tagged as Definitions
, Includes
,
Functions
, Banner
, and so on. You can append code
to each section as many times as required. This technique gives you a great deal of
flexibility in the formatting of your custom code files.
Subsections Defined for Built-In Sections describes the available file sections and their order in the generated file.
For each section of a generated file, use %openfile
and
%closefile
to store the text for that section in temporary buffers.
Then, to write (append) the buffer contents to a file section, call
LibSetSourceFileSection
, passing in the desired section tag and file
reference. For example, the following code uses two buffers (typesBuf
and tmpBuf
) to generate two sections (tagged
"Includes"
and "Functions"
) of the source file
timestwo.c
or .cpp
(referenced as
cFile
):
%openfile typesBuf #include "rtwtypes.h" %closefile typesBuf %<LibSetSourceFileSection(cFile,"Includes",typesBuf)> %openfile tmpBuf /* Times two function */ real_T timestwofcn(real_T input) { return (input * 2.0); } %closefile tmpBuf %<LibSetSourceFileSection(cFile,"Functions",tmpBuf)>
These two sections generate the entire timestwo.c
or
.cpp
file:
#include "rtwtypes.h" /* Times two function */ FLOAT64 timestwofcn(FLOAT64 input) { return (input * 2.0); }
The timestwo.c
or .cpp
file generated in the
previous example was independent of the standard code files generated from a model (for
example,
or model
.c.cpp
,
, and so on). You can use similar
techniques to generate custom code within the model files. The code template API includes
functions to obtain the names of the standard models files and other model-related
information. The following excerpt calls model
.hLibGetMdlPubHdrBaseName
to
obtain the name for the
file. It
then obtains a file reference and generates a definition in the model
.hDefines
section of
:model
.h
%% Add a #define to the model's public header file model.h %assign pubName = LibGetMdlPubHdrBaseName() %assign modelH = LibCreateSourceFile("Header", "Simulink", pubName) %openfile tmpBuf #define ACCELERATION 9.81 %closefile tmpBuf %<LibSetSourceFileSection(modelH,"Defines",tmpBuf)>
Examine the generated rtwdemo_udt.h
file to see the generated
#define
directive.
Normally, the ERT target determines whether and how to generate an
ert_main.c
or .cpp
module based on the settings of
the Generate an example main program and Target
operating system options on the Templates pane of the
Configuration Parameters dialog box. You can use a CFP template to override the normal
behavior and generate a main program module customized for your target environment.
To support generation of main program modules, two TLC files are provided:
bareboard_srmain.tlc
: TLC code to generate an example
single-rate main program module for a bareboard target environment. Code is generated
by a single TLC function, FcnSingleTaskingMain
.
bareboard_mrmain.tlc
: TLC code to generate a multirate main
program module for a bareboard target environment. Code is generated by a single TLC
function, FcnMultiTaskingMain
.
In the example CFP template file
,
the following code generates either a single- or multitasking
matlabroot
/toolbox/rtw/targets/ecoder/example_file_process.tlcert_main.c
or .cpp
module. The logic depends on
information obtained from the code template API calls
LibIsSingleRateModel
and
LibIsSingleTasking
:
%% Create a simple main. Files are located in MATLAB/rtw/c/tlc/mw. %if LibIsSingleRateModel() || LibIsSingleTasking() %include "bareboard_srmain.tlc" %<FcnSingleTaskingMain()> %else %include "bareboard_mrmain.tlc" %<FcnMultiTaskingMain()> %endif
Note that bareboard_srmain.tlc
and
bareboard_mrmain.tlc
use the code template API to generate
ert_main.c
or .cpp
.
When generating your own main program module, you disable the default generation of
ert_main.c
or .cpp
. The TLC variable
GenerateSampleERTMain
controls generation of
ert_main.c
or .cpp
. You can directly force this
variable to TLC_FALSE
. The examples
bareboard_mrmain.tlc
and bareboard_srmain.tlc
use
this technique, as shown in the following excerpt from
bareboard_srmain.tlc
.
%if GenerateSampleERTMain %assign CompiledModel.GenerateSampleERTMain = TLC_FALSE %warning Overriding example ert_main.c! %endif
Alternatively, you can implement a SelectCallback
function for your
target. A SelectCallback
function is a MATLAB function that is
triggered when you:
Load the model.
Update any configuration settings in the Configuration Parameters dialog box.
Build the model.
Your SelectCallback
function should deselect and disable
the Generate an example main program option. This
prevents the TLC variable GenerateSampleERTMain
from being set to
TLC_TRUE.
See the rtwgensettings Structure section for information on
creating a SelectCallback
function.
The following code illustrates how to deselect and disable the Generate an example main program option in the context of a
SelectCallback
function.
slConfigUISetVal(hDlg, hSrc, 'GenerateSampleERTMain', 'off'); slConfigUISetEnabled(hDlg, hSrc, 'GenerateSampleERTMain',0); hSrc.refreshDialog;
Note
Creation of a main program for your target environment requires some customization;
for example, in a bareboard environment you need to attach rt_OneStep
to a timer interrupt. It is expected that you will customize either the generated code,
the generating TLC code, or both. See Guidelines for Modifying the Main Program and Guidelines for Modifying rt_OneStep for further information.
You can define custom tokens in a CGT file and
direct generated code into an associated built-in section. This feature gives you additional
control over the formatting of code within each built-in section. For example, you could add
subsections to built-in sections that do not already define subsections. Custom sections
must be associated with one of the built-in sections: Includes
,
Defines
, Types
, Enums
,
Definitions
, Declarations
, or
Functions
. To create custom sections, you must
Add a custom token to the code insertion section of your CGT file.
In your CFP file:
Assemble code to be generated to the custom section into a buffer.
Declare an association between the custom section and a built-in section, with
the code template API function
LibAddSourceFileCustomSection
.
Emit code to the custom section with the code template API function
LibSetSourceFileCustomSection
.
The following code examples illustrate the addition of a custom token,
Myincludes
, to a CGT file, and the subsequent association of the custom
section Myincludes
with the built-in section Includes
in a CFP file.
Note
If you have not already created custom CGT and CFP files for your model, copy the
default template files
and matlabroot
/toolbox/rtw/targets/ecoder/ert_code_template.cgt
to a work folder that is outside the MATLAB folder structure but on the MATLAB or TLC path, rename them (for example, add the prefix
matlabroot
/toolbox/rtw/targets/ecoder/example_file_process.tlctest_
to each file), and update the Templates
pane of the Configuration Parameters dialog box to reference them.
First, add the token Myincludes
to the code insertion section of your
CGT file. For example:
%<Includes> %<Myincludes> %<Defines> %<Types> %<Enums> %<Definitions> %<Declarations> %<Functions>
Next, in the CFP file, add code to generate include
directives into a
buffer. For example, in your copy of the example CFP file, you could insert the following
section between the Includes
section and the Create a simple
main
section:
%% Add a custom section to the model's C file model.c %openfile tmpBuf #include "moretables1.h" #include "moretables2.h" %closefile tmpBuf %<LibAddSourceFileCustomSection(modelC,"Includes","Myincludes")> %<LibSetSourceFileCustomSection(modelC,"Myincludes",tmpBuf)>
The LibAddSourceFileCustomSection
function call declares an
association between the built-in section Includes
and the custom section
Myincludes
. Myincludes
is a subsection of
Includes
. The LibSetSourceFileCustomSection
function
call directs the code in the tmpBuf
buffer to the
Myincludes
section of the generated file.
LibSetSourceFileCustomSection
is syntactically identical to
LibSetSourceFileSection
.
In the generated code, the include directives generated to the custom section appear
after other code directed to Includes
.
#include "rtwdemo_udt.h" #include "rtwdemo_udt_private.h" /* #include "mytables.h" */ #include "moretables1.h" #include "moretables2.h"
Note
The placement of the custom token in this example CGT file is arbitrary. By locating
%<Myincludes>
after %<Includes>
, the
CGT file specifies only that the Myincludes
code appears after
Includes
code.
Custom tokens are automatically translated to TLC syntax as a part of the build process.
To escape a token, that is to prepare it for normal TLC expansion, use the '!' character.
For example, the token %<!TokenName>
is expanded to
%<TokenName>
by the template conversion program. You can specify
valid TLC code, including TLC function calls:
%<!MyTLCFcn()>
.