Define the Interfaces Between the Generated Code and Your Deployment Platform - MATLAB & Simulink (original) (raw)

To generate code that you can deploy in your target environment, create custom code interface definitions that define how the generated code interacts with the target platform software. By defining the code interfaces separately from your models, you can:

Later in the workflow, you apply the code interface configuration to your models.

Choose a Code Interface Configuration for Your Deployment Goals

Depending on your deployment goals, you define one of these types of interface configurations:

Each type of interface configuration contains definitions for the different types of code interfaces. Later in the workflow, you map elements of your models to the associated code interface definitions so that the code generator generates the corresponding code.

If your deployment scenario requires more advanced customizations that are not available in the Embedded Coder Dictionary, you can create definitions by using the custom storage class designer. To use these definitions, you must configure and maintain model elements individually. For more information, see Create Storage Classes by Using the Custom Storage Class Designer.

Example Platform Middleware Services

For this example, the platform middleware contains amain function that calls the generated algorithm code and provides services that the generated code calls. In this case, the model should use a service interface configuration for code generation. When you set up the service interface configuration, you define the generated code interfaces to match the interfaces of the platform middleware.

The example main function is in the fileEvPowerControllerIntegration.c.

EvPowertrainControllerIntegration.c

/* EvPowertrainControllerIntegration.c
 *
 *  Example handwritten client code to integrate with generated
 *  code from EvPowertrainController.slx
 *
 * Copyright 2022-2023 The MathWorks, Inc. */
 
#include "EvPowertrainController.h"
 
#include <stddef.h>
#include <stdio.h>
 
extern uint64_T tick;   // Variable used by timer service implementation
 
const size_t nIter = 10;
 
int main(void) {
 
    // Run model initialize function
    printf("\nRunning model initialize function\n");
    EvPowertrainController_initialize_func();

    // Read NVM
    printf("\nReading NVM\n");
    EvPowertrainController_readPowertrainControlNVM_func();
 
    for (size_t k = 0; k < nIter; ++k) {
 
        if (k > 4) {
            // The Regen Braking function runs only when k > 4
            printf("\nRunning Regen Braking function (iteration %llu)\n", k);
            EvPowertrainController_RegenBraking_func();
        }

        // Run Motor Power Management at every iteration
        printf("\nRunning Motor Power Management function (iteration %llu)\n", k);
        EvPowertrainController_MotorPwrMgmt_func();

        // Increment timer tick count
        tick++;
    }
 
    // Write NVM
    printf("\nWriting NVM\n");
    EvPowertrainController_writePowertrainControlNVM_func();

    // Run model terminate function
    printf("\nRunning model terminate function\n");
    EvPowertrainController_terminate_func();
}

The platform middleware provides the services in the fileEvControllerServices.c.

EvControllerServices.c

/* EvControllerServices.c
*
*  Example concrete realization of service interface for
*  the code generated from EvPowertrainController.slx.
*
* Copyright 2024 The MathWorks, Inc. */
  
#include "EvServices.h"
#include <stdio.h>
 
