Deploy the Generated Code - MATLAB & Simulink (original) (raw)

This example shows you how to deploy the generated component code as a component library by using CMake. To deploy the generated code:

  1. Generate code from the model by using the component deployment configuration.
  2. Implement handwritten integration code.
  3. Configure CMake for your target environment.
  4. Generate build artifacts and build integrated code.
  5. Run the executable program.

For information about other deployment methods, see Additional Deployment Tools.

Configure the Model for Deployment and Generate Code

Set up the model hierarchy to use the configuration for deployment.

  1. If you have not already done so, follow the steps in the previous part of the workflow, Test the Generated Code, or run the script.
    openExample("EvPowertrainController")
    TestConfigEvPowertrain
  2. From the modelEvPowertrainController, on theModeling tab, in theDesign gallery, open theModel Explorer.
  3. Expand the EvPowertrainController node and navigate to the > > node.
  4. In the center pane, select the configuration referenceActiveSharedReference. On the right pane, from the Name drop-down list, selectControllerConfigDeployment and click Apply.
    This deployment configuration is the same as theControllerConfig configuration that you edited, except for theToolchain setting, which is now set to CMake. TheCMake toolchain generates a platform-independentCMakeLists.txt file.
  5. On the left pane, right-clickevModelingData and click .
  6. If you generated code in the previous part of the workflow, delete the shared folderslprj, which will be regenerated when you build the model.
  7. From the model, generate code. Open the Embedded Coder® app and clickBuild or pressCtrl+B.

In the services subfolder beneath the build folder (EvPowertrainController_ert_rtw), the software generates a header file EvServices.h. The file defines interfaces to services that you must implement for an application containing the generated component.

In the services/lib subfolder beneath the build folder, the software generates a CMakeLists.txt file that you can use to build the generated code into a static library.

The software generates a ZIP file, which contains the generated code, build artifact, and CMakeLists.txt files, because**Package code and artifacts** is enabled. Optionally, you can relocate the ZIP file to another development environment.

Implement Integration Code

To integrate and deploy the generated code, implement:

Implement handwritten code for a main function in your code generation folder. For this example, you can use the function in the fileEvPowerControllerIntegration.c. This function:

  1. Calls the initialization function and the function to read in data from memory.
  2. Calls the motor power management function 10 times.
  3. After calling the motor power management function four times, the function also calls the regenerative braking function.
  4. Writes the output to memory and calls the terminate function.

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();
}

In your code generation folder, create handwritten code that provides implementations of the target platform services declared inEvServices.h. For this example, use the service implementations defined inEvControllerServices.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;
}

To produce an executable application that incorporates the handwritten main function and service implementations, as well as links with the library generated from the Simulink model, create a handwrittenCMakeLists.txt file in your code generation folder. The file must perform these tasks:

For this example, copy the content from the provided text fileCMakeListsEvController.txt into theCMakeLists.txt file.

copyfile CMakeListsEvController.txt CMakeLists.txt

cmake_minimum_required(VERSION 3.12)
 
# Set a name for the project
project(EvPowertrainControllerIntegration)
 
# Use the "add_subdirectory" command to reference the CMakeLists.txt file
# that was generated by codebuild for the code generated from
# the Simulink model.  This file has defined a static library target
# named "EvPowertrainController" that you will link into
# the application further down.
add_subdirectory(EvPowertrainController_ert_rtw/services/lib)
 
# Use the "add_executable" command to define an executable target named
# "EvPowertrainController" that is built from the handwritten
# source files.
add_executable(EvPowertrainControllerIntegration
    EvPowertrainControllerIntegration.c
    EvControllerServices.c)
 
# Specify that the executable target "EvPowertrainController"
# incorporating the handwritten code is linked against the
# "EvPowertrainController" library target containing the code
# generated from the Simulink model.
target_link_libraries(EvPowertrainControllerIntegration EvPowertrainController)

Configure CMake

Configure the CMake command and arguments for your target environment. In the MATLAB Command Window, run one of these examples.

Windows - Microsoft Visual Studio 2017 Solution

cmakeCommand = ['"', fullfile(matlabroot,'bin','win64','cmake','bin','cmake.exe'), '"']; cmakeArguments = '-G "Visual Studio 15 2017"';

Windows - Microsoft Visual Studio 2019 Solution

cmakeCommand = ['"', fullfile(matlabroot,'bin','win64','cmake','bin','cmake.exe'), '"']; cmakeArguments = '-G "Visual Studio 16 2019"';

Windows - Microsoft Visual Studio 2022 Solution

cmakeCommand = ['"', fullfile(matlabroot,'bin','win64','cmake','bin','cmake.exe'), '"']; cmakeArguments = '-G "Visual Studio 17 2022"';

Windows - MinGW

mingwLoc = getenv('MW_MINGW64_LOC'); assert(~isempty(mingwLoc),'Could not find location of MinGW installation'); mingwLocBin = [mingwLoc,'/bin']; envSetupCommand = ['set PATH=', mingwLocBin, ';%PATH% && ']; cmakeCommand = [envSetupCommand, '"', fullfile(matlabroot,'bin','win64','cmake','bin','cmake.exe'), '"']; cmakeArguments = ['-G "MinGW Makefiles" ', ... '-DCMAKE_C_COMPILER="gcc.exe" ', ... '-DCMAKE_CXX_COMPILER="g++.exe"'];

