Configure Generated Code According to Interface Control Document Interactively

This example shows how to configure code generation settings for a model according to specifications in an interface control document (ICD). Store necessary Simulink variables and objects, such as Simulink.Parameter objects, in a data dictionary.

An ICD describes the data interface between two software components. To exchange and share data, the components declare and define global variables that store signal and parameter values. The ICD names the variables and lists characteristics such as data type, physical units, and parameter values. When you create models of the components in Simulink, you can configure the generated code to conform to the interface specification.

In this example, the ICD is a Microsoft® Excel® workbook.

Explore Interface Control Document

Navigate to the folder matlabroot/examples/ecoder (open). Copy this file to a writable, working folder:

  • ex_ICD_PCG_inter.xls

In Microsoft® Excel® or another compatible program, open the ex_ICD_PCG_inter.xls workbook and view the first worksheet, Signals. Each row of the worksheet describes a signal that crosses the interface boundary.

Inspect the cell values in the worksheet. The Owner column indicates the name of the component that allocates memory for each signal. The DataType column indicates the signal data type in memory. For example, the worksheet uses the expression Bus: EngSensors to indicate a structure type named EngSensors.

In the Parameters worksheet, the Value column indicates the value of each parameter. If the value of the parameter is nonscalar, the value is stored in its own separate worksheet, which has the same name as the parameter.

In the Numeric Types worksheet, each row represents a named numeric data type. In this ICD, the data use fixed-point data types (Fixed-Point Designer). The IsAlias column indicates whether the C code uses the name of the data type (for example, s16En3) or uses the name of the primitive integer data type that corresponds to the word length (such as short). The DataScope column indicates whether the generated code exports or imports the definition of the type.

In the Structure Types worksheet, each row represents either a structure type or a field of a structure type. For structure types, the value in the DataType column is struct. Subsequent rows that do not use struct represent fields of the preceding structure type. This ICD defines a structure type, EngSensors, with four fields: throttle, speed, ego, and map.

In the Enumerated Types worksheet, similar to the Structure Types worksheet, each row represents either an enumerated type or an enumeration member. This ICD defines an enumerated type sldemo_FuelModes.

Write External Code

Some data items in the ICD belong to other_component, which is a component that exists outside of MATLAB. Create the code files that define and declare this external data.

Create the header file ex_inter_types.h in your current folder. This file defines the structure type EngSensors and numeric data types such as u8En7.

#ifndef INTER_TYPES_H__
#define INTER_TYPES_H__

typedef short s16En3;

typedef short s16En7;

typedef unsigned char u8En7;

typedef short s16En15;

/* Structure type for instrument measurements. */
typedef struct {
  /* Throttle angle. */
  s16En3 throttle;

  /* Engine speed. */
  s16En3 speed;

  /* EGO sensors. */
  s16En7 ego;

  /* Manifold pressure. */
  u8En7 map;
} EngSensors;

#endif

Create the source file ex_inter_sigs.c in your current folder. This file defines the imported signal sensors.

#include "ex_inter_sigs.h"

EngSensors sensors;                    /* Instrument measurements. */

Create the header file ex_inter_sigs.h in your current folder.

#include "ex_inter_types.h"

extern EngSensors sensors;   /* Instrument measurements. */

Explore Example Model

Run the script prepare_sldemo_fuelsys_dd_inter. For this example, the script prepares a system model, sldemo_fuelsys_dd.

run(fullfile(matlabroot,'examples','ecoder','main','prepare_sldemo_fuelsys_dd_inter'))

Open the system model sldemo_fuelsys_dd.

sldemo_fuelsys_dd

This system model references a controller model. In this example, you generate code from the controller model.

Open the controller model sldemo_fuelsys_dd_controller.

sldemo_fuelsys_dd_controller

Some of the signals in the controller model have names, for example, the input signal sensors. Some block parameters in the model refer to Simulink.Parameter objects in a data dictionary. For example, in the airflow_calc subsystem, the Pumping Constant block uses the parameter objects PumpCon, SpeedVect, and PressVect. These parameter objects set the values of the corresponding block parameters. You can apply code generation settings to the signals and parameter objects.