static double DataTransfer_storage[1] = {0};
static double input_storage[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
static double NVM_storage[1] = {100};
static double output_storage[2] = {0, 0};
 
/* data transfer services */
const double get_EvPowertrainController_MotorPwrMgmt_func_DataTransferAtRegenBrakingOutport1(void) {
    printf("Service function called: get_EvPowertrainController_MotorPwrMgmt_func_DataTransferAtRegenBrakingOutport1.\n");
    return DataTransfer_storage[0];
}
 
void set_EvPowertrainController_RegenBraking_func_DataTransferAtRegenBrakingOutport1(double aVal) {
    printf("Service function called: set_EvPowertrainController_RegenBraking_func_DataTransferAtRegenBrakingOutport1.\n");
    DataTransfer_storage[0] = aVal;
}
 
/* receiver services */
const double get_EvPowertrainController_MotorPwrMgmt_func_AccCmd_outside_ex(void) {
    printf("Service function called: get_EvPowertrainController_MotorPwrMgmt_func_AccCmd_outside_ex.\n");
    return input_storage[0];
}

const double get_EvPowertrainController_RegenBraking_func_DecCmd_outside_ex(void) {
    printf("Service function called: get_EvPowertrainController_RegenBraking_func_DecCmd_outside_ex.\n");
    return input_storage[1];
}
 
const double get_EvPowertrainController_RegenBraking_func_VehSpdFdbk_outside_ex(void) {
    printf("Service function called: get_EvPowertrainController_RegenBraking_func_VehSpdFdbk_outside_ex.\n");
    return input_storage[2];
}

const double get_EvPowertrainController_MotorPwrMgmt_func_BattSoc_outside_ex(void) {
    printf("Service function called: get_EvPowertrainController_MotorPwrMgmt_func_BattSoc_outside_ex.\n");
    return input_storage[3];
}

const double get_EvPowertrainController_RegenBraking_func_BattSoc_outside_ex(void) {
    printf("Service function called: get_EvPowertrainController_RegenBraking_func_BattSoc_outside_ex.\n");
    return input_storage[4];
}

const double get_EvPowertrainController_MotorPwrMgmt_func_BattPwr_outside_ex(void) {
    printf("Service function called: get_EvPowertrainController_MotorPwrMgmt_func_BattPwr_outside_ex.\n");
    return input_storage[5];
}

const double get_BattCrnt_outside_ex(void) {
    printf("Service function called: get_BattCrnt_outside_ex.\n");
    return input_storage[6];
}

const double get_EvPowertrainController_MotorPwrMgmt_func_MotSpd_outside_ex(void) {
    printf("Service function called: get_EvPowertrainController_MotorPwrMgmt_func_MotSpd_outside_ex.\n");
    return input_storage[7];
}

const double get_EvPowertrainController_RegenBraking_func_MotSpd_outside_ex(void) {
    printf("Service function called: double get_EvPowertrainController_RegenBraking_func_MotSpd_outside_ex.\n");
    return input_storage[8];
}

const double get_EvPowertrainController_readPowertrainControlNVM_func_NVMIn_outside_ex(void) {
    printf("Service function called: get_EvPowertrainController_readPowertrainControlNVM_func_NVMIn_outside_ex.\n");
    return NVM_storage[0];
}
 
/* sender services */
void set_EvPowertrainController_MotorPwrMgmt_func_MotTrqCmd_outside_ex(double
  rtu_MotTrqCmd_value) {
    printf("Service function called: set_EvPowertrainController_MotorPwrMgmt_func_MotTrqCmd_outside_ex.\n");
    output_storage[0] = rtu_MotTrqCmd_value;
}

void set_EvPowertrainController_RegenBraking_func_MotTrqCmd_outside_ex(double
  rtu_MotTrqCmd_value) {
    printf("Service function called: set_EvPowertrainController_RegenBraking_func_MotTrqCmd_outside_ex.\n");
    output_storage[0] = rtu_MotTrqCmd_value;
}

void set_EvPowertrainController_RegenBraking_func_BrakeCmd_outside_ex(double
  rtu_BrakeCmd_value) {
    printf("Service function called: set_EvPowertrainController_RegenBraking_func_BrakeCmd_outside_ex.\n");
    output_storage[1] = rtu_BrakeCmd_value;
}

void set_EvPowertrainController_RegenBraking_func_NVMOut_outside_ex(double
  rtu_NVMOut_value) {
    printf("Service function called: set_EvPowertrainController_RegenBraking_func_NVMOut_outside_ex.\n");
    NVM_storage[0] = rtu_NVMOut_value;
}

void set_EvPowertrainController_writePowertrainControlNVM_func_NVMOut_outside_ex(double
  rtu_NVMOut_value) {
    printf("Service function called: set_EvPowertrainController_writePowertrainControlNVM_func_NVMOut_outside_ex.\n");
    NVM_storage[0] = rtu_NVMOut_value;
}

For more information about the platform middleware code that integrates the generated code, see Implement Integration Code.

Create an Embedded Coder Dictionary to Contain Interface Definitions

To contain the service interface configuration, create an Embedded Coder Dictionary that you share with the models from which you want to generate code. In the dictionary, you define the interfaces of the generated functions and the calls to platform-provided services.

  1. If you have not already done so, follow the steps in the previous part of the workflow, Configure Basic Code Generation Settings, or run the script.
    openExample("EvPowertrainController")
    ConfigureEvPowertrainModel
  2. From the modelEvPowertrainController, open the Embedded Coder app. On the C Code tab, click > .
  3. In the Set Up Embedded Coder Dictionary dialog box, select Create Embedded Coder Dictionary. In the Create dictionary text box, enter the nameCoderDict.sldd.
    Set Up Embedded Coder Dictionary dialog box.
    Embedded Coder creates this data dictionary to store the Embedded Coder Dictionary. ClickNext.
  4. Select Service Interface and click Create.
    Set Up Embedded Coder Dictionary dialog box.
    The Embedded Coder Dictionary opens to display the service interface configuration. The configuration contains built-in interface definitions.
  5. On the General pane, set theServices Header File name toEvServices.h. This file is the header file for the services provided by the target platform software.
    Embedded Coder Dictionary showing the General pane.

Because you used the Set Up Embedded Coder Dictionary dialog, the dictionary is automatically shared with the referenced modelBatteryManagementSystem. If you adapt this workflow for your own system, you might need to share the dictionary with other models or otherwise manage the code interface configuration. For more information, see Share Code Interface Configuration Between Models and Manage an Embedded Coder Dictionary.

Define Function Interfaces

To control the naming of generated functions, define function customization templates. The platform scheduler executes the generated code by calling the generated functions. Types of functions include:

For this example, add a custom definition for each type of function interface.

  1. In the Service Interface pane, click Initialize and Terminate.
  2. In the center pane, under Initialize and Terminate Functions, clickCreate.
  3. Select the new template definition and, on the right pane, set these properties:
    • NameInitTermFuncs
    • Function Naming Rule$R$N_func
    • Memory SectionNone
      When this definition is applied to the modelEvPowertrainController, the generated initialize and terminate functions are namedEvPowertrainController_init_func andEvPowertrainController_term_func.
  4. In the center pane, under Periodic and Aperiodic Functions, clickCreate.
  5. Select the new template definition and, on the right pane, set these properties:
    • NameExecutionFuncs
    • Function Naming Rule$R$N_func
    • Memory SectionNone
      When this definition is applied to the modelEvPowertrainController, the generated execution functions are namedEvPowertrainController_<_export function name_>_func.
  6. Select the definitions that you added as the dictionary default definitions for functions of the respective categories. In the row for each new entry, click the circle below Dictionary Default.

Coder dictionary showing the execution functions.

Define Service Interfaces

Specify how the generated code calls the services of the platform middleware by creating service interface definitions.

For this example, add definitions for the sender, receiver, and data transfer service interfaces.

  1. In the Service Interface pane, click Data Receiver.
  2. In the center pane, under Data Receiver, clickCreate.
  3. Select the new template definition and, on the right pane, set these properties:
    • NameDataReceiver
    • Data Communication MethodOutside Execution
    • Function Naming Ruleget_$X$N_outside_ex
      When this definition is applied to the modelEvPowertrainController, each generated receiver function follows the naming rule and reads data from another function before the function starts executing.
  4. In the center pane, under Data Sender, clickCreate.
  5. Select the new template definition and, on the right pane, set these properties:
    • NameDataSender
    • Data Communication MethodOutside Execution
    • Function Naming Rule for Valueset_$X$N_outside_ex
    • Function Naming Rule for Value By Referencegetref_$X$N_outside_ex
      When this definition is applied to the modelEvPowertrainController, each generated sender function follows the naming rule and sends data to another function before the function starts executing.
  6. Select the definitions that you added as the dictionary default definitions for functions of the respective categories. In the row for each new entry, click the circle below Dictionary Default.
  7. Make parameters tunable and preserve signals for measurement by selecting default definitions for these categories:
    • Parameter TuningParameterTuningExample1
    • Parameter Argument TuningParameterArgumentTuningExample1
    • MeasurementMeasurementExample1
  8. On the Dictionary tab, click Save.

Coder dictionary showing the service interfaces.

To see the other interface customization options that the Embedded Coder Dictionary provides, click the sections in theService Interface pane on the left. For more information about defining service interfaces, see Create a Service Interface Configuration and Target Environment Services. For examples of service implementations for the communication methods, see Sample Target Environment Service Implementations of Data Communication Methods.

See Also

Embedded Coder Dictionary

Topics