C-API for Interfacing with Signals and Parameters

Introduction

Some Real-Time Workshop® applications need to interact with signals or parameters in a model's generated code. For example, calibration applications monitor and modify parameters. Signal monitoring or data logging applications interface with signal data. Using the Real-Time Workshop C-API, you can build target applications that log signals, monitor signals, and tune parameters, while the generated code executes.

The C-API uses a small memory footprint, which is achieved by sharing information common to signals and parameters in smaller structures. An index into the structure map is provided in the signal or parameter structure, allowing multiple signals or parameters to share data.

When you configure a model to use the C-API, the Real-Time Workshop code generator generates two additional files, model_capi.c and model_capi.h, where model is the name of the model. The code generator places the two C-API files in the build directory, based on settings on the Configuration Parameters dialog box. The C-API source code file contains information about global block output signals and global parameters defined in the generated code model source code. The C-API header file is an interface header file between the model source code and the generated C-API. You can use the information in these C-API files to create your application. Among the files generated are those shown in the next figure.

Generated Files with C-API Selected

Generating C-API Files

There are two ways to select the C-API feature: using the Configuration Parameters dialog box or directly from the MATLAB® command line.

Selecting C-API with the Configuration Parameters Dialog Box

  1. In the open model, select Configuration Parameters on the Simulation menu. The Configuration Parameters dialog box appears.

  2. Click Interface under Real-Time Workshop on the left pane. The Interface pane appears on the right.

  3. Select C-API in the Interface field. The Signals in C API and Parameters in C API check boxes appear, as shown in the next figure.

  4. If you want to generate C-API for global block outputs, select the Signals in C API check box. If you want to generate C-API for global block and model parameters, select the Parameters in C API check box. If you select both check boxes, the default, both signals and parameters will appear in the C-API.

  5. Click the Apply button.

  6. Click Real-Time Workshop in the left pane. The Generate code button appears in the right pane.

  7. Click Generate Code.

    C-API Checkboxes on Configuration Parameters Dialog Box

Selecting C-API from the MATLAB® Command Line

From the MATLAB command line you can select or clear the two C-API check boxes on the Configuration Parameters dialog box using the set_param function. Type one or more of the following commands on the MATLAB command line as desired, where modelname is the one-word name of the model:

To select Signals in C API, type

set_param(modelname,'RTWCAPISignals','on')

To clear Signals in C API, type

set_param(modelname,'RTWCAPISignals','off')

To select Parameters in C API, type

set_param(modelname,'RTWCAPIParams','on')

To clear Parameters in C API, type

set_param(modelname,'RTWCAPIParams','off')

Description of C-API Files

The model_capi.c or model_capi.cpp file provides external applications with a consistent interface to the model's data. Depending on your configuration settings, the data could be a signal or parameter. In this discussion, the term "data item" refers to either a signal or a parameter. The C-API uses structures that provide an interface to the data item properties. The interface packages the properties of each data item in a data structure. If there are multiple data items in the model, the interface generates an array of data structures. The members of a data structure map to data properties.

Typically, to interface with data items, an application requires the following properties for each:

As illustrated in the next figure, the properties of data item A, for example, are located in data structure DS_A. The properties of data item B are located in data structure DS_B.

Some property values can be unique to each data item, and there are some that several data items can share in common. Address, for example, has a unique value for each data item. But data type could be a property whose value several data items have in common. The interface places the unique property values directly in the data item's structure. So the address value of data item A is in DS_A.

But the fact that some data items can share a property allows the C-API to have a reuse feature. In this case, the interface places only an index value in DS_A and index value in DS_B. These indices point to a different data structure, DS_C, that contains the actual data type value. The next figure shows this scheme with more detail.

The figure shows three signals. Notice that signal1 and signal2 share the same data type, namely double. Instead of specifying this data type value in each signal data structure, the interface provides only an index value in the structure. "double" is in rtwCAPI_DataTypeMap rtDataTypeMap[]. This reuse of information reduces the memory size of the generated interface. Reuse can also occur between parameters and signals.

Structure Arrays Generated in the C-API File

Like data type, the interface maps other common properties (such as dimension, fixed-point scaling, and sample time) into separate structures and provides an index in the data item's structure. For a complete list of structure definitions, refer to the file matlabroot/rtw/c/src/rtw_capi.h. This file also describes each member in a structure. The structure arrays generated in the model_capi.c or model_capi.cpp file are of structure types defined in the rtw_capi.h file. Here is a brief description of the structure arrays generated in model_capi.c and model_capi.cpp:

