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:
- Generate code from the model by using the component deployment configuration.
- Implement handwritten integration code.
- Configure CMake for your target environment.
- Generate build artifacts and build integrated code.
- 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.
- 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 - From the model
EvPowertrainController
, on theModeling tab, in theDesign gallery, open theModel Explorer. - Expand the EvPowertrainController node and navigate to the > > node.
- In the center pane, select the configuration reference
ActiveSharedReference
. 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 toCMake
. TheCMake
toolchain generates a platform-independentCMakeLists.txt
file. - On the left pane, right-click
evModelingData
and click . - If you generated code in the previous part of the workflow, delete the shared folder
slprj
, which will be regenerated when you build the model. - From the model, generate code. Open the Embedded Coder® app and clickBuild or press
Ctrl+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:
- A
main
function - Implementations of the services declared in
EvServices.h
- A handwritten
CMakeLists.txt
file
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:
- Calls the initialization function and the function to read in data from memory.
- Calls the motor power management function 10 times.
- After calling the motor power management function four times, the function also calls the regenerative braking function.
- 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
*
* 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:
- Import the previously generated
CMakeLists.txt
file that contains the rules to build the static library from the component code. - Add a rule to build the handwritten source files
EvPowertrainControllerIntegration.c
andEvControllerServices.c
into an executable program. - Link the executable program with the static library that contains the compiled component code.
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.
- Makefile based CMake generator — Relative to your current working folder, places the executable program file in subfolder
build
. - Project-based CMake generator — Relative to your current working folder, places the executable program file in folder
build/Debug
.
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.