Linux - GCC and GMake

cmakeCommand = ['"', fullfile(matlabroot,'bin','glnxa64','cmake','bin', 'cmake'), '"']; cmakeArguments = '-G "Unix Makefiles"';

Mac - XCode with Clang

cmakeCommand = ['"', fullfile(matlabroot,'bin',computer('arch'),'cmake','bin','cmake'), '"']; cmakeArguments = '-G "Xcode"';

Generate Build Artifacts and Build Integrated Code

To generate required build artifacts and build the integrated code, run CMake. The CMake tool processes theCMakeLists.txt file in the folder specified through the -S flag, and generates the configuration files for your build system in the folder that you specify through the -B flag. In your code generation folder, run this command.

[status1, cmdout1] = system([cmakeCommand ' -S . -B build ', cmakeArguments],'-echo');

Using the --build flag, build the application.

[status2, cmdout2] = system([cmakeCommand ' --build build'],'-echo');

The location of the executable program file that the CMake generator produces depends on the CMake generator that you use.

To save the location to a variable, use one of these commands.

Windows - Visual Studio Solution

exeLocation = fullfile('build','Debug','EvPowertrainControllerIntegration.exe');

Windows - GMake Makefiles

exeLocation = fullfile('build','EvPowertrainControllerIntegration.exe');

Linux - GMake Makefiles

exeLocation = fullfile('build','EvPowertrainControllerIntegration');

Mac - Xcode project

exeLocation = fullfile('build','Debug','EvPowertrainControllerIntegration');

Run Executable Program

Use this command to run the compiled executable program.

[status3, cmdout3] = system(exeLocation,'-echo');

Some sample output follows.

Running Motor Power Management function (iteration 4) Service function called: get_EvPowertrainController_MotorPwrMgmt_func_AccCmd_outside_ex. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_DataTransferAtRegenBrakingOutport1. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_BattSoc_outside_ex. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_MotSpd_outside_ex. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_MotSpd_outside_ex. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_BattPwr_outside_ex. Service function called: set_EvPowertrainController_MotorPwrMgmt_func_MotTrqCmd_outside_ex.

Running Regen Braking function (iteration 5) Service function called: get_EvPowertrainController_RegenBraking_func_DecCmd_outside_ex. Service function called: get_EvPowertrainController_RegenBraking_func_MotSpd_outside_ex. Service function called: get_EvPowertrainController_RegenBraking_func_VehSpdFdbk_outside_ex. Service function called: get_EvPowertrainController_RegenBraking_func_BattSoc_outside_ex. Service function called: set_EvPowertrainController_RegenBraking_func_DataTransferAtRegenBrakingOutport1. Service function called: set_EvPowertrainController_RegenBraking_func_MotTrqCmd_outside_ex. Service function called: set_EvPowertrainController_RegenBraking_func_BrakeCmd_outside_ex. Service function called: set_EvPowertrainController_RegenBraking_func_NVMOut_outside_ex.

Running Motor Power Management function (iteration 5) Service function called: get_EvPowertrainController_MotorPwrMgmt_func_AccCmd_outside_ex. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_DataTransferAtRegenBrakingOutport1. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_BattSoc_outside_ex. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_MotSpd_outside_ex. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_MotSpd_outside_ex. Service function called: get_EvPowertrainController_MotorPwrMgmt_func_BattPwr_outside_ex. Service function called: set_EvPowertrainController_MotorPwrMgmt_func_MotTrqCmd_outside_ex.

Running Regen Braking function (iteration 6) Service function called: get_EvPowertrainController_RegenBraking_func_DecCmd_outside_ex. Service function called: get_EvPowertrainController_RegenBraking_func_MotSpd_outside_ex. Service function called: get_EvPowertrainController_RegenBraking_func_VehSpdFdbk_outside_ex. Service function called: get_EvPowertrainController_RegenBraking_func_BattSoc_outside_ex. Service function called: set_EvPowertrainController_RegenBraking_func_DataTransferAtRegenBrakingOutport1. Service function called: set_EvPowertrainController_RegenBraking_func_MotTrqCmd_outside_ex. Service function called: set_EvPowertrainController_RegenBraking_func_BrakeCmd_outside_ex. Service function called: set_EvPowertrainController_RegenBraking_func_NVMOut_outside_ex.

Writing NVM out Service function called: set_EvPowertrainController_writePowertrainControlNVM_func_NVMOut_outside_ex.

Running model terminate function Updating Model Advisor cache... Model Advisor cache updated. For new customizations, to update the cache, use the Advisor.Manager.refresh_customizations method.

Additional Deployment Tools

This example showed you how to deploy the component algorithm as a component model library by using CMake. To deploy your generated code, consider these additional deployment tools for different goals and targets.

For some common platforms and hardware targets, you can use relevant blocksets and hardware support packages to automate the deployment of generated code.

For more information, see Approaches for Building Code Generated from Simulink Models.

See Also

Topics