Contenuto principale

Programmatically Customize Arguments of Step C Function Generated from Single Tasking Model

Entry-point functions are functions in the generated model code that interface with your external code. A step function is an entry-point function that contains the execution code for each step in a Simulink® model task. The return value and input arguments of the generated function represent the root-level inports and outports that are used by that task, and the function body corresponds to the task logic.

The examples Programmatically Customize Generated Entry-Point C Function Arguments for Component Models and Customize Generated Entry-Point C Function Arguments for Subcomponent Models show how to customize the identifiers of entry-point function arguments and how to customize the way root-level inports and outports are passed to the generated entry-point functions.

When your model is configured as single-tasking, you can override these customizations for the generated step function. In these settings, you can directly customize the arguments of the step function:

  • You can specify the order of the arguments in the generated function prototype.

  • You can specify the identifier for each of the arguments.

  • You can customize the function to use combined arguments, corresponding each to one root-level inport and one root-level outport of the model.

This example shows how to configure your model to apply these customizations.

Note:

  • Applying these customizations does not affect other generated entry-point functions.

  • The customizations demonstrated in this example apply to both models configured for component deployment type, and models configured for subcomponent deployment type.

Limitations: To apply the customization options demonstrated in this example:

  • Your model must be configured as single-tasking.

  • The storage class of all root-level inports and outports of the model must be specified as Auto, or as Model default with the default storage class of the execution category specified as Default.

  • If your model is configured for component deployment type, it must be configured as nonreusable, or as reusable with the root-level ports passed as individual arguments.

  • If your model is configured for subcomponent deployment type, it must be configured as reusable, or as nonreusable with the root-level ports passed as individual arguments.

Load Model

Load the model EntryPoints.

epModel = 'EntryPoints';
load_system(epModel)

EntryPoints is a nonreusable, single-rate single tasking model, configured to use the ERT system target file.

Prepare to Customize Step Function Arguments

To customize the generated step function arguments programmatically, you use the code mappings object of the model. Get a handle to the object and store it in the variable codeMapObj.

codeMapObj = coder.mapping.api.get(epModel);

Store the code mappings identifier for the step function in the variable stepFuncID.

stepFuncID = "Periodic:D1";

Use the function setFunction with the code mappings object and the identifier to specify the name for the generated step function as custArgsStepFcn.

setFunction(codeMapObj,stepFuncID,FunctionName="custArgsStepFcn")

Customize Function Arguments

The generated step function uses its return value and input arguments to represent the model root-level inports and outports. You can,

  • Optionally designate one of the root-level outports to become the return value of the generated step function. Each of the remaining root-level outports corresponds to one pointer input argument.

  • Specify the type qualifier of each argument that corresponds to a root-level inport to indicate how you want the argument to be passed to the step function.

  • Customize argument order.

  • Customize argument identifiers.

To customize the arguments, use the function setFunction this way:

setFunction(codeMapObj,stepFuncID,Arguments=arg_spec)

Here, codeMapObj is the code mappings object of the model, stepFuncID is the identifier of the step function as defined in the code mappings of the model, and arg_spec is a variable with the expression that specifies how root-level inports and outports of the model are represented and arranged in the generated step function.

The generic structure of the argument specifications expression is "return_value_outport = (arg1, arg2, ... , argN)".

The part before the parenthesis is optional. Include it to designate the root-level outport return_value_outport as the return value of the generated function. The rest of the root-level outports become pointer input arguments in the generated function. If you do not designate a root-level outport as the return value, all root-level outports become pointer input arguments.

Each of the root-level inports and outports, except for the outport designated as the return value of the generated function (if there is one), corresponds to one element in the comma separated list arg1, arg2, ... , argN. The element includes the name of the root-level inport or outport, and in some cases, additional specifications:

● An element that corresponds to a root-level outport must be preceded by an asterisk (*) to indicate that the generated argument is a pointer.

● An element that corresponds to a root-level inport can be preceded by one of these prefixes to indicate how you want the generated argument to be passed to the function.

  • const* const — pass as a constant pointer to constant.

  • const* — pass as a pointer to constant.

  • asterisk (*) — pass as a pointer.

  • const — pass as a constant value.

  • no prefix — pass by value.