The controller model is linked to a data dictionary, sldemo_fuelsys_dd_controller.sldd. In the lower-left corner of the model, click the model data badge, then click the Data Dictionary link. In the Model Explorer Model Hierarchy pane, select the Design Data node.

The dictionary already stores:

  • The parameter objects

  • Simulink.NumericType objects such as u8En7

  • A Simulink.Bus object, EngSensors

  • The definition of an enumerated data type, sldemo_FuelModes

Configure Model According to ICD

Navigate to the root level of the controller model then, on the Modeling tab, click Model Data Editor.

In the Model Data Editor, activate the Change scope button. The Model Data Editor now shows information about data items in the subsystems.

Click the Show/refresh additional information button. The Model Data Editor now shows information about data objects (the Simulink.Parameter objects in the data dictionary) that the model uses.

Select the Inports/Outports tab (which is selected by default).

In the model, select the Inport block labeled sensors. The Model Data Editor highlights the corresponding row.

In the ICD, select the Signals tab.

Use the Model Data Editor to configure the signal according to the information in the ICD:

  • Set the value in the Data Type column to Bus: EngSensors. In this case, the value is already set.

  • Set the Change view drop-down list to Code and, for sensors, set Storage Class to ImportFromFile. Use this storage class because the Owner column in the ICD implies that a different component, not sldemo_fuelsys_dd_controller, provides the C-code definition of the sensors variable. With this storage class, the generated code does not define the variable.

  • Set Header File to ex_inter_sigs.h. When you use a storage class that represents imported data, such as ImportFromFile, you cannot specify Definition File in the Model Data Editor. Instead, include the definition file (in this case, ex_inter_sigs.c) in the code generation and build process by using model configuration parameter Source files.

In the model, select the Outport block labeled fuel_rate.

Use the Model Data Editor to configure fuel_rate according to the ICD. To access design properties such as minimum value (Min) and physical unit (Unit), set Change view to Design. For code generation settings, because the ICD specifies sldemo_fuelsys_dd_controller as the owner of the other signals, set Storage Class to ExportToFile.

Inspect the Signals tab.

Set Change view to Code and configure code generation settings for the signal fuel_mode.

You cannot use the Model Data Editor to configure design properties for fuel_mode (such as data type) because fuel_mode is an output of a Stateflow chart. In the model, navigate into the chart.

On the Modeling tab, click Model Explorer.

In the Model Explorer Contents pane (the middle pane), select the fuel_mode data item.

In the Dialog pane (the right pane), configure fuel_mode according to the ICD. In this case, the signal data type is already set, so you can specify only the description.

Navigate to the root level of the model.

In the ICD and the Model Data Editor, select the Parameters tab. In the Model Data Editor, set Change view to Design.

In the Model Data Editor, use the Filter contents box to search for the first parameter, PressEst. The Model Data Editor shows two rows: One row that corresponds to the parameter object PressEst and one row that corresponds to the block parameter that uses PressEst.

Use the Model Data Editor to configure PressEst according to the ICD. The parameter value (the Value column) is already set. Because the ICD specifies sldemo_fuelsys_dd_controller as the owner of PressEst, set Storage Class to ExportToFile.

Use the Model Data Editor to configure the other parameters. Optionally, to apply a change to multiple parameters at once, select multiple rows in the data table.

In the lower-left corner of the model, click the model data badge, then click the Data Dictionary link to open the data dictionary in the Model Explorer.

In the Model Hierarchy pane, select the Design Data node.

In the Contents pane (the middle pane), select the Simulink.NumericType object u8En7. This object represents one of the primitive typedef statements in ex_inter_types.h.

In the ICD, select the Numeric Types tab.

Use the Model Explorer Dialog pane (the right pane) to configure the object according to the ICD.

