Main Content

Integrate External C Functions That Pass Input and Output Arguments as Parameters with a Fixed-Point Data Type

Integrate legacy C functions that pass their inputs and outputs by using parameters of a fixed-point data type with the Legacy Code Tool.

With the Legacy Code Tool, you can:

  • Provide the legacy function specification.

  • Generate a C-MEX S-function that calls the legacy code during simulation.

  • Compile and build the generated S-function for simulation.

  • Generate a TLC block file and optional rtwmakecfg.m file that specifies how the generated code for a model calls the legacy code.

Provide the Legacy Function Specification

Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code() using initialize as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:

myFixpt timesS16(const myFixpt in1, const myFixpt in2, const uint8_T fracLength)

myFixpt is logically a fixed point data type, which is physically a typedef to a 16-bit integer:

myFixpt = Simulink.NumericType;
myFixpt.DataTypeMode = 'Fixed-point: binary point scaling';
myFixpt.Signed = true;
myFixpt.WordLength = 16;
myFixpt.FractionLength = 10;
myFixpt.IsAlias = true;
myFixpt.HeaderFile = 'timesFixpt.h';

The legacy source code is in the files timesFixpt.h, and timesS16.c.

% sfun_gain_fixpt
def = legacy_code('initialize');
def.SFunctionName = 'sfun_gain_fixpt';
def.OutputFcnSpec = 'myFixpt y1 = timesS16(myFixpt u1, myFixpt p1, uint8 p2)';
def.HeaderFiles   = {'timesFixpt.h'};
def.SourceFiles   = {'timesS16.c'};
def.IncPaths      = {'Lct_src'};
def.SrcPaths      = {'Lct_src'};

Generate an S-Function for Simulation

To generate a C-MEX S-function according to the description provided by the input argument def, call the function legacy_code() again with the first input set to sfcn_cmex_generate. The S-function calls the legacy functions during simulation. The source code for the S-function is in the file sfun_gain_fixpt.c.

legacy_code('sfcn_cmex_generate', def);

Compile the Generated S-Function for Simulation

After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code() again with the first input set to compile.

legacy_code('compile', def);
### Start Compiling sfun_gain_fixpt
    mex('-I/tmp/Bdoc24a_2528353_1319773/tpa05a9724/simulinkcoder-ex05928773/Lct_src', '-I/tmp/Bdoc24a_2528353_1319773/tpa05a9724/simulinkcoder-ex05928773', '-c', '-outdir', '/tmp/Bdoc24a_2528353_1319773/tp1c97463f_1e62_44ef_9a7d_1a256e3714da', '/tmp/Bdoc24a_2528353_1319773/tpa05a9724/simulinkcoder-ex05928773/Lct_src/timesS16.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sfun_gain_fixpt.c', '-I/tmp/Bdoc24a_2528353_1319773/tpa05a9724/simulinkcoder-ex05928773/Lct_src', '-I/tmp/Bdoc24a_2528353_1319773/tpa05a9724/simulinkcoder-ex05928773', '/tmp/Bdoc24a_2528353_1319773/tp1c97463f_1e62_44ef_9a7d_1a256e3714da/timesS16.o')
Building with 'gcc'.
MEX completed successfully.
### Finish Compiling sfun_gain_fixpt
### Exit

Generate a TLC Block File for Code Generation

After you compile the S-function and use it in simulation, you can call the function legacy_code() again. Set the first input to sfcn_tlc_generate to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails. The TLC block file for the S-function is sfun_gain_fixpt.tlc.

legacy_code('sfcn_tlc_generate', def);

Generate an rtwmakecfg.m File for Code Generation

After you create the TLC block file, you can call the function legacy_code() again. Set the first input to rtwmakecfg_generate to generate an rtwmakecfg.m file that supports code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m file.

legacy_code('rtwmakecfg_generate', def);

Generate a Masked S-Function Block for Calling the Generated S-Function

After you compile the C-MEX S-function source, you can call the function legacy_code() again. Set the first input to slblock_generate to generate a masked S-function block that calls that S-function. The software places the block in a new model. You can copy the block to an existing model.

legacy_code('slblock_generate', def);

Show the Generated Integration with Legacy Code

The model LctFixedParams shows integration of the model with the legacy code. The subsystem TestFixpt serves as a harness for the call to the legacy C function via the generated S-function.

open_system('LctFixedParams')
open_system('LctFixedParams/TestFixpt')
sim('LctFixedParams')

See Also

Related Topics