Generate C Measurement Service Interface Code for Component Deployment
This example shows how to generate component code that includes interface support for measuring signal, state, and datastore data. The generated interface code must align with target environment interface requirements.
The example shows how to:
Represent a measurable signal, state, and datastore data in the top model.
Configure the code generator to apply a code interface.
Generate and inspect the interface code.
Represent Measurement Data in Top Model
Open example component model ComponentDeploymentFcn
.
open_system('ComponentDeploymentFcn');
The integrator and accumulator functions operate on state variables that you want to measure.
Open the function-call subsystems Integrator
and Accumulator
.
The integrator function uses a state variable to represent the discrete time integrator. The accumulator function uses a state variable to represent the delay. The target environment expects the names of the corresponding variables in the generated code to be CD_measured.dti
and CD_measured.delay
.
Configure Measurement Code Interface
The example model is linked to the shared Embedded Coder Dictionary file ComponentDeploymentCoderDictionary.sldd
, which defines a service code interface configuration. That configuration defines a measurement service interface named MeasurementService
. That service is configured to apply storage class SignalStruct
. That storage class is defined with these property settings:
Access is set to
Direct
.Data Scope is set to
Exported
.Header File is set to
$N.h
, where$N
is the model name.Definition File is set to
$N.c
, where$N
is the model name.Use different property settings for single-instance and multi-instance data is cleared.
Storage Type is set to
Structured.
Type Name is set to naming rule
CD_measured_T$M
.Instance Name is set to naming rule
CD_measured
.Data Initialization is set to Dynamic.
Memory Section is set to
None
.Preserve array dimensions is cleared.
No qualifiers are specified.
Configure the model such that the code generator applies the coder dictionary default interface for measured data elements.
Open the Embedded Coder app.
Select Code Interface > Component Interface.
In the Code Mappings editor, click the Signals/States tab.
Expand the States node and select the row for
Discrete-Time Integrator
.From the menu in the Measurement Service column of the selected row, select
Dictionary default: MeasurementService
.In the selected row, click the pencil icon.
In the dialog box that appears, set the Identifier property to
dti
. Alternatively, you can set the property in the Property Inspector.Select the row for
Unit Delay
.Repeat steps six and seven to set the Identifier property for the state to
delay
.Save configuration changes by saving the model.
Generate and Inspect Interface Code
Generate code from the example model. The code generator creates the folder ComponentDeploymentFcn_ert_rtw
in the current working folder and places source code files in that folder. The generated code is in two primary files: header file ComponentDeploymentFcn.h
and source code file ComponentDeploymentFcn.c
. Model data and entry-point functions are accessible to a caller by including the header file in the target environment software.
To inspect the generated code, use the code generation report or, in the Embedded Coder app, use the Code view.
Header File
The header file ComponentDeploymentFcn.h
includes interface header file services.h
, defines an instance of the real-time model data structure, and declares structures and callable entry-point functions for data and function interface elements represented in the model.
This code fragment shows code in the header file that is relevant to measureable data.
typedef struct { real_T delay[10]; real_T dti[10]; } CD_measured_T; . . . extern void CD_accumulator(void); extern void CD_integrator(void); extern CD_measured_T CD_measured;
Source Code File
This code fragment in generated source code file ComponentDeploymentFcn.c
shows code relevant to the parameter tuning service interface.
CD_measured_T CD_measured; . . . void CD_accumulator(void) { const real_T *tmpIrvIRead; int32_T i; tmpIrvIRead = get_CD_accumulator_DataTransfer(); for (i = 0; i < 10; i++) { CD_measured.delay[i] += tmpIrvIRead[i]; (getref_CD_accumulator_OutBus_y())[i] = CD_tunable.k * CD_measured.delay[i]; } } void CD_integrator(void) { real_T tmp; real_T *tmp_0; int32_T i; . . . tmp = 1.25 * (real_T)Integrator_ELAPS_T; for (i = 0; i < 10; i++) { if ((int32_T)rtDWork.DiscreteTimeIntegrator_SYSTEM_E == 0) } CD_measured.dti[i] += tmp * rtDWork.DiscreteTimeIntegrator_PREV_U[i]; } rtDWork.DiscreteTimeIntegrator_PREV_U[i] = get_CD_integrator_InBus_u())[i]; } rtDWork.DiscreteTimeIntegrator_SYSTEM_E = 0U; memcpy(&tmp_0[0], &CD_measured.dti[0], (uint32_T)(10U * sizeof(real_T))); void CD_initialize(void) { { real_T *tmp; int32_T i; tmp = set_ModelInitialize_DataTransfer(); for (i = 0; i < 10; i++) { tmp[i] = 5.0; } memcpy(&CD_measured.delay[0], &(get_CD_initialize_InBus_NVM())[0], (uint32_T) (10U * sizeof(real_T))); rtDWork.Integrator_RESET_ELAPS_T = true; rtDWork.DiscreteTimeIntegrator_SYSTEM_E = 1U; } } void CD_terminate(void) { memcpy(&(getref_CD_terminate_OutBus_NVM())[0], &CD_measured.delay[0], (uint32_T)(10U * sizeof(real_T))); }
The accumulator and integrator functions use the state variables CD_states.dti
and CD_states.delay
in the for
loops. The integrator, initialize, and terminate functions, use the variables for the memory copy operations.