diff --git a/.github/workflows/build-ls-xcp.yml b/.github/workflows/build-ls-xcp.yml index 4033d25..770ae29 100644 --- a/.github/workflows/build-ls-xcp.yml +++ b/.github/workflows/build-ls-xcp.yml @@ -9,11 +9,24 @@ on: branches: [ main ] jobs: + lint-examples: + name: Validate examples + runs-on: ubuntu-20.04 + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install dependencies + run: python -m pip install lxml + - name: Validate examples + run: python lint.py + build-ls-xcp: name: Build Layered Standard XCP - runs-on: ubuntu-20.04 - steps: - name: checkout uses: actions/checkout@v3 diff --git a/docs/examples/fmi_ls_xcp_manifest_example.xml b/docs/examples/fmi_ls_xcp_manifest_example.xml index 41186d8..9e18815 100644 --- a/docs/examples/fmi_ls_xcp_manifest_example.xml +++ b/docs/examples/fmi_ls_xcp_manifest_example.xml @@ -2,9 +2,30 @@ \ No newline at end of file + xmlns:fmi-ls="http://fmi-standard.org/fmi-ls-manifest" + fmi-ls:fmi-ls-name="org.fmi-standard.fmi-ls-xcp" + fmi-ls:fmi-ls-version="1.0.0-rc.4" + fmi-ls:fmi-ls-description="Layered standard based on FMI 2.0 and FMI 3.0 for describing and implementing XCP support for FMUs, which can either provide an XCP service or allow direct memory access via A2L files."> + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index.adoc b/docs/index.adoc index a79385a..f574ad6 100644 --- a/docs/index.adoc +++ b/docs/index.adoc @@ -70,21 +70,21 @@ Conventions used in this document: There are alternative implementations depending on the use case and data availability: - . The FMU implements an XCP slave which provides access to measurement and calibration variables of the virtual ECU and handles the communication protocol with the XCP master in the MCD tool. - The necessary information for an MCD tool is given in a description file which follows the https://www.asam.net/standards/detail/mcd-2-mc/[ASAM MCD-2 MC] standard (aka A2L, also <>) and customarily carries the file extension `.a2l`. + . The FMU implements one or more XCP slaves which provide access to measurement and calibration variables of the virtual ECU and handles the communication protocol with the XCP master in the MCD tool. + The necessary information for an MCD tool is given in one or more variable description files which follow the https://www.asam.net/standards/detail/mcd-2-mc/[ASAM MCD-2 MC] standard (aka A2L, also <>) and customarily carry the file extension `.a2l`. For further details see <>. . An external XCP slave implementation accesses the memory of the virtual ECU to expose the XCP protocol to the MCD tool. - In this case, the importer needs to provide such an XCP slave implementation using the A2L description file. + In this case, the importer needs to provide such an XCP slave implementation using the A2L variable description file(s) provided by the FMU. `fmi3IntermediateUpdateCallback` calls or the clocks mechanism could be used to synchronize DAQ lists. For further details see <>. -It is also possible for an FMU to have an integrated XCP service and allow memory access for an external XCP service. +It is also possible for an FMU to have integrated XCP services and to allow memory access for an external XCP service. The importer might also use the A2L address, type, layout and scaling information to use direct memory access into the virtual ECU. As this approach does not use the standardized XCP protocol it is not further described in this layered standard. This layered standard will have no effect on the FMU interface, nor the C-API behavior. -If the XCP slave is implemented inside the FMU, it is recommended that it runs in its own thread and leaves the rest of the operation of the FMU unaffected. +If an XCP slave is implemented inside the FMU, it is recommended that it runs in its own thread and leaves the rest of the operation of the FMU unaffected. The A2L/XCP standards allow to measure and calibrate variables synchronously to different types of events. These so called event channels are either time-based, angular-based, or non-deterministic, and are identified by a unique event channel number (aka measurement raster). @@ -93,15 +93,15 @@ Calibration and communication with the XCP master is typically performed in a ba The background thread must always be responsive to the XCP master within the defined communication timeout. Refer to the A2L/XCP standards for more information. -The XCP/A2L approach can not only be used for virtual ECUs, but also for plant models, if the FMU exporter generates an appropriate A2L file. +The XCP/A2L approach can not only be used for virtual ECUs, but also for plant models, if the FMU exporter generates appropriate A2L files. [#common-concepts] == Layered Standard Manifest File -This layered standard defines additional capability flags in the layered standard manifest file. -<> shows the content of `fmi-ls-manifest.xml`. +This layered standard defines additional elements that carry relevant interface definitions and capability flags in the layered standard manifest file. +<> shows the attributes of the root element of `fmi-ls-manifest.xml`. -.Attribute Details. +.Root Element Attribute Details. [[table-schema-fmi-ls-xcp-attributes]] [cols="1,1,1,2",options="header"] |==== @@ -125,22 +125,91 @@ This layered standard defines additional capability flags in the layered standar | `Layered standard based on FMI 2.0 and FMI 3.0 for describing and implementing XCP support for FMUs, which can either provide an XCP service or allow direct memory access via A2L files.` | String with a brief description of the layered standard that is suitable for display to users. -|`containsXcpService` +|==== + +The root element must contain at least one, and can contain more than one `Interface` elements. +Each such element specifies one set of interface information for calibration using one underlying variable description file (A2L). +Multiple elements might be provided if there are different XCP slaves embedded in the FMU, or there are other reasons why multiple A2L variable description files that apply in parallel have to be provided. + +Each `Interface` element has the <>: + +.Interface Element Attribute Details. +[[table-schema-fmi-ls-xcp-interface-attributes]] +[cols="1,1,1,2",options="header"] +|==== +|Attribute +|Namespace +|Value +|Description + +|`definition` +| +| Relative URI +| This attribute must be a relative reference to a URI (formerly called a relative URI) to the A2L variable description file for this interface. +It may not contain any dot segments, that is, complete path segments consiting only of `.` or `..`. +It is resolved to an absolute URI using a base URI that depends on the relevant FMU target, as defined in <>. + +|`types` +| +| List of `CoSimulation`, `ModelExchange`, `ScheduledExecution`, separated by a whitespace character +| Optional attribute to restrict the applicability of the interface being defined to certain FMU interface types. +The value is provided as a list of interface type names to which this interface applies. +If the attribute is not provided, the interface applies to all available FMU interface types. + +|`description` +| +| String +| Optional human-readable description of the interface being defined. + +|`containsXCPService` | | `true` or `false` | If `true`, the FMU provides its own XCP slave implementation. See <>. +Defaults to `false`. -|`supportsDirectMemoryAccessViaA2L` +|`supportsDirectMemoryAccess` | | `true` or `false` -| If `true`, the FMU allows direct memory access from the outside via its A2L file. +| If `true`, the FMU allows direct memory access from the outside via the information provided in its variable description file. In most cases this mechanism will be used by an external XCP service provided by the importer. See <>. +Defaults to `false`. + +|==== + +The attribute `definition` is required, all other attributes of `Interface` are optional. +The FMU must provide a valid `definition` attribute and must set at least one of the attributes `containsXCPService` or `supportsDirectMemoryAccess` to `true` to comply with this layered standard. + +Additionally the `Interface` element can contain one or more `Variable` elements, which assign relevant roles to existing FMU variables. +Each `Variable` element has the <>: + +.Variable Element Attribute Details. +[[table-schema-fmi-ls-xcp-variable-attributes]] +[cols="1,1,1,2",options="header"] |==== +|Attribute +|Namespace +|Value +|Description -The FMU must set at least one of the attributes `containsXcpService` or `supportsDirectMemoryAccessViaA2L` to `true` to comply with this layered standard. +|`name` +| +| Valid variable name +| Name of a variable defined in the `modelDescription.xml` of the FMU. + +|`role` +| +| Valid role enum value +| Role of the variable. Must be a valid role as defined in <>. + +|==== + +Each `Variable` entry assigns a role to an existing variable. +No variable shall occur in more than one `Variable` entry. +No role shall occur in more than one `Variable` entry of one `Interface`, but can occur again in `Variable` entries of a different `Interface`. +The set of allowed roles and their meaning is defined <>. An example of a manifest file for this layered standard is shown below: @@ -157,7 +226,7 @@ The definitions that are specific to the particular implementation types are def === Structure of the FMU Archive -A2L description files and other files needed for XCP support are placed in `/extra/org.fmi-standard.fmi-ls-xcp`. +The manifest file, any A2L variable description files and other files needed for XCP support are placed in `/extra/org.fmi-standard.fmi-ls-xcp`. _[This allows these files to be added and modified after the FMU has been created without affecting any checksums.]_ The directory structure is analogous to the `binaries` directory structure, specific to the FMI version. The structure for an FMI 3.0 FMU is shown below. @@ -169,17 +238,32 @@ documentation fmi-ls-xcp.{txt|html} // Informal description how to use XCP/A2L for this FMU (optional). extra/org.fmi-standard.fmi-ls-xcp // Contains files related to XCP/A2L fmi-ls-manifest.xml // The layered standard manifest file - .a2l // Variable description of a source code FMU (optional) + // Variable description of a source code FMU (optional) + // Variable description of a source code FMU (optional) + ... x86_64-windows - .a2l // Variable description for Windows on Intel 64-bit (optional) + // Variable description for Windows on Intel 64-bit (optional) + // Variable description for Windows on Intel 64-bit (optional) + ... x86-linux - .a2l // Variable description for Linux on Intel 32-bit (optional) + // Variable description for Linux on Intel 32-bit (optional) + ... aarch32-linux - .a2l // Variable description for Linux on ARM 32-bit (optional) + // Variable description for Linux on ARM 32-bit (optional) + ... x86_64-darwin - .a2l // Variable description for macOS (optional) + // Variable description for macOS (optional) + ... ---- +The `` and `` above are the relative URI references of the corresponding `definition` attributes of `Interface` elements. +The resultant absolute URI to the variable description file results from resolving the relative URI against the following base URI: + +* For a source code FMU target the base URI is the URI of the manifest file. +* For a binary FMU target the base URI is the URI that results by replacing the file name part of the URI of the manifest file with a directory path component with the given target name of the relevant FMI version. + +If multiple `Interface` elements are present in the manifest, then multiple A2L variable description files will be present at each level of the directory structure, as defined by their `definition` attribute values. + === Documentation When shipping an FMU with XCP/A2L support, it is recommended to provide the necessary information to the importer in the file `documentation/fmi-ls-xcp.{txt|html}`. @@ -197,7 +281,8 @@ ____ The A2L description depends on the FMU binary, for example, regarding memory addresses, and byte order. If an FMU archive contains multiple binaries for different platforms, the associated A2L files are placed into separate subdirectories below `/extra/org.fmi-standard.fmi-ls-xcp` following the same scheme as in the `binaries` directory, see <>. -It is highly advisable that all A2L files in the FMU use the same XCP configuration, i.e., the same protocol (TCP/UDP), the same ports, and so on. + +All A2L files in the FMU should use the same XCP configuration, including the same protocol (TCP/UDP), ports, etc. Note that the A2L files placed under the `extra` directory are not accessible to the FMU at runtime. Any files that shall be accessible to the FMU at runtime must (also) be placed into the `resources` directory as defined by the FMI standard. @@ -205,8 +290,6 @@ Any files that shall be accessible to the FMU at runtime must (also) be placed i A2L files may have a considerable size. If size is a concern, it may be decided to supply just a single platform and A2L file with an FMU. -The root name of the A2L file shall be identical to the model identifier and is case sensitive, i.e., a variable description named `.a2l` is associated with an FMU binary named `.{dll|so}`. - All format versions of the A2L standard are allowed and it is the responsibility of the MCD tool to handle each format version correctly. This layered standard forbids the use of the `including mechanism` of additional A2L files to simplify complete extraction and copying of the A2L file to a location where it is accessible by the MCD tool. @@ -219,7 +302,8 @@ See <> and <>, respect The A2L description shall include `IF_DATA XCP` elements to help MCD tools to connect and interact with the XCP service of the FMU more reliably and without user interaction. Parts of the `IF_DATA XCP` description depend on the machine where the FMU binary is executed, for example, the IP address and port. -The default IP address assigned by the FMU exporter should be `localhost`, i.e., `127.0.0.1`, which fits in many cases. +The default IP address assigned by the FMU exporter should be a `localhost` IP address, that is one of the loopback interface IP addresses (`127.0.0.1` for IPv4 or `::1` for IPv6), as this is the most fitting choice in many cases. + The requirement for the port number is, that it must be unique on the machine where the FMU binary is executed. Typically, a certain range of ports is reserved for this purpose. The FMU importer is responsible for checking if any conflicts of the defined IP addresses and port numbers occur in the context of the simulated system. @@ -254,7 +338,7 @@ This standard expressly does not restrict the relationship between both sets of _[As a matter of fact, it is quite likely that the variables published in `modelDescription.xml` is a minimal set required for connectivity reasons._ _The A2L file might publish a much larger set of variables and parameters that the user can selectively choose to measure or calibrate._ -_From the viewpoint of an MCD tool, the details of the variable access are transparent, i.e., this information is encapsulated in the A2L file.]_ +_The details of the variable access are transparent from the viewpoint of an MCD tool, as this information is encapsulated in the A2L file.]_ === Numeric Effects of XCP Access @@ -273,7 +357,7 @@ _Appropriate care must be taken when to serve XCP master requests to ensure simu If the XCP slave is implemented in the FMU, the FMU is responsible for handling the communication protocol with the XCP master. The following sections describe how to configure and handle the internal XCP slave. -The FMU states that it contains an internal XCP slave implementation with the `containsXcpService` attribute in the `fmi-ls-manifest.xml` file. +The FMU states that it contains an internal XCP slave implementation with the `containsXCPService` attribute in the `fmi-ls-manifest.xml` file. _[<> shows a typical design where the XCP slave (in the FMU) communicates with the XCP master (in the MCD tool) using a separate network channel, e.g., the IP stack of the host OS._ _Thus, the communication of the XCP service is not mixed with the simulated network communication of the ECU wrapped in the FMU._ @@ -306,67 +390,87 @@ _Note that blocking OS calls should be avoided, because they may have an effect To avoid collisions in a simulation system with several XCP services, it can be necessary for the FMU importer to override the default port number the FMU listens on, which was assigned by the FMU exporter in the XCP slave implementation and in the A2L file (see <>). Besides the listen port number, the user may also want to change or restrict the listen IP address, which is the IP address of the network interface to which the socket of the XCP service is bound and where it is listening for XCP client commands. -In most cases, the listen IP address will be set to `INADDR_ANY`, i.e., `0.0.0.0`, allowing connections from any available network interface. -However, it is possible to restrict the XCP service to, e.g., only allow local connections by setting the listen IP address to `127.0.0.1`. +In many cases, the listen IP address will be set to `INADDR_ANY` (`0.0.0.0` for IPv4, `::` for IPv6), allowing connections from any available network interface. +However, it is possible to restrict the XCP service to listen only on a single interface. +This is commonly done with the loopback addresses (`127.0.0.1` for IPv4 and `::1` for IPv6), to only allow local connections. Furthermore, it is likely valuable for the user to have the possibility to deactivate the internal XCP service to avoid certain problems with the environment, e.g., with anti-virus software or firewalls or when running the FMU in a container. The importer might also want to use an external XCP service even when an internal XCP service is available. -Therefore, if the XCP slave is embedded in the virtual ECU, the FMU should expose the following variables with pre-defined names in the `modelDescription.xml` file, which are used to configure the embedded XCP slave (see <>): - -.XCP Configuration Variables -[#figure-xcp-configuration-parameters] ----- - org.fmi_standard.fmi_ls_xcp.EnableXcpOnTcpIp - Description: "Determines whether the TCP instance of the XCP service provided - by the FMU shall be started." - Type: Boolean - Example Start Value: "true" - Requirement Type: Should be supplied, if the FMU provides an XCP service using TCP - If not present: Defaults to true, i.e. if the XCP slave supports TCP it will be started. - - org.fmi_standard.fmi_ls_xcp.EnableXcpOnUdpIp - Description: "Determines whether the UDP instance of the XCP service provided - by the FMU shall be started." - Type: Boolean - Example Start Value: "false" - Requirement Type: Should be supplied, if the FMU provides an XCP service using UDP - If not present: Defaults to true, i.e. if the XCP slave supports UDP it will be started. - - org.fmi_standard.fmi_ls_xcp.TcpListenPortNumber - Description: "TCP port number where the XCP slave listens for XCP protocol commands." - Type: UInt16/Integer - Example Start Value: - Requirement Type: Should be supplied, if the FMU provides an XCP service using TCP - If not present: Defaults to the protocol data values found in the relevant A2L file. - - org.fmi_standard.fmi_ls_xcp.UdpListenPortNumber - Description: "UDP port number where the XCP slave listens for XCP protocol commands." - Type: UInt16/Integer - Example Start Value: - Requirement Type: Should be supplied, if the FMU provides an XCP service using UDP - If not present: Defaults to the protocol data values found in the relevant A2L file. - - org.fmi_standard.fmi_ls_xcp.TcpListenIpAddress - Description: "TCP IP address where the XCP slave listens for XCP protocol commands." - Type: String - Example Start Value: "0.0.0.0" - Requirement Type: Should be supplied, if the FMU provides an XCP service using TCP - If not present: Defaults to the protocol data values found in the relevant A2L file. - - org.fmi_standard.fmi_ls_xcp.UdpListenIpAddress - Description: "UDP IP address where the XCP slave listens for XCP protocol commands." - Type: String - Example Start Value: "0.0.0.0" - Requirement Type: Should be supplied, if the FMU provides an XCP service using UDP - If not present: Defaults to the protocol data values found in the relevant A2L file. ----- +Therefore, if the XCP slave is embedded in the virtual ECU, the FMU should expose the following configuration capabilities as variables in the `modelDescription.xml` file, which are used to configure the embedded XCP slave (see <>). +The variable that is provided for a capability is identified by providing a `Variable` element in the relevant `Interface` element of the manifest file, with the name of the variable and its role as the corresponding attribute values. + +Enable XCP over TCP:: Determines whether the TCP instance of the XCP service provided by the FMU shall be started. ++ +[cols="1h,4"] +|=== +|Role |`XCPServiceTCPEnable` +|Type |`Boolean` +|Example Start Value |`true` +|Requirement Type |Should be supplied, if the FMU provides an XCP service using TCP. +|If not present |Defaults to `true`, so if the XCP slave supports TCP, it will be started. +|=== + +TCP listen port number:: TCP port number where the XCP slave listens for XCP protocol commands. ++ +[cols="1h,4"] +|=== +|Role |`XCPServiceTCPPort` +|Type |`UInt16` / `Integer` +|Example Start Value |In an agreed range of ports, e.g., `32768` to `39999`. +|Requirement Type |Should be supplied, if the FMU provides an XCP service using TCP. +|If not present |Defaults to the protocol data values found in the relevant A2L file. +|=== + +TCP listen IP address:: IP address where the XCP slave listens for XCP protocol commands over TCP. ++ +[cols="1h,4"] +|=== +|Role |`XCPServiceTCPListenAddress` +|Type |`String` +|Example Start Value |`0.0.0.0` or `::0` +|Requirement Type |Should be supplied, if the FMU provides an XCP service using TCP. +|If not present |Defaults to the protocol data values found in the relevant A2L file. +|=== + +Enable XCP over UDP:: Determines whether the UDP instance of the XCP service provided by the FMU shall be started. ++ +[cols="1h,4"] +|=== +|Role |`XCPServiceUDPEnable` +|Type |`Boolean` +|Example Start Value |`false` +|Requirement Type |Should be supplied, if the FMU provides an XCP service using UDP. +|If not present |Defaults to `true`, so if the XCP slave supports UDP, it will be started. +|=== + +UDP listen port number:: UDP port number where the XCP slave listens for XCP protocol commands. ++ +[cols="1h,4"] +|=== +|Role |`XCPServiceUDPPort` +|Type |`UInt16` / `Integer` +|Example Start Value |In an agreed range of ports, e.g., `32768` to `39999`. +|Requirement Type |Should be supplied, if the FMU provides an XCP service using UDP. +|If not present |Defaults to the protocol data values found in the relevant A2L file. +|=== + +UDP listen IP address:: IP address where the XCP slave listens for XCP protocol commands over UDP. ++ +[cols="1h,4"] +|=== +|Capability Attribute |`XCPServiceUDPListenAddress` +|Type |`String` +|Example Start Value |`0.0.0.0` or `::0` +|Requirement Type |Should be supplied, if the FMU provides an XCP service using UDP. +|If not present |Defaults to the protocol data values found in the relevant A2L file. +|=== All variables that are defined must be defined as scalars with one of the following `causality`/`variability` combinations: * **fixed structuralParameter (FMI 3.0 only):** If the FMU defines the variables as `structuralParameters`, the XCP configuration can be changed during `Configuration Mode`. -When the XCP service is started in `fmi3ExitConfigurationMode`, it is configured and running before the simulation starts, i.e., before `Initialization Mode` is entered. +When the XCP service is started in `fmi3ExitConfigurationMode`, it is configured and running before the simulation starts, specifically before `Initialization Mode` is entered. For FMI 3.0, this is the most flexible variant and should be preferred over the other variants. * **fixed parameter:** @@ -397,29 +501,29 @@ The configuration variables are duplicated for both transport layers, TCP and UD The FMU shall only provide the corresponding variables for the protocols it supports. Without knowing the concrete XCP slave implementation the importer cannot know if the different protocols can be used in parallel or only exclusively. -In case the XCP service is not multi-session capable and both of the variables `org.fmi_standard.fmi_ls_xcp.EnableXcpOn[Tcp|Udp]Ip` are set to `true`, the FMU must return an error and provide a meaningful error message when exiting `Configuration Mode`. +In case the XCP service is not multi-session capable and both of the variables with role `XCPServiceTCPEnable` and `XCPServiceUDPEnable` are set to `true`, the FMU must return an error and provide a meaningful error message when exiting `Configuration Mode`. This information may also be provided in the `documentation` directory inside the FMU. -The importer of an FMU is responsible for keeping all occurrences of the port number consistent, i.e., in both the FMU configuration and in the A2L file. +The importer of an FMU is responsible for keeping all occurrences of the port number consistent, including both the FMU configuration and the A2L file that is presented to the MCD tool. [#starting-internal-xcp-service] === Starting and Stopping the XCP Service Since an XCP slave is implemented inside the FMU, the FMU is responsible for starting and stopping the internal XCP service. -*Using FMI 3.0*, the FMU should preferably expose its XCP configuration variables (see <>) as `structuralParameters` and start the XCP service during the first invocation of `fmi3ExitConfigurationMode` and shut it down during `fmi3Terminate`, if the FMU has no explicit power-up signal to simplify user interactions between simulator and MCD tool. +*Using FMI 3.0*, the FMU should preferably expose its XCP configuration variables (see <>) as `structuralParameters` and start the XCP service during the first invocation of `fmi3ExitConfigurationMode` and shut it down during `fmi3Terminate`, if the FMU has no explicit power-up signal to simplify user interactions between simulator and MCD tool. If the FMU contains a virtual ECU with power-up control (K15), all built-in OS and Basic Software services (including XCP) should follow the normal power-up protocol. -If the simulator puts the FMU in `Configuration Mode` and sets the structural parameters `org.fmi_standard.fmi_ls_xcp.[Tcp|Udp]ListenIpAddress` and `org.fmi_standard.fmi_ls_xcp.[Tcp|Udp]ListenPortNumber`, the XCP slave shall use those parameters to set up the communication connection for the XCP protocol. +If the simulator puts the FMU in `Configuration Mode` and sets the structural parameters with role `XCPService{TCP|UDP}ListenAddress` and `XCPService{TCP|UDP}Port`, the XCP slave shall use those parameters to set up the communication connection for the XCP protocol. -If the value of structural parameter `org.fmi_standard.fmi_ls_xcp.EnableXcpOn[Tcp|Udp]Ip` is `true`, the XCP slave must be responsive for XCP commands on the corresponding channel (TCP/UDP) after leaving `Configuration Mode`. +If the value of structural parameter with role `XCPService{TCP|UDP}Enable` is `true`, the XCP slave must be responsive for XCP commands on the corresponding channel (TCP/UDP) after leaving `Configuration Mode`. Thus, it is possible for the XCP master to perform calibration during the `Instantiated` state, for example, to set parameters before entering `Initialization Mode`. Note that reading values of calculated variables, which depend on an initialization function, is only possible after entering the `Initialized` super state with `fmi3ExitInitializationMode`. -If `org.fmi_standard.fmi_ls_xcp.EnableXcpOn[Tcp|Udp]Ip` is `false`, the internal XCP service must not be started with TCP/UDP, the network resources must not be used and no XCP service actions must be performed by the FMU on this channel during simulation. +If the variable with role `XCPService{TCP|UDP}Enable` is `false`, the internal XCP service must not be started with TCP/UDP, the network resources must not be used and no XCP service actions must be performed by the FMU on this channel during simulation. If both parameters are `false` the XCP service must not be started at all. -If `Configuration Mode` was not entered and the value of variable `org.fmi_standard.fmi_ls_xcp.EnableXcpOn[Tcp|Udp]Ip` is `true`, the FMU must start the XCP service in `fmi3EnterInitializationMode` at the latest. +If `Configuration Mode` was not entered and the value of variable with role `XCPService{TCP|UDP}Enable` is `true`, the FMU must start the XCP service in `fmi3EnterInitializationMode` at the latest. In this case, it is not possible to perform calibration before `Initialization Mode` is entered or to configure the XCP connection settings. If the importer re-enters `Configuration Mode` and reconfigures the parameters it is up to the FMU if it reacts to the parameter change or not. @@ -428,9 +532,10 @@ If the importer re-enters `Configuration Mode` and reconfigures the parameters i The importer is responsible for calling `fmi2SetupExperiment` at least once and setting the parameters before `fmi2SetupExperiment` is called. If the FMU does not expose its XCP configuration variables as `structuralParameters` using FMI 3.0, or as `parameters` using FMI 2.0, the importer will not have control over whether the internal XCP service should be started. -In this case, the default value of the `start` attribute of variable `org.fmi_standard.fmi_ls_xcp.EnableXcpOn[Tcp|Udp]Ip` determines if the XCP service is started. +In this case, the default value of the `start` attribute of the variable with role `XCPService{TCP|UDP}Enable`, if it exists, determines if the XCP service is started. +If no variable of this role exists, then the XCP service is always started. -_[Note that it is not possible to manually change the `start` value for `org.fmi_standard.fmi_ls_xcp.EnableXcpOn[Tcp|Udp]Ip` in the `modelDescription.xml` file to change the behavior of the internal XCP service._ +_[Note that it is not possible to manually change the `start` value for any variable in the `modelDescription.xml` file to change the behavior of the internal XCP service._ _The `start` value merely reflects the default behavior coded into the FMU.]_ [#address-resolution-internal] @@ -438,23 +543,23 @@ _The `start` value merely reflects the default behavior coded into the FMU.]_ Dependent on the FMU format and the XCP slave implementation inside the FMU, dealing with memory addresses of variables in the A2L file differs. -If the FMU is in binary format, i.e., it is shipped with a shared library, the FMU exporter must provide values for the ECU addresses inside the A2L file and the XCP slave inside the FMU is responsible for resolving the physical addresses from the address field values. +If the FMU is in binary format, that is, it is shipped with a shared library, the FMU exporter must provide values for the ECU addresses inside the A2L file, and the XCP slave inside the FMU is responsible for resolving the physical addresses from the address field values. _[These address field values can be either real addresses or fixed target-independent indices that are used by the XCP slave implementation for getting variables during runtime.]_ -If the FMU is only shipped with source code, it is not possible to determine the memory addresses before building the binary, i.e., real addresses cannot be provided by the exporter in the A2L file. +If the FMU is only shipped with source code, the memory addresses cannot be determined before building the binary, so the exporter cannot provide real addresses in the A2L file. In this case the address field values in the A2L file must be either fixed target-independent indices, which allow the FMU to resolve the addresses at runtime, or the A2L file only contains linker symbol links (`SYMBOL_LINK`). In the latter case, the importer or an external A2L tool is responsible for determining the actual variable addresses from the symbol links. These addresses must be relative to the base address of the built FMU binary. Refer to the https://www.asam.net/standards/detail/mcd-2-mc/[ASAM MCD-2 MC] standard for more information on symbol links and automatic address update. -If the FMU exporter does not use real (offset) addresses in the A2L file in the binary FMU case, or does not provide symbol links in the source code FMU case, attribute `supportsDirectMemoryAccessViaA2L` in the `fmi-ls-manifest.xml` file must be set to `false` (see <>). +If the FMU exporter does not use real (offset) addresses in the A2L file in the binary FMU case, or does not provide symbol links in the source code FMU case, attribute `supportsDirectMemoryAccess` in the `fmi-ls-manifest.xml` file must be set to `false` (see <>). == External XCP Service -An FMU might support XCP but does not bring along its own XCP slave implementation (attribute `containsXcpService = false` in the `fmi-ls-manifest.xml` file). +An FMU might support XCP but does not bring along its own XCP slave implementation (attribute `containsXCPService = false` in the corresponding `Interface` element of the `fmi-ls-manifest.xml` file). In this case the FMU importer must provide its own implementation of an XCP slave. -It is also possible that the FMU does contain an internal XCP slave implementation but additionally allows the importer to access the memory of the virtual ECU with an external XCP service (attribute `supportsDirectMemoryAccessViaA2L = true`). +It is also possible that the FMU does contain an internal XCP slave implementation but additionally allows the importer to access the memory of the virtual ECU with an external XCP service (attribute `supportsDirectMemoryAccess = true`). In this case it is the choice of the importer whether to use the FMU internal XCP slave or its own implementation. See <> on how to deactivate the internal XCP service. @@ -515,7 +620,8 @@ Therefore, this constellation is not applicable to this layered standard and the Limitations for binary FMUs: -* Normally only variables in the memory segments owned by the main FMU binary `.{dll|so}` are accessible by the XCP service, i.e., variables defined in source code modules and in statically linked libraries. +* Normally only variables in the memory segments owned by the main FMU binary `.{dll|so}` are accessible by the XCP service. +This usually encompasses variables defined in source code modules and in statically linked libraries. Accessing variables in the memory of indirectly loaded dynamic libraries requires a special implementation which is out-of-scope for this layered standard. == Contributions diff --git a/lint.py b/lint.py new file mode 100644 index 0000000..9ead416 --- /dev/null +++ b/lint.py @@ -0,0 +1,34 @@ +# validate the XML examples against the XSD schema + +from lxml import etree +from pathlib import Path +import urllib.request + + +repo_root = Path(__file__).parent + +fmi_ls_schema_url = 'https://raw.githubusercontent.com/modelica/fmi-standard/v3.0.1/schema/fmi3LayeredStandardManifest.xsd' + +# download the FMI Layered Standard Manifest schema +urllib.request.urlretrieve(fmi_ls_schema_url, repo_root / 'schema' / 'fmi3LayeredStandardManifest.xsd') + +xcp_schema_file = repo_root / 'schema' / 'fmi3LayeredStandardXcpManifest.xsd' + +with open(xcp_schema_file) as f: + s = f.read() + +# use a local path for the referenced FMI LS schema, so we can load it with lxml +s = s.replace( + 'https://raw.githubusercontent.com/modelica/fmi-standard/v3.0.1/schema/fmi3LayeredStandardManifest.xsd', + 'fmi3LayeredStandardManifest.xsd' +) + +with open(xcp_schema_file, 'w') as f: + f.write(s) + +xcp_schema = etree.XMLSchema(file=xcp_schema_file) + +for filename in (repo_root / 'docs' / 'examples').glob('*.xml'): + print(f"Validating {filename}") + tree = etree.parse(repo_root / 'docs' / 'examples' / 'fmi_ls_xcp_manifest_example.xml') + assert xcp_schema.validate(tree.getroot()) diff --git a/schema/fmi3LayeredStandardXcpManifest.xsd b/schema/fmi3LayeredStandardXcpManifest.xsd index a3c33e7..fbdd686 100644 --- a/schema/fmi3LayeredStandardXcpManifest.xsd +++ b/schema/fmi3LayeredStandardXcpManifest.xsd @@ -1,10 +1,10 @@ - + Copyright(c) 2023-2024 Modelica Association Project FMI. - All rights reserved. + All rights reserved. This file is licensed by the copyright holders under the 2-Clause BSD License (https://opensource.org/licenses/BSD-2-Clause): @@ -32,27 +32,105 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- - + + + + + + + + + + + Name of the variable. Must be a valid variable name as defined in the modelDescription.xml + of the FMU. + + + + + + + Role of the variable. Must be a valid role as defined in the enumeration and the specification. + + + + + + + + + + + + + + + + + + + + Optional human-readable description of the interface being defined. + + + + + + + Optional attribute to restrict the applicability of the interface being defined to certain + FMU interface types. The value is provided as a list of interface type names to which this + interface applies. If the attribute is not provided, the interface applies to all available + FMU interface types. + + + + + + + + + + + + + + + + + + This attribute must be a relative reference to a URI (formerly called a relative URI) to the A2L + definition file for this interface. It may not contain any dot-segments (i.e., complete path segments + of `.` or `..`). It is resolved to an absolute URI using a base URI as follows: + For any source FMU implementation this is resolved against the manifest file as the base URI, + for binary FMU implementations this is resolved against the corresponding target sub-directory + of the layered standard `extra` directory as the base URI. + + + + + + + If true, this interface of the FMU provides its own XCP slave implementation. + + + + + + + If true, this interface of the FMU allows direct memory access from the outside via its definition file. + In most cases this mechanism will be used by an external XCP service provided by the importer. + + + + + + - - - - If true, the FMU provides its own XCP slave implementation. - - - - - - - If true, the FMU allows direct memory access from the outside via its A2L file. In most cases this mechanism will be used by an external XCP service provided by the importer. - - -