Configure Generated Code According to Interface Control Document

Import specifications from an interface control document (ICD), configure code generation settings for a model according to the specifications, and store the settings in data dictionaries.

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.xls

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

  • ex_importICD_PCG.m

In Microsoft® Excel® or another compatible program, open the ex_ICD_PCG.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 represent 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, u8En7) or uses the name of the primitive integer data type that corresponds to the word length. 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 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. */

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

Explore Example Model

Run the script prepare_sldemo_fuelsys_dd. The script prepares a system model, sldemo_fuelsys_dd, for this example.

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

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

Data items in the controller model refer to Simulink.Signal and Simulink.Parameter objects in the base workspace. For example, the input signal sensors refers to a Simulink.Signal object that has the same name. These objects store settings such as data types, block parameter values, and physical units. The names of these data items and objects match the names of the signals and parameters in the ICD.

Import ICD Specifications into Simulink

To configure code generation settings for the data items, import the settings from the ICD.

Open the example script ex_importICD_PCG. The script imports the data from each worksheet of the ICD into variables in the base workspace. It then configures the properties of the Simulink.Signal and Simulink.Parameter objects in the base workspace by using the imported data.

edit('ex_importICD_PCG')

If the base workspace already contains a data object that corresponds to a target data item in the ICD, the script configures the properties of the existing object. If the object does not exist, the script creates the object.

Run the ex_importICD_PCG script.

run('ex_importICD_PCG')

The script configures the data objects in the base workspace for code generation according to the specifications in the ICD. The Simulink.Bus object EngSensors represents the structure type from the ICD. The Simulink.NumericType objects, such as u8En7, represent the fixed-point data types.

Generate and Inspect Code

Configure the controller model to compile the generated code into an executable 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' */

/* Lookup table to estimate pressure on sensor failure. */
extern s16En15 PumpCon[551];        /* Referenced by: '<S1>/Pumping Constant' */

/* Lookup table to determine pumping constant based on measured engine speed and manifold pressure. */
extern s16En15 RampRateKiZ[25];        /* Referenced by: '<S1>/Ramp Rate Ki' */

/* Lookup table to determine throttle rate. */
extern s16En3 SpeedEst[1305];       /* Referenced by: '<S7>/Speed Estimation' */

/* Lookup table to estimate engine speed on sensor failure. */
extern s16En7 ThrotEst[551];     /* Referenced by: '<S8>/Throttle Estimation' */

/* Lookup table to estimate throttle angle on sensor failure. */
extern sldemo_FuelModes fuel_mode;     /* '<Root>/control_logic' */

/* Fueling mode of engine. Enrich air/fuel mixture on sensor failure. */
extern int16_T fuel_rate;              /* '<S10>/Merge' */

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' incorporates:
   *  Constant: '<S11>/shutoff'
   */
  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);

Change Ownership of Data in ICD

When you make changes to the ICD, you can reuse the ex_importICD_PCG script to reconfigure the model. Change the ownership of the signal sensors, the structure type, and the fixed-point data types from other_component to sldemo_fuelsys_dd_controller.

In the ICD, on the signals worksheet, for the signal sensors, set these cell values:

  • Owner to sldemo_fuelsys_dd_controller

  • HeaderFile to global_data.h

  • DefinitionFile to signals.c

On the Numeric Types worksheet, for the fixed-point data types, set:

  • DataScope to Exported

  • HeaderFile to exported_types.h.

On the Structure Types worksheet, for the structure type EngSensors, set:

  • DataScope to Exported

  • HeaderFile to exported_types.h.

Rerun the ex_importICD_PCG script.

Generate code from the model.

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

The generated file exported_types.h defines the structure type EngSensors and the fixed-point data types.

typedef int16_T s16En3;
typedef int16_T s16En7;
typedef uint8_T u8En7;

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

  /* Engine speed. */
  s16En3 speed;

  /* EGO sensors. */
  s16En7 ego;

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

typedef int16_T s16En15;

The file signals.c now includes the definition of the signal sensors.

/* Exported data definition */

/* Definition for custom storage class: ExportToFile */
sldemo_FuelModes fuel_mode;            /* '<Root>/control_logic' */

/* Fueling mode of engine. Enrich air/fuel mixture on sensor failure. */
int16_T fuel_rate;                     /* '<S10>/Merge' */

/* Fuel rate setpoint. */
EngSensors sensors;                    /* '<Root>/sensors' */

Migrate Base Workspace Data to Data Dictionary

Objects and variables that you create in the base workspace (for example, Simulink.Parameter objects) are not saved with the model. When you end your MATLAB session, the objects and variables do not persist. To permanently store the objects and variables, link one or more models to one or more data dictionaries.

Data dictionaries also enable you to track changes made to the objects and variables, which helps you to:

  • Reconcile the data stored in MATLAB with the data stored in the ICD.

  • Export data from MATLAB to the ICD.

  1. In the top model, sldemo_fuelsys_dd, on the Modeling tab, under Design, click Link to Data Dictionary.

  2. In the Model Properties dialog box, click New.

  3. In the Create a new Data Dictionary dialog box, set File name to sysDict and click Save.

  4. Click Migrate data.

  5. Click Change all models in response to the message about using the dictionary for referenced models.

  6. Click Migrate in response to the message about copying referenced variables.

The variables and objects that the models use exist in the new data dictionary sysDict.sldd, which is in your current folder. The three models in the model reference hierarchy are linked to this dictionary.

Store Enumerated Type Definition in Data Dictionary

You can import the definition of the enumerated type sldemo_FuelModes into the controller dictionary. See Enumerations in Data Dictionary.

Store Signal and State Design Attributes Inside or Outside of Model File

In this example, you use Simulink.Signal objects to specify design attributes such as data types, minimum and maximum values, and physical units. The signal objects store these specifications outside of the model file.

Alternatively, you can store these specifications in the model file by using block and port parameters, which you can access through the Model Data Editor, the Property Inspector, and other dialog boxes.

To decide where to store the specifications, see Store Design Attributes of Signals and States.

Related Topics