Main Content

Generate C Interface Code for Measurement Service Using Persistent Data for Component Deployment

Since R2025a

This example shows how to generate component code that includes interface support for accessing state data stored in nonvolatile memory. The generated interface code must align with target environment interface requirements.

The example shows how to:

  1. Represent measurable state data that is stored in nonvolatile memory in the top model.

  2. Configure the code generator to apply a code interface.

  3. Generate and inspect the interface code.

Represent Measurement Data in Top Model

Open example component model ComponentServiceWithPersistency.

open_system('ComponentServiceWithPersistency');

The integrator and accumulator functions operate on state data, which is stored in nonvolatile memory. Discrete state data is accessed through the measurement service interface for persistent data.

Open the function-call subsystems Integrator and Accumulator to review the function modeling.

The integrator function uses a state variable to represent the discrete time integrator. The accumulator function uses a state variable to represent the delay. In this example, the target environment requires the names of the corresponding variables in the generated code to be dti and delay.

Configure Measurement Code Interface for Persistent Data

The example model is linked to the shared Embedded Coder Dictionary file ComponentServiceCoderDictionary.sldd, which defines a service code interface configuration. That configuration defines a measurement service interface named PermanentRAM. The PermanentRAM service interface has persistent data support enabled and is configured to apply storage class PersistentMemory, which is defined with these settings:

  • Data Access - Direct

  • Data Scope - Exported

  • Header File - $N.h

  • Definition File - $N.c

  • Use different property settings for single-instance and multi-instance data - off

  • Storage Type - Unstructured

  • Data Initialization - None

  • Memory Section - None

  • Preserve array dimensions - off

In addition, no qualifiers are specified. In the values for Header File and Definition File, the software replaces $N with the name of the model.

Configure the model so that the code generator applies the PermanentRAM coder dictionary interface to the modeling elements that use persistent data.

  1. Open the Embedded Coder app.

  2. On the C Code tab, select Code Interface > Component Interface to configure individual model elements.

  3. In the Code Mappings editor, click the Signals/States tab.

  4. Expand the States node and select the row for Discrete-Time Integrator.

  5. From the menu in the Measurement Service column of the selected row, select PermanentRAM.

  6. In the selected row, click the pencil icon.

  7. In the dialog box that appears, set Identifier to dti. Alternatively, you can set Identifier in the Property Inspector.

  8. Select the row for Unit Delay.

  9. Set Identifier 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 ComponentServiceWithPersistency_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 ComponentServiceWithPersistency.h and source code file ComponentServiceWithPersistency.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 ComponentServiceWithPersistency.h declares model data structures and a public interface to the model entry points and exported model data.

This code fragment shows the declaration of block state variables for persistent data that are exported through the header file.

extern double delay[10];               /* '<S1>/Unit Delay' */
extern double dti[10];                 /* '<S2>/Discrete-Time Integrator' */

Source Code File

This code fragment in generated source code file ComponentServiceWithPersistency.c shows code relevant to the measurement service interface for persistent data.

/* Storage class 'PersistentMemory' */
double delay[10];
double dti[10];
.
.
.

void CD_accumulator(void)
{
  const double *tmpDataTransferIRead;
  double rtb_Sum_0;
  int32_t i;

  tmpDataTransferIRead = get_CD_accumulator_DataTransfer();
  for (i = 0; i < 10; i++) {
    rtb_Sum_0 = tmpDataTransferIRead[i] + delay[i];
    (getref_CD_accumulator_OutBus_y())[i] = CD_tunable.k * rtb_Sum_0;
    delay[i] = rtb_Sum_0;
  }
}

void CD_integrator(void)
{
  double DiscreteTimeIntegrator[10];
  double DiscreteTimeIntegrator_0;
  double *tmp;
  uint64_t Integrator_ELAPS_T;
  int32_t i;

  tmp = set_CD_integrator_DataTransfer();

  if (rtDWork.Integrator_RESET_ELAPS_T) {
    Integrator_ELAPS_T = 0ULL;
  } else {
    Integrator_ELAPS_T = (uint64_t)get_tick_outside_tick_CD_integrator() -
      rtDWork.Integrator_PREV_T;
  }

  rtDWork.Integrator_PREV_T = get_tick_outside_tick_CD_integrator();
  rtDWork.Integrator_RESET_ELAPS_T = false;
  for (i = 0; i < 10; i++) {
    if (rtDWork.DiscreteTimeIntegrator_SYSTEM_E != 0) {
      DiscreteTimeIntegrator_0 = dti[i];
    } else {
      DiscreteTimeIntegrator_0 = 0.25 * (double)Integrator_ELAPS_T
        * rtDWork.DiscreteTimeIntegrator_PREV_U[i] + dti[i];
    }

    DiscreteTimeIntegrator[i] = DiscreteTimeIntegrator_0;
    dti[i] = DiscreteTimeIntegrator_0;
    rtDWork.DiscreteTimeIntegrator_PREV_U[i] = (get_CD_integrator_InBus_u())[i];
  }

  rtDWork.DiscreteTimeIntegrator_SYSTEM_E = 0U;
  memcpy(&tmp[0], &DiscreteTimeIntegrator[0], 10U * sizeof(double));

}

void ComponentServiceWithPersistency_initialize(void)
{
  (void) memset((void *)&rtDWork, 0,
                sizeof(D_Work));
  {
    double *tmp;
    int32_t i;
    tmp = set_ComponentServiceWithPersistency_initialize_DataTransfer();

    for (i = 0; i < 10; i++) {
      rtDWork.DiscreteTimeIntegrator_PREV_U[i] = 0.0;
      tmp[i] = 5.0;
    }

    rtDWork.Integrator_RESET_ELAPS_T = true;
    rtDWork.DiscreteTimeIntegrator_SYSTEM_E = 1U;
  }
}

void ComponentServiceWithPersistency_terminate(void)
{
}

The accumulator and integrator functions use the variables dti and delay to hold internal states during algorithmic computations for the functions. Variables dti and delay are not initialized in ComponentServiceWithPersistency_initialize or elsewhere in the generated code because those variables are mapped to persistent data, which is initialized and managed by a nonvolatile memory management service in the external environment.

Related Examples

More About