Customize XCP Server Software
The XCP communication protocol for Simulink® external mode simulations is a client-server communication protocol. By default, the software supports XCP external mode simulations:
On your development computer for code that is generated by using ERT (
ert.tlc
) and GRT (grt.tlc
) system target files.
If your system target file for custom target hardware is derived from the ERT or GRT system target files, you can use supplied APIs to provide XCP target connectivity. XCP external mode limitations apply.
The external mode target connectivity software comprises:
External mode abstraction layer
XCP server protocol layer
XCP server transport layer
XCP platform abstraction layer
External Mode Abstraction Layer
To communicate with Simulink during an external mode simulation, your target application must invoke functions from the external mode abstraction layer.
The parent folder for source code files is:
matlabroot\toolbox\coder\xcp\src\target\ext_mode
The layer APIs are declared in include\ext_mode.h
and implemented in
src\xcp_ext_mode.c
.
To communicate with Simulink, the target application uses services exposed by the external mode abstraction layer. This flow chart shows the required target application steps to establish communication with Simulink.
This tables lists the functions that your target application must invoke at each stage.
Stage | Function | Purpose |
---|---|---|
| Extract external mode command-line arguments. | |
| Initialize generated Simulink model code. | |
Initialize external mode target connectivity. | ||
| Wait for a start request from development computer, which is created when you click Run button. | |
|
| Run single step of generated Simulink model code. |
For sample time ID of the model, sample signals generated by model step function and pass packet content to transport layer of communication protocol for transmission to development computer. | ||
Transmit and receive packet from physical communication interface and process packet content in accordance with selected communication protocol. | ||
HOST STOP REQUEST OR SIMULATION
COMPLETE | Check whether a request to stop external mode simulation is received from the model on the development computer. The request is created when you click the Stop button. | |
Check whether execution of generated model code is complete. | ||
RESET |
| Terminate generated Simulink model code. |
Reset the external mode target connectivity to initial state. |
This pseudo-code example shows how you can implement the various flowchart stages in
your target application. During the RUN
stage, the external mode run-time
environment requires at least two threads:
A periodic thread that is responsible for the execution of the generated model code.
A background thread that is responsible for running the external mode communication stack and transmitting and receiving packets.
The pseudo-code simulates multithreading by running
periodicThread
and extmodeBackgroundRun
sequentially
within the same while()
loop.
/*------------- Pseudo-Code Example -------------*/ /* Define periodic thread */ void periodicThread(void) { /* Run model step function */ modelName_step(); /* Notify external mode abstraction layer about periodic event */ extmodeEvent(PERIODIC_EVENT_ID, currentSimulationTime); } /* Main function for target application */ main(int argc, char *argv[]) { /*------------- INITIALIZE -------------*/ /* Parse external mode command line arguments */ extmodeParseArgs(argc, argv); /* Initialize model */ modelName_initialize(); /* Initialize external mode target connectivity */ extmodeInit(extModeInfo, finalSimulationTime); /*------------- HOST START REQUEST -------------*/ /* Wait until a start request is received from development computer */ extmodeWaitForHostRequest(EXTMODE_WAIT_FOREVER); /*------- HOST STOP REQUEST OR SIMULATION COMPLETE -------*/ /* While simulation is not complete and stop request is not received */ while (!extmodeSimulationComplete() && !extmodeStopRequested()) { /*------------- RUN -------------*/ periodicThread(); extmodeBackgroundRun(); } /*------------- RESET -------------*/ /* Terminate model */ modelName_terminate(); /* Reset external mode target connectivity */ extmodeReset(); return 0; }
To see code that invokes the functions, complete the example in External Mode Simulation by Using XCP Communication with System target
file set to ert.tlc
. Then, from the code generation
folder, open ert_main.c
.
Note
If your system target file is grt.tlc
or GRT-based, the code
generator creates rt_main.c
, and, by default, uses API defined by the
internal file ext_work.h
. To enable the use of
ext_mode.h
API, before building the target application,
run:
set_param(model, 'TLCOptions', '-aExtModeXCPClassicInterface=0');
If your system target file is ert.tlc
or ERT-based and
GenerateSampleERTMain
is set to 'on'
, the code
generator creates ert_main.c
and, by default, uses API defined by
ext_mode.h
. To enable the use of ext_work.h
API,
before building the target application,
run:
set_param(model, 'TLCOptions', '-aExtModeXCPClassicInterface=1');
XCP Server Protocol Layer
The XCP server protocol layer interprets XCP commands and data according to the Association for Standardisation of Automation and Measuring Systems (ASAM) standard, ASAM MCD-1 XCP.
The source code folder is:
matlabroot\toolbox\coder\xcp\src\target\server\protocol\src
XCP Server Transport Layer
The XCP server transport layer transmits and receives messages from the communication medium according to ASAM specifications.
The source folder is:
matlabroot\toolbox\coder\xcp\src\target\server\transport\src
XCP Platform Abstraction Layer
The XCP platform abstraction layer provides:
An XCP driver for sending and receiving raw data through the physical communication interface.
The implementation of a static memory allocator.
You can use the
target
package
to provide connectivity between Simulink and your target hardware. To specify:
The XCP driver, use the
target.CommunicationInterface
class.Other parts of the XCP platform abstraction layer, use the
target.XCPPlatformAbstraction
class.
If you do not specify the XCP platform abstraction layer, the software uses the default platform abstraction layer, which supports Linux®, Windows®, and Mac platforms. For more information, see Customise Connectivity for XCP External Mode Simulations.
For a customization example, see Create Custom Abstraction Layer.
XCP Driver
The XCP driver sends and receives XCP messages through the communication channel. In an external mode simulation, the build process automatically adds the driver files to build information.
The XCP driver is based on the rtiostream
API. For example,
host-based external mode simulations use these rtiostream
files:
matlabroot
\toolbox\coder\rtiostream\src\rtiostreamtcpip\rtiostream_tcpip.cmatlabroot
\toolbox\coder\rtiostream\src\rtiostreamserial\rtiostream_serial.c
For details on implementing and testing an rtiostream
communications channel, see:
Communications rtiostream API (Embedded Coder)
To provide rtiostream
information:
If you use the
target
package for connectivity, use thetarget.CommunicationInterface
class. See Customise Connectivity for XCP External Mode Simulations.If you do not use the
target
package, add yourrtiostream
files to a build information object.
For more information, see Create Custom Abstraction Layer.
Memory Allocator
The XCP server software requires the dynamic allocation of variable-size, contiguous memory blocks to hold internal data structures. In an external mode simulation, the build process automatically adds memory allocator files to the build information object.
Configure alignment for the memory allocator through the
XCP_MEM_ALIGNMENT
preprocessor macro. For
example:
#define XCP_MEM_ALIGNMENT 8
If you use the
target
package for connectivity, use the BuildDependencies
property of the
target.XCPPlatformAbstraction
class. For
example:
xcpPlatformAbstraction.BuildDependencies.Defines = {'XCP_MEM_ALIGNMENT=8'};
Other Platform Abstraction Layer Functionality
This file defines the platform abstraction layer interface:
matlabroot\toolbox\coder\xcp\src\target\server\platform\include\xcp_platform.h
This table describes the functionality that you must provide for the XCP server software that you deploy on your target hardware.
Functionality | Details |
---|---|
Mutual exclusion | To access system data structures with mutual exclusion support, the XCP driver depends on basic APIs for definition, initialization, lock, and unlock. To support mutual exclusion for your target hardware, provide a custom implementation. The default implementation for Linux and Windows supports mutual exclusion. #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) ... #define XCP_MUTEX_DEFINE(lock) HANDLE lock #define XCP_MUTEX_INIT(lock) lock = CreateMutex(0, FALSE, 0) #define XCP_MUTEX_LOCK(lock) WaitForSingleObject((lock), INFINITE) #define XCP_MUTEX_UNLOCK(lock) ReleaseMutex(lock) #else ... #include <pthread.h> #define XCP_MUTEX_DEFINE(lock) pthread_mutex_t lock #define XCP_MUTEX_INIT(lock) pthread_mutex_init(&(lock), NULL) #define XCP_MUTEX_LOCK(lock) pthread_mutex_lock(&(lock)) #define XCP_MUTEX_UNLOCK(lock) pthread_mutex_unlock(&(lock)) ... #endif |
Sleep | Provide a sleep API that makes the calling thread sleep until a specified time has elapsed. The default implementation for Linux and Windows systems is: #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) ... #define XCP_SLEEP(seconds,microseconds) Sleep((seconds) * 1000 \ + (((microseconds) + 1000 - 1) / 1000)) #else ... #if _POSIX_C_SOURCE >= 199309L #define XCP_SLEEP(seconds,microseconds) do {struct timespec t;\ t.tv_sec = seconds; t.tv_nsec = microseconds * 1000; nanosleep(&t, NULL);} while(0) #else /* nanosleep is not available. Use select instead. */ #define XCP_SLEEP(seconds,microseconds) do {struct timeval t; t.tv_sec = seconds;\ t.tv_usec = microseconds; select(0, NULL, NULL, NULL, &t);} while(0) #endif /* _POSIX_C_SOURCE >= 199309L */ ... #endif |
Logging | To generate diagnostic messages, the XCP server software requires a
custom print API that supports logging services provided by the target
hardware. If you do not define the |
Address conversion | The XCP standard expresses the address of a variable in memory as a 32-bit address with an 8-bit extension. The XCP client extracts the addresses of signals and parameters of the model by parsing the debug information that the build process creates. The debug information is in DWARF or PDB format. The XCP client requests access to parameters and
signals by sending an XCP command that contains the arguments
When Use the #if defined(__MINGW32__) || defined(__MINGW64__) #define XCP_ADDRESS_GET(addressExtension, address) \ (uint8_T*) ((uintptr_t) address) #else #define XCP_ADDRESS_GET(addressExtension, address) \ (uint8_T*) ((address) + (uint8_T*)&__ImageBase) #endif addressExtension is 0. |
Set and copy memory | You can specify an optimized version of copy memory and set memory operations. If you do not define the #ifndef XCP_MEMCPY #define XCP_MEMCPY memcpy #endif #ifndef XCP_MEMSET #define XCP_MEMSET memset #endif |
Parsing command-line arguments | If your target hardware does not support the parsing of command-line
arguments, define the preprocessor macro
To replace
the set_param(modelName, 'OnTargetWaitForStart', 'on'); -DON_TARGET_WAIT_FOR_START=1 ) to the
compiler. |
Structure packing and alignment | The XCP software stack implementation requires the packing and alignment of some internal C structures. In the platform abstraction layer, provide packing and alignment information by using preprocessor directives that are compiler-specific. To pack and align C structures, provide these preprocessor directives: #define XCP_PRAGMA_PACK_BEGIN(n) #define XCP_PRAGMA_PACK_END() #define XCP_ATTRIBUTE_ALIGNED(n) #define XCP_ATTRIBUTE_PACKED XCP_PRAGMA_PACK_BEGIN(1) typedef struct XCP_ATTRIBUTE_PACKED XcpSetDaqListModeCmdPacketFrame { uint8_T PID; /* Packet identifier, always XCP_PID_SET_DAQ_LIST_MODE */ uint8_T mode; /* DAQ list mode (XCP DAQ Mode bit masks) */ uint16_T daqListId; /* DAQ list Id */ uint16_T eventId; /* Event Channel Id */ uint8_T prescaler; /* Transmission rate prescaler */ uint8_T priority; /* DAQ list priority (0xFF -> highest) */ } XcpSetDaqListModeCmdPacketFrame; XCP_PRAGMA_PACK_END() XCP_PRAGMA_PACK_BEGIN(XCP_MEM_ALIGNMENT) struct XCP_ATTRIBUTE_ALIGNED(XCP_MEM_ALIGNMENT) xcpFifoEntry { struct xcpFifoEntry *next; size_t msgFrameSize; /* in AG units */ }; XCP_PRAGMA_PACK_END() For a GCC compiler, use these directives: #define XCP_PRAGMA_PACK_BEGIN(n) #define XCP_PRAGMA_PACK_END() #define XCP_ATTRIBUTE_ALIGNED(n) __attribute__((aligned(n))) #define XCP_ATTRIBUTE_PACKED __attribute__((packed)) For a Microsoft® Visual C++® compiler, use these directives: #define PRAGMA(n) _Pragma(#n) #define XCP_PRAGMA_PACK_BEGIN(n) PRAGMA(pack(push, n)) #define XCP_PRAGMA_PACK_END() PRAGMA(pack(pop)) #define XCP_ATTRIBUTE_ALIGNED(n) #define XCP_ATTRIBUTE_PACKED |
Create Custom Abstraction Layer
To create a custom platform abstraction layer:
Specify the header file
xcp_platform_custom.h
. This Linux example defines the required functions.#ifndef XCP_PLATFORM_CUSTOM_H #define XCP_PLATFORM_CUSTOM_H /* XCP_ADDRESS_GET */ #include <stdint.h> #define XCP_ADDRESS_GET(addressExtension, address) (uint8_T*) ((uintptr_t) address) /* XCP_MUTEX */ #include <pthread.h> #define XCP_MUTEX_DEFINE(lock) pthread_mutex_t lock #define XCP_MUTEX_INIT(lock) pthread_mutex_init(&(lock), NULL) #define XCP_MUTEX_LOCK(lock) pthread_mutex_lock(&(lock)) #define XCP_MUTEX_UNLOCK(lock) pthread_mutex_unlock(&(lock)) /* XCP_SLEEP */ #include <sys/time.h> /* gettimeofday */ #if _POSIX_C_SOURCE >= 199309L #include <time.h> /* for nanosleep */ #else #include <stddef.h> #include <sys/select.h> /* for select */ #endif /* _POSIX_C_SOURCE >= 199309L */ #if _POSIX_C_SOURCE >= 199309L #define XCP_SLEEP(seconds,microseconds) do {struct timespec t;\ t.tv_sec = seconds; t.tv_nsec = microseconds * 1000; nanosleep(&t, NULL);} while(0) #else /* nanosleep is not available. Use select instead. */ #define XCP_SLEEP(seconds,microseconds) do {struct timeval t; t.tv_sec = seconds;\ t.tv_usec = microseconds; select(0, NULL, NULL, NULL, &t);} while(0) #endif /* _POSIX_C_SOURCE >= 199309L */ #endif
Register the header file:
If you use the
target
package for connectivity, use theBuildDependencies
property of thetarget.XCPPlatformAbstraction
class to specify the required information. See Customise Connectivity for XCP External Mode Simulations.If you do not use the
target
package for connectivity, define a post-code generation command:function myXCPTargetPostCodeGenCommand(buildInfo) buildInfo.addIncludePaths(customPlatformAbstractionLayerPath, 'OPTS'); buildInfo.addDefines('-DXCP_CUSTOM_PLATFORM', 'OPTS'); % Add my rtiostream buildInfo.addSourceFiles(customRtIOStreamFileName, ... customRtIOStreamSrcPath); % If the target hardware does not support parsing of command % line arguments buildInfo.addDefines('-DEXTMODE_DISABLE_ARGS_PROCESSING', 'OPTS'); end
See Also
extmodeBackgroundRun
| extmodeEvent
| extmodeGetFinalSimulationTime
| extmodeInit
| extmodeParseArgs
| extmodeReset
| extmodeSetFinalSimulationTime
| extmodeSimulationComplete
| extmodeStopRequested
| extmodeWaitForHostRequest
Related Topics
- External Mode Simulations for Parameter Tuning, Signal Monitoring, and Code Execution Profiling
- External Mode Simulation by Using XCP Communication
- Set Up External Mode Connectivity Between Simulink and Target Hardware