Use the Model Explorer to configure the other Simulink.NumericType objects. You can use the Contents pane to perform batch operations.

In the Contents pane, click the Simulink.Bus object EngSensors. This object represents the structure type that ex_inter_types.h defines.

In the Dialog pane (the right pane), click Launch Bus Editor.

In the ICD, select the Structure Types tab.

Use the Bus Editor to configure the bus object and the signal elements in the bus (such as throttle) according to the ICD.

In the ICD, select the Enumerated Types tab.

In the Model Explorer Contents pane, click the enumerated type definition sldemo_FuelModes.

Use the Dialog pane to configure the type according to the ICD. Set Storage Type to Native Integer and Data Scope to Exported.

Generate and Inspect Code

Configure the controller model to compile the generated code into an executable program by clearing the model configuration parameter Generate code only.

Generate code from the controller model.

### Starting build procedure for model: sldemo_fuelsys_dd_controller
### Successful completion of build procedure for model: sldemo_fuelsys_dd_controller

The generated header file sldemo_FuelModes.h defines the enumeration sldemo_FuelModes.

typedef enum {
  LOW = 1,                             /* Default value */
  RICH,
  DISABLED
} sldemo_FuelModes;

The file sldemo_fuelsys_dd_controller_types.h includes (#include) the external header file ex_inter_types.h, which defines data types such as u8En7 and the structure type EngSensors.

#include "ex_inter_types.h"

The file sldemo_fuelsys_dd_controller_private.h includes the header file ex_inter_sigs.h. This external header file contains the extern declaration of the signal sensors, which a different software component owns.

The data header file global_data.h declares the exported parameters and signals that the ICD specifies. To share this data, other components can include this header file.

/* Exported data declaration */

/* Declaration for custom storage class: ExportToFile */
extern u8En7 PressEst[855];      /* Referenced by: '<S6>/Pressure Estimation' */
extern s16En15 PumpCon[551];        /* Referenced by: '<S1>/Pumping Constant' */
extern s16En15 RampRateKiZ[25];        /* Referenced by: '<S1>/Ramp Rate Ki' */
extern s16En3 SpeedEst[1305];       /* Referenced by: '<S7>/Speed Estimation' */
extern s16En7 ThrotEst[551];     /* Referenced by: '<S8>/Throttle Estimation' */
extern sldemo_FuelModes fuel_mode;     /* '<Root>/control_logic' */
extern s16En7 fuel_rate;               /* '<Root>/fuel_rate' */

The data definitions (memory allocation) appear in the source files that the ICD specifies: params.c and signals.c. For example, params.c defines and initializes the parameter RampRateKiZ.

s16En15 RampRateKiZ[25] = { 393, 786, 1180, 1573, 1966, 786, 1573, 2359, 3146,
  3932, 1180, 2359, 3539, 4719, 5898, 1573, 3146, 4719, 6291, 7864, 1966, 3932,
  5898, 7864, 9830 } ;                 /* Referenced by: '<S1>/Ramp Rate Ki' */

The algorithm is in the model step function in the file sldemo_fuelsys_dd_controller.c. The algorithm uses the global data that the ICD identifies. For example, the algorithm uses the value of the signal fuel_mode in a switch block to control the flow of execution.

  /* SwitchCase: '<S10>/Switch Case' */
  switch (fuel_mode) {
   case LOW:
    /* Outputs for IfAction SubSystem: '<S10>/low_mode' incorporates:
     *  ActionPort: '<S12>/Action Port'
     */
    /* DiscreteFilter: '<S12>/Discrete Filter' incorporates:
     *  DiscreteIntegrator: '<S1>/Discrete Integrator'
     */
    DiscreteFilter_tmp = (int16_T)(int32_T)((int32_T)((int32_T)((int32_T)
      rtDWork.DiscreteIntegrator_DSTATE << 14) - (int32_T)(-12137 * (int32_T)
      rtDWork.DiscreteFilter_states_g)) >> 14);

Related Topics