For complex variables, such as arrays, the code generator cannot honor the last two options (pass as a constant value or pass by value). In such cases, the argument is generated as a pointer to constant or as a pointer, respectively.

● When using the programmatic interface, the default identifier of each generated argument is the name of the corresponding root-level port. Optionally, you can specify a custom identifier for the argument by adding a space to the element followed by the custom identifier. The custom identifier must contain valid C language characters.

● The order of the arguments in the generated function is the order of the elements in the comma separated list arg1, arg2, ... , argN.

Store these argument specifications in the variable arg_spec:

arg_spec = "data_out2 = (*data_out1 outArg1, const data_in2 inArg2, const* data_in1)";

Here is a breakdown of the specifications used to customize the arguments of the generated function:

  • There is no custom identifier for the third argument, so the generated identifier is the name of the root-level outport itself, data_in1.

Use the function setFunction with arg_spec to apply the argument specifications:

setFunction(codeMapObj,stepFuncID,Arguments=arg_spec);

Use the slbuild function to generate code from the model. Use the evalc function to suppress the output of the slbuild function.

evalc("slbuild(epModel)");

Store the path to the generated source file in the variable srcFile, then use the function coder.example.extractLines to see the generated step function in the generated source code file.

srcFile = "EntryPoints_ert_rtw/EntryPoints.c";
coder.example.extractLines(srcFile,"StepFcn(","}",true,true);
real_T custArgsStepFcn(real_T *outArg1, const real_T inArg2, const real_T
  *data_in1)
{
  /* specified return value */
  real_T data_out2;

  /* Gain: '<Root>/Gain1' incorporates:
   *  Inport: '<Root>/data_in1'
   *  Inport: '<Root>/data_in2'
   *  Sum: '<Root>/Add'
   */
  *outArg1 = (*data_in1 + inArg2) * 23.11;

  /* Outport: '<Root>/data_out2' incorporates:
   *  Gain: '<Root>/Gain2'
   */
  data_out2 = 1946.0 * *outArg1;
  return data_out2;
}

In the generated code:

  • The argument order, type qualifiers, and identifiers adhere to your specifications.

  • The return value is kept, during the running of the function, in the temporary variable data_out2, which corresponds to root-level outport data_out2 that you designated to be the return value of the generated function.

Use Combined Inports and Outports

You can customize the generated function to have combined arguments, corresponding each to one root-level inport and one root-level outport. A combined argument is passed by pointer and is used in the generated function for both input and output. To use combined arguments, specify the same custom identifier for the two arguments you want to combine. In the argument specifications, both the inport and the outport of the shared argument must be preceded by an asterisk (*) to indicate that the shared argument is passed by pointer.

In the example, update arg_spec such that:

  • the generated function has no return value (it is a void function).

  • data_in1 and data_out1 are combined into the shared argument sharedArg1.

  • data_in2 and data_out2 are combined into the shared argument sharedArg2.

  • sharedArg2 is the first input argument of the generated function, and sharedArg1 is the second input argument of the generated function.

arg_spec="(*data_in2 sharedArg2, *data_out2 sharedArg2, *data_in1 sharedArg1, *data_out1 sharedArg1)";

In a single function call to setFunction, update the name of the generated function to sharedArgsStepFcn, and use arg_spec to update its argument specifications.

setFunction(codeMapObj,stepFuncID,FunctionName="sharedArgsStepFcn",Arguments=arg_spec)

Generate model code again, and use the function coder.example.extractLines to examine the generated step function.

evalc("slbuild(epModel)");
coder.example.extractLines(srcFile,"StepFcn(","}",true,true);
void sharedArgsStepFcn(real_T *sharedArg2, real_T *sharedArg1)
{
  /* Gain: '<Root>/Gain1' incorporates:
   *  Sum: '<Root>/Add'
   */
  *sharedArg1 = (*sharedArg1 + *sharedArg2) * 23.11;

  /* Outport: '<Root>/data_out2' incorporates:
   *  Gain: '<Root>/Gain2'
   */
  *sharedArg2 = 1946.0 * *sharedArg1;
}

In the code, each of the combined arguments is used for both input and output. The value of each argument is used in the calculations, and is being updated.

See Also

| | |

Topics