Example model_capi.c File

This section discusses the generated C-API structures for the demo model rtwdemo_capi. This model is located in matlabroot/toolbox/rtw/rtwdemos directory.

Open the model by clicking the link above or by typing rtwdemo_capi on the MATLAB command line. The model appears as shown in the next figure.

This model has three global signals, two named and one unnamed: sig1_sg and sig2_eg, and the unnamed signal is the test point at the output of the Gain1 block. There are five parameters: Kp (Gain1 and Gain2 blocks share), Ki (Gain3 block), p1 (lookup table lu1d), p2 (lookup table lu2d), p3 (lookup table lu3d).

C-API Signals

The rtwCAPI_Signals structure captures the signal's description, address, data type information, dimensions information, and sample-time information.

Here is the section of code in rtwdemo_capi_capi.c that provides information on C-API signals:

15 /* Block output signal information */
16 static const rtwCAPI_Signals rtBlockSignals[] = {
17
18   /* addrMapIndex, sysNum, blockPath,
19    * signalLabel, portNumber, dataTypeIndex, dimIndex, 
20    * fxpIndex, sampTimeIndex
21    */
22    {0, 0, "rtwdemo_capi/Gain1",
23     "NULL", 0, 0, 0, 0, 0},
24    {1, 0, "rtwdemo_capi/Gain3",
25     "sig1_sg", 0, 0, 0, 0, 0},
26    {2, 0, "rtwdemo_capi/lu2d",
27     "sig2_eg", 0, 0, 1, 0, 0},
28    {
29     0, 0, NULL, NULL, 0, 0, 0, 0, 0
30    }
31 };

Each array element, except the last, describes one output port for a block signal. The final array element is a sentinel, with all elements set to null values. Take the second signal, described by the code in lines 24 and 25, for example:

24    {1, 0, "rtwdemo_capi/Gain3",
25     "sig1_sg", 0, 0, 0, 0, 0}

This signal, named sig1_sg, is the output signal of the first port of the block rtwdemo_capi/Gain3. (It is the first port because the index for portNumber on line 25 is assigned the value 0.) The address of this signal is given by the addrMapIndex, which, in this example, is 1 on line 24. This gives the index to the rtDataAddrMap array, found later in rtwdemo_capi_capi.c.

The first member value on line 24 is 1. This is the value of addrMapIndex for the signal described on lines 24 to 25. The index of 1 points to the second element in the rtDataAddrMap array. So, from the rtDataAddrMap array, you can infer that the address of this signal is &rtwdemo_capi_B.sig1_sg.

This level of indirection is provided to support multiple code instances of the same model. For multiple instances, the signal information remains constant, except for the address. In this case, the model is a single instance. Therefore, the rtDataAddrMap is declared statically. If you choose to generate reusable code, an initialize function is generated that initializes the addresses dynamically per instance. (For details on generating reusable code, see Configuring Model Interfaces and Model Entry Points in the Real-Time Workshop® Embedded Coder™ documentation.)

The dataTypeIndex provides the index to the rtDataTypeMap array indicating the data type of the signal:

/* Data Type Map - Use dataTypeMapIndex to access this 
 * structure */
static const rtwCAPI_DataTypeMap rtDataTypeMap[] = {
  /* cName, mwName, numElements, elemMapIndex, dataSize,
   * slDataId, isComplex, isPointer */
  {"double", "real_T", 0, 0, sizeof(real_T), SS_DOUBLE, 0, 0}
};

Because this index is 0 for sig1_sg, it points to the first structure element in the array. So you can infer that the signal's data type is double. The value of isComplex is 0, indicating that the signal is not complex. Rather than providing the data type information directly in the rwtCAPI_Signals structure, a level of indirection is introduced. The indirection allows multiple signals that share the same data type to point to one map structure. This saves memory for each signal.

The dimIndex provides the index to the rtDimensionMap array indicating the dimensions of the signal. Because this index is 0 on line 25, it points to the first element in the rtDimensionMap array:

/* dataOrientation, dimArrayIndex, numDims */
{rtwCAPI_SCALAR, 0, 2}

From this structure you can infer that this is a scalar signal having a dimension of 2.

The fixptIndex provides the index to the rtFixPtMap array indicating any fixed-point information about the signal. Your code can use the scaling information provided to compute the real-world value of the signal, using the equation V=SQ+B, where V is "real-world" (that is, base-10) value, S is user-specified slope, Q is "quantized fixed-point value" or "stored integer," and B is user-specified bias. (For details, see Scaling in the Fixed-Point Toolbox™ documentation.)

