Main Content

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.

  • For some support packages.

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.

StageFunctionPurpose

INITIALIZE

extmodeParseArgs

Extract external mode command-line arguments.

modelName_initialize

Initialize generated Simulink model code.

extmodeInit

Initialize external mode target connectivity.

HOST START REQUEST

extmodeWaitForHostRequest

Wait for a start request from development computer, which is created when you click Run button.

RUN

modelName_step

Run single step of generated Simulink model code.

extmodeEvent

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.

extmodeBackgroundRun

Transmit and receive packet from physical communication interface and process packet content in accordance with selected communication protocol.

HOST STOP REQUEST OR SIMULATION COMPLETE

extmodeStopRequested

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.

extmodeSimulationComplete

Check whether execution of generated model code is complete.
RESET

modelName_terminate

Terminate generated Simulink model code.

extmodeReset

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
In an external mode simulation, the build process automatically adds the required files to the build information object.

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
In an external mode simulation, the build process automatically adds the required files to the build information object.

XCP Platform Abstraction Layer

The XCP platform abstraction layer provides:

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.c

  • matlabroot\toolbox\coder\rtiostream\src\rtiostreamserial\rtiostream_serial.c

For details on implementing and testing an rtiostream communications channel, see:

To provide rtiostream information:

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'};
See Customise Connectivity for XCP External Mode Simulations.

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.

FunctionalityDetails

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 XCP_PRINTF preprocessor macro, the default implementation is empty.

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 addressExtension and address.

When addressExtension and address information is received by the target hardware, the XCP server must convert the address to the location of the variable in the target hardware memory. The variable location is assigned by the loader and is target-specific.

Use the XCP_ADDRESS_GET() macro to specify the conversion logic. The default implementation for Linux and Windows systems is:

#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
Currently, only 32-bit hardware architectures are supported, so 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 XCP_MEMCPY and XCP_MEMSET preprocessor macros, the default implementation specifies the standard C functions, memcpy and memset.

#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 EXTMODE_DISABLE_ARGS_PROCESSING.

To replace the -w option, you can use this command to specify that the target application enters and stays in a wait state until it receives a Connect message from Simulink:

set_param(modelName, 'OnTargetWaitForStart', 'on');
The build process provides the required option (-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
For example:
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:

  1. 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
    

  2. Register the header file:

    • If you use the target package for connectivity, use the BuildDependencies property of the target.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

| | | | | | | | |

Related Topics

External Websites