Because this index is 0 on line 25, the signal has no fixed-point information. A fixed-point map index of zero always means that the signal has no fixed-point information.

The sampTimeIndex provides the index to the rtSampleTimeMap array indicating task information about the signal. The sampling information can be useful if you log multirate signals or conditionally executed signals.

model_capi.c and model_capi.cpp include rtw_capi.h. Any source file that references the rtBlockSignals array also should include rtw_capi.h.

C-API Parameters

The rtCAPI_ModelParameter structure captures the parameter's description, address, data type information, and dimensions information. Each element in the rtModelParameters array corresponds to a tunable parameter in the model. The code below is an example of elements in this array:

49  /* Tunable variable parameters */
50
51  static const rtwCAPI_ModelParameters rtModelParameters[] = {
52
53  /* addrMapIndex, varName, dataTypeIndex, dimIndex, 
54   * fixPtIndex */
55
56  {3, "Ki", 0, 0, 0},
57  {4, "Kp", 0, 0, 0},
58  {5, "p1", 0, 2, 0},
59  {6, "p2", 0, 3, 0},
60  {7, "p3", 0, 4, 0},
61  {0, NULL, 0, 0, 0 }
62 };

Notice line 58, for example. The varName (variable name) of the line 58 parameter is p2. The address of this parameter is given by the addrMapIndex which, in this example, is 6. This is the index to the rtDataAddrMap array, found later in model_capi.c or model_capi.cpp. Because the index is zero based, 6 corresponds to the seventh element in rtDataAddrMap, &(p2). The dataTypeIndex is 0, which corresponds to a double and noncomplex parameter. The dimIndex (dimension index) is 3. So it points to the fourth element in the rtDimensionMap array. Later in the generated C-API file, this fourth element appears as

{rtwCAPI_Matrix_COL_MAJOR, 6, 2}

As mentioned in Structure Arrays Generated in the C-API File, rtBlockParameters is an array of structures of type struct rtwCAPI_Parameters. In the example, all the members of the structure rtwCAPI_BlockParameters are assigned NULL and zero values. This is because the Inline parameters check box on the Optimization pane of the Configuration Parameters dialog box is selected. If you clear this check box, the block parameters are generated in the rtwCAPI_BlockParameters structure.

In this manner, the Inline parameters check box affects the information generated in the rtBlockParameters and rtModelParameters arrays.

If Inline parameters is cleared,

If Inline parameters is selected,

Mapping C-API Data Structures to Real-Time Model

The real-time model data structure encapsulates model data and associated information necessary to describe the model fully. For details, see The Real-Time Model Data Structure. When you select the C-API feature and generate code, the Real-Time Workshop code generator adds another member to the real-time model data structure:

struct {
rtwCAPI_ModelMappingInfo mmi;
} DataMapInfo;

This member defines mmi (for model mapping information) of type struct rtwCAPI_ModelMappingInfo. The structure is provided in matlabroot/rtw/c/src/rtw_modelmap.h. The mmi substructure defines the interface between the model and the C-API files. More specifically, members of mmi map the real-time model data structure to the structures in the model_capi.c.

Initializing values of mmi members to the arrays accomplishes the mapping. See the next figure. Each member points to one of the arrays of structures in the generated C-API file. For example, the address of the rtBlockSignals array of structures is allocated to the first member of the mmi substructure in model.c, using the following code in the rtwmodelmap.h file:

/* signals */
 struct {
 rtwCAPI_Signals const *signals; /* Signals Array */
 uint_T numSignals; /* Num Signals */
} Signals;

The model initialize function in model.c or model.cpp performs the initializing during model initialization. It does so by calling the C-API initialize function:

rtwdemo_capi_InitializeDataMapInfo(rtwdemo_capi_M).

Mapping Between Model and C-API Arrays of Structures

Using the C-API in an Application

The C-API provides you with the flexibility of writing your own application code to interact with model parameters and signals. Your target-based application code is compiled with the Real-Time Workshop generated code into an executable. The target-based application code accesses the C-API structure arrays in model_capi.c or model_capi.cpp. You might have host-based code that interacts with your target-based application code. Or you might have other target-based code that interacts with your target-based application code. The rtw_modelmap.h file provides macros for accessing the structures in these arrays and their members.

This section provides the following examples to help you get started writing application code to interact with model parameters and signals:

Example: Using the C-API to Access Model Parameters

An example application is provided below that prints the parameter values of all tunable parameters in a model to the standard output. This code is intended as a starting point for accessing parameter addresses. You can extend the code to perform parameter tuning. The application

The example application code is provided below:

{
/* Get CAPI Mapping structure from Real-Time Model structure */
rtwCAPI_ModelMappingInfo* capiMap = \ 
&(rtmGetDataMapInfo(rtwdemo_capi_M).mmi);

/* Get number of Model Parameters from capiMap */
uint_T nModelParams = rtwCAPI_GetNumModelParameters(capiMap);
printf("Number of Model Parameters: %d\n", nModelParams);

/* If the model has Model Parameters, print them using the 
application capi_PrintModelParameter */
if (nModelParams == 0) {
   printf("No Tunable Model Parameters in the model \n");
}
else {
   unsigned int idx;
   
   for (idx=0; idx < nModelParams; idx++) {
      /* call print utility function */
      capi_PrintModelParameter(capiMap, idx);
   }
}
}

The print utility function is provided in matlabroot/rtw/c/src/rtw_capi_examples.c. This file contains utility functions for accessing the C-API structures.

To become familiar with the example code, try building a model that displays all the tunable block parameters and MATLAB variables. You can use rtwdemo_capi.mdl, the C-API demo model, for this purpose. The steps below apply to both grt.tlc and ert.tlc targets, unless otherwise indicated:

  1. Open the model rtwdemo_capi.mdl by typing rtwdemo_capi at the MATLAB command line.

  2. Open the Configuration Parameters dialog box and go to the Optimization pane.

  3. Verify that the Inline parameters option is selected.

  4. If you want to use the ert.tlc target instead of the default grt.tlc, select an ert.tlc target in the System target file field on the Real-Time Workshop pane and click OK.

  5. Use the Custom Code pane to embed your custom application code in the generated code: Select the Custom Code pane, and then click Initialize function. The Initialize function input field appears on the right.

  6. In the Initialize function input field, type or copy the example application code provided above. This embeds the application code in the MdlStart function. (If you are using ert.tlc, the code appears in the model_initialize function.)

  7. Click Include directories, and type matlabroot/rtw/c/src, where matlabroot is the directory where your MATLAB installation resides on your system.

  8. In the Include list of additional subpane, click Source files, and type rtw_capi_examples.c, as shown in the figure below. Click the Apply button.

  9. If you are using the ert.tlc target, select the following options on the Real-Time Workshop > Interface pane, and then click Apply:

  10. Go to the Real-Time Workshop pane and clear the Generate code only check box if it is not already cleared.

  11. Click the Build button. The Real-Time Workshop code generator generates the executable file rtwdemo_capi.exe in your current working directory.

  12. Type !rtwdemo_capi at the MATLAB command line to run the executable file. Parameter information is displayed in the Command Window, as shown below.

    >> !rtwdemo_capi
     
    ** starting the model ** 
    Number of Model Parameters: 5 
    Ki =  
    	7 
    Kp =  
    	4 
    p1 =  
    	0.8147 
    	0.9058 
    	0.127 
    p2 =  
    	0.9649	0.9706	0.4854 
    	0.1576	0.9572	0.8003 
    p3 =  
    ans(:,:,1) = 
    	0.1419	0.9157	0.9595	0.03571 
    	0.4218	0.7922	0.6557	0.8491 
     
    ans(:,:,2) = 
    	0.934	0.7577	0.3922	0.1712 
    	0.6787	0.7431	0.6555	0.706 
     
    >> 

Example: Using the C-API to Access Model Signals

An example application is provided below that logs a model's global signals to a text file. This code is intended as a starting point for accessing signal addresses. You can extend the code to perform signal logging and monitoring.

This example uses the following macro and function interfaces:

The following excerpts of generated code from model.c (rearranged to reflect their order of execution) show how the function interfaces are used.

void MdlStart(void)
{
...
  /* user code (Start function Trailer) */

  /* C API Custom Logging Function: Start Block IO Signal logging via C-API.
   * capi_StartBlockIOLogging: Function prototype in capi_BIOSignalLog.h
   */
  {
    rtwCAPI_ModelMappingInfo *MMI = &(example_capi_M->DataMapInfo.mmi);
    capi_StartBlockIOLogging(MMI, MAX_DATA_POINTS);
    printf("** Started BIO logging via C-API **\n\n");
  }
...
}
...
/* Model output function */
static void example_capi_output(int_T tid)
{
...
  /* user code (Output function Trailer) */
  /* C API Custom Logging Function: Update Block IO Signal logging buffer.
   * capi_UpdateBlockIOLogging: Function prototype in capi_BIOSignalLog.h
   */
  {
    rtwCAPI_ModelMappingInfo *MMI = &(example_capi_M->DataMapInfo.mmi);
    capi_UpdateBlockIOLogging(MMI, rtmGetTPtr(example_capi_M));
  }
...
}
...
/* Model terminate function */
void example_capi_terminate(void)
{
  /* user code (Terminate function Trailer) */
  /* C API Custom Logging Function: Dump Block IO Signal buffers into a text file.
   * capi_StopBlockIOLogging: Function prototype in capi_BIOSignalLog.h
   */
  {
    capi_StopBlockIOLogging("example_capi_BlockIOLog.txt");
    printf("** Finished BIO logging. Created example_capi_BlockIOLog.txt **\n");
  }
}

The following procedure illustrates how you can use the C-API macro and function interfaces to log a model's global signals to a text file.

  1. Download the files listed below from the MathWorks Web site by clicking each filename. Copy the files to a working directory.

  2. Open the model example_capi.mdl.

  3. Open the Configuration Parameters dialog box and go to the Real-Time Workshop pane.

  4. For the System target file parameter, select grt.tlc. (Alternatively, if you are licensed for Real-Time Workshop Embedded Coder software, you can select ert.tlc.)

  5. Examine the TLC options parameter. If the field does not already contain the string -acapiSigTestFile="capitestsigfile.tlc", edit the field to include it. Including the string causes the example's custom application C code to be integrated with the code you generate from the model.

  6. Go to the Interface pane.

    1. In the Data exchange subpane, for the Interface parameter, select C-API.

    2. Additionally, select the option Signals in C API and clear the option Parameters in C API. For the purposes of this example, you can limit the C-API data exchange to signals only.

    3. If you are using the ert.tlc target, verify that the options MAT-file logging and Support: complex numbers are selected.

    4. Click the Apply button.

  7. In the Real-Time Workshop pane, verify that the Build button is visible. If necessary, clear the option Generate code only and click the Apply button.

    Also, make sure that the C, H, and TLC files that you downloaded for this example are on the MATLAB path (for example, in the current working directory).

    Click the Build button to build the model and generate the executable file example_capi.exe.

  8. To run the executable file, enter the command !example_capi in the MATLAB command window. During execution, model block I/O signals are logged using the C-API and then written to the text file example_capi_BlockIOLog.txt in your working directory.

    >> !example_capi
     
    ** starting the model ** 
    ** Started BIO logging via C-API ** 
     
    ** Finished BIO logging. Created example_capi_BlockIOLog.txt ** 
    >> 
  9. Examine the text file in the MATLAB editor or any text editor. An excerpt of the signal logging output is shown below.

    ******** Signal Log File******** 
    
    Number of Signals Logged: 3
    Number of points (time steps) logged: 51
    
    Time           sig1_tp                  sig2_fixedPt             sig3_complex  
    0              0                        6.5                      50    + 50   i
    0.2            0.7947                   3                        50    + 50   i
    0.4            1.558                    8.5                      50    + 50   i
    0.6            2.259                    4                        50    + 50   i
    0.8            2.869                    2                        50    + 50   i
    1              3.366                    6.5                      50    + 50   i
    1.2            3.728                    3                        50    + 50   i
    1.4            3.942                    8.5                      50    + 50   i
    1.6            3.998                    4                        50    + 50   i
    1.8            3.895                    2                        50    + 50   i
    2              3.637                    6.5                      50    + 50   i
    ...

C-API Limitations

The C-API feature has the following limitations.

Generating C-API and ASAP2 Files

The C-API and ASAP2 interfaces are not mutually exclusive. Although the Interface option on the Real-Time Workshop > Interface pane of the Configuration Parameters dialog box allows you to select either the ASAP2 or C-API interface, you can instruct the Real-Time Workshop code generator to generate files for both interfaces. For details, see Generating ASAP2 and C-API Files.

Target Language Compiler API for Signals and Parameters

The Real-Time Workshop product provides a TLC function library that lets you create a global data map record. The global data map record, when generated, is added to the CompiledModel structure in the model.rtw file. The global data map record is a database containing all information required for accessing memory in the generated code, including

Use of the global data map requires knowledge of the Target Language Compiler and of the structure of the model.rtw file. See the Target Language Compiler documentation for information on these topics.

The TLC functions that are required to generate and access the global data map record are contained in matlabroot/rtw/c/tlc/mw/globalmaplib.tlc. The comments in the source code fully document the global data map structures and the library functions.

The global data map structures and functions might be modified or enhanced in future releases.

  


 © 1984-2008- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS