From 3a670a27c247d054419749b22477a321974867bf Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Wed, 15 Nov 2023 17:41:02 +0100 Subject: [PATCH 01/15] Create further content --- ls-bus-guide/4____network_abstraction.adoc | 315 +++++++++++++++++++-- 1 file changed, 286 insertions(+), 29 deletions(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index 38abd66..07a3b4f 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -1,43 +1,300 @@ == Network Abstraction ("low cut") This chapter contains details on common topics of the network abstraction layer. -=== Differences between System Compositions -The principles of communication is closely linked with the introduced System Compositions. -Within the `Direct Communication` use case in combination with network abstraction, exactly two FMUs communicate with each other. -No Bus Simulation is required. -<<#figure-example-network-simulation-direct>> illustrates this communication, whereby FMU 1 transmits network data to FMU 2.After that, the transmission is directly confirmed by FMU 1 itself, whereby FMU 1 handles that self confirmation internally. +=== CAN, CAN FD, CAN XL +This chapter contains details on CAN, CAN FD, CAN XL specific topics. -.Direct communication between two FMUs. -[#figure-example-network-simulation-direct] -image::principles_of_communication_direct.svg[width=40%, align="center"] +==== Getting Started with CAN, CAN FD and CAN XL +This section shows the exemplary implementation in conjunction with the provided header files of the fmi-ls-bus layered standard. -Within `Composition with dedicated Bus Simulation FMU` and `Importer with Integrated Bus Simulation` communication case there exists always a Bus Simulation and two or more FMUs can be connected for communication. -Bus connections between FMUs are then redirected via the Bus Simulation (FMU). -This means that the bus simulation model sets the level of accuracy and feature support for the respective bus type. +===== Provided Header Files +The layered standard fmi-ls-bus not only contains a textual specification for bus support, but also provides header and utility functions as C code to make creation and use within FMUs as easy as possible. +The following header files are provided by the standard for this purpose, although their use is not mandatory but optional: -<<#figure-example-network-simulation-complex>> shows the communication of two FMUs which are connected via a Bus Simulation. -All in all FMU 1 transmits network data to FMU 2. -First FMU 1 commits the baud rate to the Bus Simulation. -This information can be used for timing calculations during the transmission of a message. -In a second operation FMU 1 transmits network data to the Bus Simulation. -Inside the Bus Simulation a calculation of the transmission time for the specified network data is done. -After this the Bus Simulation transmits the network data to FMU 2 and confirms the successful transmission to FMU 1. +* https://github.com/modelica/fmi-ls-bus/blob/main/headers/fmi3LsBus.h[fmi3LsBus.h] provides general functions and structures. +These header file applies to all supported bus types of the layered standard. +* https://github.com/modelica/fmi-ls-bus/blob/main/headers/fmi3LsBusCan.h[fmi3LsBusCan.h] provides functions and structures explicit for CAN, CAN FD and CAN XL. +Primarily, structures are included here that allow the operations specified by the layered standard to be easily created and used. +* https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtil.h[fmi3LsBusUtil.h] provides common utility functions and structures for all supported bus types. +* https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] provides CAN, CAN FD and CAN XL explicit utility functions. -.Communication between two FMUs by using a Bus Simulation FMU. -[#figure-example-network-simulation-complex] -image::principles_of_communication_complex.svg[width=70%, align="center"] +===== General Aspects +tbd -=== Creating Bus Operations ahead of the next Simulation Step -#TODO dSPACE# +===== Buffer Handling +The exchange of operations between FMUs takes place via FMI variables of the binary type. +For this reason, appropriate variables must first be set up that represent the content for this exchange. +The buffer type can be easily initialized in the form of an `fmi3UInt8` array of any size. +It should be noted that the entire buffer size must of course provide enough space for all produced operations during a `fmi3DoStep`. +Due to better accessibility, the buffer variables in our case are declared with global visibility within the FMU. -=== Data and Time Synchronization -#TODO dSPACE# +Since describing and reading operations from a simple array can be quite complicated, the common utility headers provide an `fmi3LsBusUtilBufferInfo` entity. +This abstraction represents a kind of view of the underlying buffer array and allows simplified access using additionally provided functionality. -=== Decoupling of Fixed and Variable Step Size FMUs [[low-cut-decoupling-of-fixed-and-variable-step-size-fmus]] -#TODO dSPACE# +The following program code shows the declaration and initialization of a buffer for transmitting (Tx) and receiving (Rx) operations in the form of an array. +In addition, an `fmi3LsBusUtilBufferInfo` is created for both buffer variables. +Using `FMI3_LS_BUS_BUFFER_INFO_INIT`, the underlying buffer is coupled to the respective `fmi3LsBusUtilBufferInfo` instance. -=== CAN, CAN FD, CAN XL -This chapter contains details on CAN, CAN FD, CAN XL specific topics. +[source,c] +.Setting up buffering and fmi3LsBusUtilBufferInfo instance +---- +#include "fmi3PlatformTypes.h" +#include "fmi3LsBusUtil.h" // <1> + +fmi3UInt8 TxBufferCan[2048]; // <2> +fmi3UInt8 RxBufferCan[2048]; +fmi3LsBusUtilBufferInfo TxBufferInfoCan; // <3> +fmi3LsBusUtilBufferInfo RxBufferInfoCan; + +fmi3Instance fmi3InstantiateCoSimulation(...) { + FMI3_LS_BUS_BUFFER_INFO_INIT(&TxBufferInfoCan, &TxBufferCan, sizeof(TxBufferCan)); // <4> + FMI3_LS_BUS_BUFFER_INFO_INIT(&RxBufferInfoCan, &RxBufferCan, sizeof(RxBufferCan)); +} +---- +<1> Necessary include of the fmi3LsBusUtilCan.h header file. +<2> Declaration and initialization of a Buffer FMI binary variable. +<3> Declaration of BufferInfo variable instance. +<4> Coupling of a Buffer and a BufferInfo variable. + +The buffer is always treated by the provided header functionalities using FIFO (First In - First Out) semantics. +The usage of the BufferInfo variable is discussed further. + +[NOTE] +.Summary +==== +* The transfer of Bus Operations must typically be decoupled from creation and processing +* The API provides macros for buffering of Bus Operations in a FIFO manner +==== + +===== Creating Bus Operations +The header file https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] offers macros for all operations specified by the layered standard, which minimize the effort required to create and serialize such an operation. +The macros are always provided according to the following syntax: `FMI3_LS_BUS__CREATE_OP_`. +Following these rule, the macro for creating a CAN Transmit operation is `FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT`. +A macro for creating an operation also provides the direct possibility of adding it to a BufferInfo variable. + +The following program code shows how to first define the payload and the ID that should be used in the CAN transmit operation. +Afterwards, the BufferInfo is reset using `FMI3_LS_BUS_BUFFER_RESET`. +The reset resets the internal position of the BufferInfo entity, so that it is essentially emptied and written to from the beginning. +The whole thing is necessary to ensure that operations that have already been transmitted are not transmitted a second time. +`FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT` now creates a new transmit operation with the associated parameters such as CAN ID and payload and adds them directly to the BufferInfo variable. +Querying the status of a BufferInfo entity allows you to check whether there is still enough space in the underlying buffer. +In the last step, `FMI3_LS_BUS_BUFFER_INFO_LENGTH` is used to check whether there are operations in the respective BufferInfo variable that should be transmitted in `EventMode`. + +[source,c] +.Creation of a CAN Transmit operation +---- +#include "fmi3LsBusUtilCan.h" + +fmi3Status fmi3DoStep(..., eventHandlingNeeded, ...) { + fmi3UInt8 msg[] = "Hey guys"; // <1> + fmi3LsBusCanId msgId = 42; // <2> + + /* Reset read/write positions of the BufferInfo variable */ + FMI3_LS_BUS_BUFFER_RESET(&TxBufferInfoCan); // <3> + + /* Create a CAN Transmit operation to be send */ + FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT(&TxBufferInfoCan, msgId, , sizeof(msg), msg); // <4> + + if(!TxBufferInfoCan->status){ // <5> + /* Error: No free buffer space available */ + } + + ... + + if(FMI3_LS_BUS_BUFFER_INFO_LENGTH(&TxBufferInfoCan) > 0){ + *eventHandlingNeeded = fmi3True; // <6> + } +} +---- +<1> Creation of CAN frame payload. +<2> Definition of CAN ID of the specified frame. +<3> Resetting of BufferInfo variable instance. +<4> Creation of a CAN Transmit operation and adding it to the specified BufferInfo variable. +<5> Verify that free buffer space is available. +<6> Activate FMI EventMode if needed. + +According to exactly the same principle, any specified operation can be created using an existing macro. + +[NOTE] +.Summary +==== +* Bus Operations can be created by using the provided FMI3_LS_BUS__CREATE_OP_ macros +* The CREATE_OP macros are creating a Bus Operation and updating the given buffer in a single step +==== + +===== Transmit of Bus Operations +Within the layered standard, the https://modelica.github.io/fmi-ls-bus/main/#low-cut-variables[connection] between the data to be exchanged (`TX_Data` and `Rx_Data`) and the time of exchange +(`Tx_Clock` and `Rx_Clock`) has been well defined. +The https://modelica.github.io/fmi-ls-bus/main/#low-cut-tx-triggered-clock-variables[simplest case represents] a `triggered` clock as `Tx_Clock` that basically allows to signal events when returning from `fmi3DoStep`. + +The program code below schematically illustrates an implementation. +`fmi3GetClock` is called by the importer after `fmi3DoStep` has completed or ended prematurely. +Within `fmi3GetClock` shows `TX_CLOCK_REFERENCE` represents the valueReference of the respective `Tx_Clock`. +The usage of the macro `FMI3_LS_BUS_BUFFER_IS_EMPTY` indicates whether there is data to be transferred in the respective buffer. +If this is the case, the corresponding `Tx_Clock` will tick. + +[source,c] +.Transmission of operations +---- +#include "fmi3LsBusUtil.h" + +// Example of how to transmit Bus Operations (triggered clock) +fmi3Status fmi3GetClock(fmi3Instance instance, + const fmi3ValueReference valueReferences [], + size_t nValueReferences, + fmi3Clock values[]) { + ... + for (size_t i = 0; i < nValueReferences; i++) { + if (valueReferences[i] == TX_CLOCK_REFERENCE) { + if(!FMI3_LS_BUS_BUFFER_IS_EMPTY(&TxBufferInfoCan)) { + *values[i] = fmi3ClockActive; + } + } + } + ... +} + +fmi3Status fmi3GetBinary(fmi3Instance instance, + const fmi3ValueReference valueReferences [], + size_t nValueReferences, + size_t valueSizes[], + fmi3Binary values[], + size_t nValues) { + ... + for (size_t i = 0; i < nValueReferences; i++) { + if (valueReferences[i] == TX_DATA_REFERENCE) { + *values[i] = FMI3_LS_BUS_BUFFER_START(&TxBufferInfoCan); + *valueSizes[i] = FMI3_LS_BUS_BUFFER_LENGTH(&TxBufferInfoCan); + } + } + ... +} +---- +<1> Creation of CAN frame message. +<2> Definition of CAN ID of the specified frame. +<3> Resetting of BufferInfo variable instance. +<4> Coupling of a Buffer and a BufferInfo variable. + +[NOTE] +.Summary +==== +* The LS-BUS C API provides macros to get the START address and LENGTH of the buffer which can be used in the context of `fmi3GetClock` and `fmi3GetBinary` +==== + +===== Receive of Bus Operations +* The LS-BUS API provides macros to write received binary data into a given buffer +* The buffer is updated by the WRITE macro +* The FMI3_LS_BUS_BUFFER_WRITE can be called repeatedly + +[source,c] +---- +#include "fmi3LsBusUtil.h" + +// Example of how to receive Bus Operations +fmi3Status fmi3SetBinary (fmi3Instance instance, + const fmi3ValueReference valueReferences [], + size_t nValueReferences, + const size_t valueSize, + const fmi3Binary value, ...) { + ... + for (size_t i = 0; i < nValueReferences; i++) { + if (valueReferences[i] == RX_DATA_REFERENCE) { + FMI3_LS_BUS_BUFFER_WRITE(&RXBufferInfoCan, value[i], valueSize [i]); + } + } + ... +} +---- +<1> Creation of CAN frame message. +<2> Definition of CAN ID of the specified frame. +<3> Resetting of BufferInfo variable instance. +<4> Coupling of a Buffer and a BufferInfo variable. + + + + +===== Processing of Bus Operations in Step Mode + +* Received Bus Operations can be processed by usage of the FMI3_LS_BUS_READ_NEXT_OPERATION macro +* FMI3_LS_BUS_BUFFER_INFO_RESET allows to reset the buffer after processing + + +[source,c] +---- +// Example how to processed received Bus Operations +#include "fmi3LsBusUtilCan.h" + +fmi3Status fmi3DoStep (...) { + fmi3LsBusOperationHeader* hdr; + ... + /* Processing of received bus operations */ + while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)){ + switch (hdr->type) + { + case FMI3_LS_BUS_CAN_OP_CAN_TRANSMIT: + fmi3LsBusCanOperationCanTransmit* receivedTransmitOp + = (fmi3LsBusCanOperationCanTransmit*) hdr; + ... + } + + /* Reset read/write positions */ + FMI3_LS_BUS_BUFFER_INFO_RESET(&RXBufferInfoCan); + ... + } +} +---- +<1> Creation of CAN frame message. +<2> Definition of CAN ID of the specified frame. +<3> Resetting of BufferInfo variable instance. +<4> Coupling of a Buffer and a BufferInfo variable. + + +===== Processing of Bus Operations in Event Mode + +* Received Bus Operations can be processed by usage of the FMI3_LS_BUS_READ_NEXT_OPERATION macro +* FMI3_LS_BUS_BUFFER_INFO_RESET allows to reset the buffer after processing + + +[source,c] +---- +// Example of how to processed received Bus Operations in Event Mode +#include "fmi3LsBusUtilCan.h" + +fmi3Status fmi3SetClock (fmi3Instance instance, + const fmi3ValueReference valueReference [], + size_t nValueReferences, + const fmi3clock values[]) { + fmi3LsBusOperationHeader* hdr; + ... + for (size_t i = 0; i < nValueReferences; i++) { + if (valueReferences[i] == RX_CLOCK_REFERENCE && values[i] == fmi3ClockActive) { + /* Processing of received bus operations */ + while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RXBufferInfoCan, hdr)) + { + switch (hdr->type) + { + case FMI3_LS_BUS_CAN_OP_CAN_TRANSMIT: + fmi3LsBusCanOperationCanTransmit receivedTransmitOp + = (fmi3LsBusCanOperationCanTransmit*) hdr; + ... + } + } + + /* Reset read\write positions */ + FMI3_LS_BUS_BUFFER_INFO_RESET(&RxBufferInfoCan); + } + } + ... +} +---- +<1> Creation of CAN frame payload. +<2> Definition of CAN ID of the specified frame. +<3> Resetting of BufferInfo variable instance. +<4> Coupling of a Buffer and a BufferInfo variable. + +===== Examples + +reference to example fmus with description... ==== Sequence Diagrams [[low-cut-can-sequence-diagrams]] This section contains sample sequences to clarify the facts in the CAN, CAN FD, CAN XL part. From ca4afbf93c24b21b942a5706bb64be41d553ff57 Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Fri, 17 Nov 2023 16:28:30 +0100 Subject: [PATCH 02/15] Create further content --- ls-bus-guide/4____network_abstraction.adoc | 198 ++++++++++-------- .../create_process_bus_operations.drawio | 94 +++++++++ .../images/create_process_bus_operations.svg | 3 + ...principles_of_communication_complex.drawio | 67 ------ .../principles_of_communication_complex.svg | 3 - .../principles_of_communication_direct.drawio | 42 ---- .../principles_of_communication_direct.svg | 3 - .../images/queuing_bus_operations.drawio | 1 - .../images/queuing_bus_operations.svg | 3 - 9 files changed, 211 insertions(+), 203 deletions(-) create mode 100644 ls-bus-guide/images/create_process_bus_operations.drawio create mode 100644 ls-bus-guide/images/create_process_bus_operations.svg delete mode 100644 ls-bus-guide/images/principles_of_communication_complex.drawio delete mode 100644 ls-bus-guide/images/principles_of_communication_complex.svg delete mode 100644 ls-bus-guide/images/principles_of_communication_direct.drawio delete mode 100644 ls-bus-guide/images/principles_of_communication_direct.svg delete mode 100644 ls-bus-guide/images/queuing_bus_operations.drawio delete mode 100644 ls-bus-guide/images/queuing_bus_operations.svg diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index 07a3b4f..0a32324 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -7,31 +7,47 @@ This chapter contains details on CAN, CAN FD, CAN XL specific topics. ==== Getting Started with CAN, CAN FD and CAN XL This section shows the exemplary implementation in conjunction with the provided header files of the fmi-ls-bus layered standard. -===== Provided Header Files +===== Provided Header Files [[low-cut-can-getting-started-provided-header-files]] The layered standard fmi-ls-bus not only contains a textual specification for bus support, but also provides header and utility functions as C code to make creation and use within FMUs as easy as possible. The following header files are provided by the standard for this purpose, although their use is not mandatory but optional: * https://github.com/modelica/fmi-ls-bus/blob/main/headers/fmi3LsBus.h[fmi3LsBus.h] provides general functions and structures. These header file applies to all supported bus types of the layered standard. * https://github.com/modelica/fmi-ls-bus/blob/main/headers/fmi3LsBusCan.h[fmi3LsBusCan.h] provides functions and structures explicit for CAN, CAN FD and CAN XL. -Primarily, structures are included here that allow the operations specified by the layered standard to be easily created and used. +Primarily, structures are included here that allow the bus operations specified by the layered standard to be easily created and used. * https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtil.h[fmi3LsBusUtil.h] provides common utility functions and structures for all supported bus types. * https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] provides CAN, CAN FD and CAN XL explicit utility functions. ===== General Aspects -tbd +Bus operations represent protocol units to be transmitted in the environment of the layered standard based on the https://modelica.github.io/fmi-ls-bus/main/#low-cut-layered-standard-bus-protocol[Layered Standard Bus Protocol]. +All FMI variables required for the exchange are grouped by a defined https://modelica.github.io/fmi-ls-bus/main/#low-cut-bus-terminal[Bus Terminal]. +Bus operations are created and processed within an FMU. +This can be done either in `Step Mode` or in `Event Mode`. +For a transfer, all bus operations are serialized together in a `fmi3Binary` https://modelica.github.io/fmi-ls-bus/main/#low-cut-tx-rx-data-variables[variable]. +This serialization can be done individually or using the provided <>. +After the contents of the binary variables have been transferred to another FMU via an FMU importer, they are deserialized and processed there again inside the receiver. + +.Create, process and transfer bus operations. +[#figure-general-aspects-overview] +image::create_process_bus_operations.svg[width=60%, align="center"] + +The point in time where bus operations are transferred between different FMUss are defined by variable of type `fmi3Clock`. +For this reason, the exchange of bus operations is always carried out within the `Event Mode`. +Details about possible entry points regarding the FMI interface will be provided later in this section. +However, it is important to know that due to the resulting decoupling between the generation, processing and transfer of bus operations, the need for buffer semantics arises. +This semantics is reflected directly in the structure and handling of the <> provided. ===== Buffer Handling -The exchange of operations between FMUs takes place via FMI variables of the binary type. +The exchange of bus operations between FMUs takes place via FMI variables of the `fmi3Binary` type. For this reason, appropriate variables must first be set up that represent the content for this exchange. The buffer type can be easily initialized in the form of an `fmi3UInt8` array of any size. -It should be noted that the entire buffer size must of course provide enough space for all produced operations during a `fmi3DoStep`. +It should be noted that the entire buffer size must of course provide enough space for all created bus operations during a `fmi3DoStep`. Due to better accessibility, the buffer variables in our case are declared with global visibility within the FMU. -Since describing and reading operations from a simple array can be quite complicated, the common utility headers provide an `fmi3LsBusUtilBufferInfo` entity. +Since describing and reading bus operations from a simple array can be quite complicated, the common utility headers provide an `fmi3LsBusUtilBufferInfo` entity. This abstraction represents a kind of view of the underlying buffer array and allows simplified access using additionally provided functionality. -The following program code shows the declaration and initialization of a buffer for transmitting (Tx) and receiving (Rx) operations in the form of an array. +The following program code shows the declaration and initialization of a buffer for transmitting (Tx) and receiving (Rx) bus operations in the form of an array. In addition, an `fmi3LsBusUtilBufferInfo` is created for both buffer variables. Using `FMI3_LS_BUS_BUFFER_INFO_INIT`, the underlying buffer is coupled to the respective `fmi3LsBusUtilBufferInfo` instance. @@ -47,38 +63,38 @@ fmi3LsBusUtilBufferInfo TxBufferInfoCan; // <3> fmi3LsBusUtilBufferInfo RxBufferInfoCan; fmi3Instance fmi3InstantiateCoSimulation(...) { - FMI3_LS_BUS_BUFFER_INFO_INIT(&TxBufferInfoCan, &TxBufferCan, sizeof(TxBufferCan)); // <4> - FMI3_LS_BUS_BUFFER_INFO_INIT(&RxBufferInfoCan, &RxBufferCan, sizeof(RxBufferCan)); + FMI3_LS_BUS_BUFFER_INFO_INIT(&TxBufferInfoCan, TxBufferCan, sizeof(TxBufferCan)); // <4> + FMI3_LS_BUS_BUFFER_INFO_INIT(&RxBufferInfoCan, RxBufferCan, sizeof(RxBufferCan)); } ---- <1> Necessary include of the fmi3LsBusUtilCan.h header file. -<2> Declaration and initialization of a Buffer FMI binary variable. -<3> Declaration of BufferInfo variable instance. -<4> Coupling of a Buffer and a BufferInfo variable. +<2> Declaration and initialization of a `fmi3Binary` buffer variable. +<3> Declaration of `fmi3LsBusUtilBufferInfo` variable instance. +<4> Coupling of a Buffer and a `fmi3LsBusUtilBufferInfo` variable. The buffer is always treated by the provided header functionalities using FIFO (First In - First Out) semantics. -The usage of the BufferInfo variable is discussed further. +The usage of the `fmi3LsBusUtilBufferInfo` variable is discussed further. [NOTE] .Summary ==== -* The transfer of Bus Operations must typically be decoupled from creation and processing -* The API provides macros for buffering of Bus Operations in a FIFO manner +* The transfer of bus operations must typically be decoupled from creation and processing +* The API provides macros for buffering of bus operations in a FIFO manner ==== ===== Creating Bus Operations -The header file https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] offers macros for all operations specified by the layered standard, which minimize the effort required to create and serialize such an operation. +The header file https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] offers macros for all bus operations specified by the layered standard, which minimize the effort required to create and serialize such an operation. The macros are always provided according to the following syntax: `FMI3_LS_BUS__CREATE_OP_`. Following these rule, the macro for creating a CAN Transmit operation is `FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT`. -A macro for creating an operation also provides the direct possibility of adding it to a BufferInfo variable. +A macro for creating an operation also provides the direct possibility of adding it to a `fmi3LsBusUtilBufferInfo` instance. The following program code shows how to first define the payload and the ID that should be used in the CAN transmit operation. -Afterwards, the BufferInfo is reset using `FMI3_LS_BUS_BUFFER_RESET`. -The reset resets the internal position of the BufferInfo entity, so that it is essentially emptied and written to from the beginning. -The whole thing is necessary to ensure that operations that have already been transmitted are not transmitted a second time. -`FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT` now creates a new transmit operation with the associated parameters such as CAN ID and payload and adds them directly to the BufferInfo variable. -Querying the status of a BufferInfo entity allows you to check whether there is still enough space in the underlying buffer. -In the last step, `FMI3_LS_BUS_BUFFER_INFO_LENGTH` is used to check whether there are operations in the respective BufferInfo variable that should be transmitted in `EventMode`. +Afterwards, the `fmi3LsBusUtilBufferInfo` is reset using `FMI3_LS_BUS_BUFFER_RESET`. +The reset resets the internal position of the `fmi3LsBusUtilBufferInfo` instance, so that it is essentially emptied and written to from the beginning. +The whole thing is necessary to ensure that bus operations that have already been transmitted are not transmitted a second time. +`FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT` now creates a new transmit operation with the associated parameters such as CAN ID and payload and adds them directly to the `fmi3LsBusUtilBufferInfo` instance. +Querying the status of a `fmi3LsBusUtilBufferInfo` instance allows you to check whether there is still enough space in the underlying buffer. +In the last step, `FMI3_LS_BUS_BUFFER_INFO_LENGTH` is used to check whether there are bus operations in the respective `fmi3LsBusUtilBufferInfo` variable that should be transmitted in `Event Mode`. [source,c] .Creation of a CAN Transmit operation @@ -108,17 +124,17 @@ fmi3Status fmi3DoStep(..., eventHandlingNeeded, ...) { ---- <1> Creation of CAN frame payload. <2> Definition of CAN ID of the specified frame. -<3> Resetting of BufferInfo variable instance. -<4> Creation of a CAN Transmit operation and adding it to the specified BufferInfo variable. +<3> Resetting of `fmi3LsBusUtilBufferInfo` variable instance. +<4> Creation of a CAN Transmit operation and adding it to the specified `fmi3LsBusUtilBufferInfo` variable. <5> Verify that free buffer space is available. -<6> Activate FMI EventMode if needed. +<6> Activate FMI Event Mode if needed. According to exactly the same principle, any specified operation can be created using an existing macro. [NOTE] .Summary ==== -* Bus Operations can be created by using the provided FMI3_LS_BUS__CREATE_OP_ macros +* Bus operations can be created by using the provided FMI3_LS_BUS__CREATE_OP_ macros * The CREATE_OP macros are creating a Bus Operation and updating the given buffer in a single step ==== @@ -133,21 +149,24 @@ Within `fmi3GetClock` shows `TX_CLOCK_REFERENCE` represents the valueReference o The usage of the macro `FMI3_LS_BUS_BUFFER_IS_EMPTY` indicates whether there is data to be transferred in the respective buffer. If this is the case, the corresponding `Tx_Clock` will tick. +The content of the `fmi3LsBusUtilBufferInfo` instance is provided to the importer via the FMI variable `Tx_Data` via `fmi3GetBinary`. +The value can be easily passed on to the FMI interface via `FMI3_LS_BUS_BUFFER_START`. +`FMI3_LS_BUS_BUFFER_LENGTH` can also be used to set the size of the `fmi3Binary` variable. + [source,c] -.Transmission of operations +.Transmit Bus Operations via triggered clock ---- #include "fmi3LsBusUtil.h" -// Example of how to transmit Bus Operations (triggered clock) fmi3Status fmi3GetClock(fmi3Instance instance, - const fmi3ValueReference valueReferences [], + const fmi3ValueReference valueReferences[], size_t nValueReferences, fmi3Clock values[]) { ... for (size_t i = 0; i < nValueReferences; i++) { if (valueReferences[i] == TX_CLOCK_REFERENCE) { - if(!FMI3_LS_BUS_BUFFER_IS_EMPTY(&TxBufferInfoCan)) { - *values[i] = fmi3ClockActive; + if(!FMI3_LS_BUS_BUFFER_IS_EMPTY(&TxBufferInfoCan)) { // <1> + *values[i] = fmi3ClockActive; // <2> } } } @@ -155,7 +174,7 @@ fmi3Status fmi3GetClock(fmi3Instance instance, } fmi3Status fmi3GetBinary(fmi3Instance instance, - const fmi3ValueReference valueReferences [], + const fmi3ValueReference valueReferences[], size_t nValueReferences, size_t valueSizes[], fmi3Binary values[], @@ -163,17 +182,19 @@ fmi3Status fmi3GetBinary(fmi3Instance instance, ... for (size_t i = 0; i < nValueReferences; i++) { if (valueReferences[i] == TX_DATA_REFERENCE) { - *values[i] = FMI3_LS_BUS_BUFFER_START(&TxBufferInfoCan); - *valueSizes[i] = FMI3_LS_BUS_BUFFER_LENGTH(&TxBufferInfoCan); + *values[i] = FMI3_LS_BUS_BUFFER_START(&TxBufferInfoCan); // <3> + *valueSizes[i] = FMI3_LS_BUS_BUFFER_LENGTH(&TxBufferInfoCan); // <4> } } ... } ---- -<1> Creation of CAN frame message. -<2> Definition of CAN ID of the specified frame. -<3> Resetting of BufferInfo variable instance. -<4> Coupling of a Buffer and a BufferInfo variable. +<1> Verify if bus operations exists for transfer. +<2> Activate specified `Tx_Clock`. +<3> Get the start memory address of the buffer. +<4> Get the size of the buffer. + +It should be clear that, depending on the application, the different FMI clock types each offer advantages and disadvantages. See also the https://modelica.github.io/fmi-ls-bus/main/#_selecting_the_type_of_tx_clock[corresponding chapter in the layered standard]. [NOTE] .Summary @@ -182,57 +203,64 @@ fmi3Status fmi3GetBinary(fmi3Instance instance, ==== ===== Receive of Bus Operations -* The LS-BUS API provides macros to write received binary data into a given buffer -* The buffer is updated by the WRITE macro -* The FMI3_LS_BUS_BUFFER_WRITE can be called repeatedly +The operation-receiving FMU gets the bus operations via a `fmi3Binary` variable. +This variable can be transformed back into a `fmi3LsBusUtilBufferInfo` instance. +With the help of this transformation, the bus operations to be processed can be easily accessed. +`FMI3_LS_BUS_BUFFER_WRITE` can be used for transformation. + +The code snipped below shows its use within the `fmi3SetBinary` function, which an FMU importer calls when setting the `fmi3Binary` variables. [source,c] +.Receiving Bus Operations ---- #include "fmi3LsBusUtil.h" -// Example of how to receive Bus Operations -fmi3Status fmi3SetBinary (fmi3Instance instance, - const fmi3ValueReference valueReferences [], +fmi3Status fmi3SetBinary(fmi3Instance instance, + const fmi3ValueReference valueReferences[], size_t nValueReferences, const size_t valueSize, const fmi3Binary value, ...) { ... for (size_t i = 0; i < nValueReferences; i++) { if (valueReferences[i] == RX_DATA_REFERENCE) { - FMI3_LS_BUS_BUFFER_WRITE(&RXBufferInfoCan, value[i], valueSize [i]); + FMI3_LS_BUS_BUFFER_WRITE(&RXBufferInfoCan, value[i], valueSize[i]); // <1> } } ... } ---- -<1> Creation of CAN frame message. -<2> Definition of CAN ID of the specified frame. -<3> Resetting of BufferInfo variable instance. -<4> Coupling of a Buffer and a BufferInfo variable. - - +<1> Building a `fmi3LsBusUtilBufferInfo` instance basing on received bus operations. +[NOTE] +.Summary +==== +* The LS-BUS API provides macros to write received binary data into a given buffer +* The buffer is updated by the `FMI3_LS_BUS_BUFFER_WRITE` macro +* The `FMI3_LS_BUS_BUFFER_WRITE` can be called repeatedly +==== -===== Processing of Bus Operations in Step Mode - -* Received Bus Operations can be processed by usage of the FMI3_LS_BUS_READ_NEXT_OPERATION macro -* FMI3_LS_BUS_BUFFER_INFO_RESET allows to reset the buffer after processing +===== Processing of Bus Operations +Depending on the application, the received bus operations can easily be processed within the FMU within an `fmi3DoStep`. +This procedure allows very simple implementation, especially when using FMU in a fixed step size way. +It should be clear at this point that this simple implementation is compromised by https://modelica.github.io/fmi-ls-bus/main/#_selecting_the_type_of_tx_clock[limitations in bus simulation]. +In this case, the `FMI3_LS_BUS_READ_NEXT_OPERATION` macro can be used so that all received bus operations are deserialized one after the other into the correct operation structure within `fmi3DoStep`. +After this they can be handled. [source,c] +.Processing received Bus Operations in `fmi3DoStep` ---- -// Example how to processed received Bus Operations #include "fmi3LsBusUtilCan.h" -fmi3Status fmi3DoStep (...) { +fmi3Status fmi3DoStep(...) { fmi3LsBusOperationHeader* hdr; ... /* Processing of received bus operations */ - while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)){ - switch (hdr->type) + while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)){ // <1> + switch (hdr->type) // <2> { case FMI3_LS_BUS_CAN_OP_CAN_TRANSMIT: - fmi3LsBusCanOperationCanTransmit* receivedTransmitOp + fmi3LsBusCanOperationCanTransmit* receivedTransmitOp // <3> = (fmi3LsBusCanOperationCanTransmit*) hdr; ... } @@ -243,25 +271,20 @@ fmi3Status fmi3DoStep (...) { } } ---- -<1> Creation of CAN frame message. -<2> Definition of CAN ID of the specified frame. -<3> Resetting of BufferInfo variable instance. -<4> Coupling of a Buffer and a BufferInfo variable. - - -===== Processing of Bus Operations in Event Mode - -* Received Bus Operations can be processed by usage of the FMI3_LS_BUS_READ_NEXT_OPERATION macro -* FMI3_LS_BUS_BUFFER_INFO_RESET allows to reset the buffer after processing +<1> Reading the next operation from the `fmi3LsBusUtilBufferInfo` instance. +<2> Decide which kind of operation needs to be handled. +<3> Casting into the concrete operation underlying structure. +A https://modelica.github.io/fmi-ls-bus/main/#low-cut-variables[more fine-grained bus simulation] enables the processing of the bus operations within the `Event Mode`. +This makes it possible to react directly to the receipt of new bus operations using the `Rx_Clock`. [source,c] +.Processing received Bus Operations in `Event Mode` ---- -// Example of how to processed received Bus Operations in Event Mode #include "fmi3LsBusUtilCan.h" -fmi3Status fmi3SetClock (fmi3Instance instance, - const fmi3ValueReference valueReference [], +fmi3Status fmi3SetClock(fmi3Instance instance, + const fmi3ValueReference valueReference[], size_t nValueReferences, const fmi3clock values[]) { fmi3LsBusOperationHeader* hdr; @@ -269,32 +292,39 @@ fmi3Status fmi3SetClock (fmi3Instance instance, for (size_t i = 0; i < nValueReferences; i++) { if (valueReferences[i] == RX_CLOCK_REFERENCE && values[i] == fmi3ClockActive) { /* Processing of received bus operations */ - while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RXBufferInfoCan, hdr)) + while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RXBufferInfoCan, hdr)) // <1> { - switch (hdr->type) + switch (hdr->type) // <2> { case FMI3_LS_BUS_CAN_OP_CAN_TRANSMIT: - fmi3LsBusCanOperationCanTransmit receivedTransmitOp + fmi3LsBusCanOperationCanTransmit receivedTransmitOp // <3> = (fmi3LsBusCanOperationCanTransmit*) hdr; ... } } - /* Reset read\write positions */ + /* Reset read/write positions */ FMI3_LS_BUS_BUFFER_INFO_RESET(&RxBufferInfoCan); } } ... } ---- -<1> Creation of CAN frame payload. -<2> Definition of CAN ID of the specified frame. -<3> Resetting of BufferInfo variable instance. -<4> Coupling of a Buffer and a BufferInfo variable. +<1> Reading the next operation from the `fmi3LsBusUtilBufferInfo` instance. +<2> Decide which kind of operation needs to be handled. +<3> Casting into the concrete operation underlying structure. -===== Examples +Depending on the specified application scenario, it should always check which access matches best. -reference to example fmus with description... +[NOTE] +.Summary +==== +* Received bus operations can be processed by usage of the FMI3_LS_BUS_READ_NEXT_OPERATION macro +* FMI3_LS_BUS_BUFFER_INFO_RESET allows to reset the buffer after processing +==== + +===== Examples +#TODO# ==== Sequence Diagrams [[low-cut-can-sequence-diagrams]] This section contains sample sequences to clarify the facts in the CAN, CAN FD, CAN XL part. diff --git a/ls-bus-guide/images/create_process_bus_operations.drawio b/ls-bus-guide/images/create_process_bus_operations.drawio new file mode 100644 index 0000000..7de9d31 --- /dev/null +++ b/ls-bus-guide/images/create_process_bus_operations.drawio @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ls-bus-guide/images/create_process_bus_operations.svg b/ls-bus-guide/images/create_process_bus_operations.svg new file mode 100644 index 0000000..32e7716 --- /dev/null +++ b/ls-bus-guide/images/create_process_bus_operations.svg @@ -0,0 +1,3 @@ + + +
FMU
(Co-Simulation)
FMU...
StepMode
StepMode
EventMode
EventMode
Rx_Clock
Rx_Clock
Rx_Data
(Binary)
Rx_Data...
Tx_Data
(Binary)
Tx_Data...
Tx_Clock
Tx_Clock
Bus Terminal
Bus Termin...

Create and process

Bus Operations

Create and process...

Create, process and transfer
Bus Operations

Create, process and transfer...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/ls-bus-guide/images/principles_of_communication_complex.drawio b/ls-bus-guide/images/principles_of_communication_complex.drawio deleted file mode 100644 index 67d0865..0000000 --- a/ls-bus-guide/images/principles_of_communication_complex.drawio +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ls-bus-guide/images/principles_of_communication_complex.svg b/ls-bus-guide/images/principles_of_communication_complex.svg deleted file mode 100644 index 97922b6..0000000 --- a/ls-bus-guide/images/principles_of_communication_complex.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -:FMU 1:Bus SimulationTransmitConfigure baudrate:FMU 2Computetransmission timeTransmitConfirm transmission \ No newline at end of file diff --git a/ls-bus-guide/images/principles_of_communication_direct.drawio b/ls-bus-guide/images/principles_of_communication_direct.drawio deleted file mode 100644 index c56ff92..0000000 --- a/ls-bus-guide/images/principles_of_communication_direct.drawio +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ls-bus-guide/images/principles_of_communication_direct.svg b/ls-bus-guide/images/principles_of_communication_direct.svg deleted file mode 100644 index 935e0a5..0000000 --- a/ls-bus-guide/images/principles_of_communication_direct.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -:FMU 1Confirm transmission:FMU 2Transmit \ No newline at end of file diff --git a/ls-bus-guide/images/queuing_bus_operations.drawio b/ls-bus-guide/images/queuing_bus_operations.drawio deleted file mode 100644 index d515e91..0000000 --- a/ls-bus-guide/images/queuing_bus_operations.drawio +++ /dev/null @@ -1 +0,0 @@ -7Vxbc6JIFP41qZp9iEXTgPioJia7k9nJ5DKz8zSF0CgboB3AW379NAoK3Y2gIhATU5XYh+aA5/v63BpzAfvO4sbTJuMv2ED2hSgYiwt4dSGKiiyT36FguRZARVkLRp5lrEVgK3i0XlEkFCLp1DKQn5oYYGwH1iQt1LHrIj1IyTTPw/P0NBPb6atOtBFiBI+6ZrPSH5YRjNdSVRa28ltkjcbxlYEQHXG0eHIk8MeagecJEby+gH0P42D9zln0kR3aLrbL+rxBxtHNjXnIDYqcMJPx37PJ/GqErJfB4gn9P3n+eRlpmWn2NPrA0c0Gy9gCHp66BgqVgAvYm4+tAD1OND08OieQE9k4cOzosB94+AX1sY291dmws3ptjsQ2JJ++x36A+G6QF6BFQhR9oBuEHRR4SzIlOipFtl2mh/MtUiA2/ziBkhrJtIgco43irf3Im8iEe5hTfNvmbJw9pX3sKeTb07RsO2FNQ0OqqfPsrOgqGprlWHVjssiqHdaqPKOKpzKqfA5G3VixIUYFKseqik0u2zOsWcq6yu9p6PN7JnaDS38V8bpkAlAmi5Vt4uPk3Sj6a8fzj1I0+PIc6yKfca0ufQkiXt1tLKVoQbAJdjkoF7uIIkQk0mxr5JKhThBHRN4LkbZImO1GBxzLMMLLcMmWpmN441GiIArlsKlN+T2VIZPCIRM8WRjhheUPMr0RMtXIps/X37w7sycOvGdz8Xl5ib+2788sxwMq6+llnqsH8sl8fTvfosg1umH5sWVtMmJSpKMi6BAYhinwLN2+7irXAkPitN3bROLgmTZc3Ut4PQ+RBZ0c40ALEmNSs6HkGBlWchjVVglJJqzISJVTLKhJ1DigxTIP2VpgzdJFGA/I6Ar32Fr5s4gzMkUaUZXSKnw89XQUnZUsmihFSo6eQPNGKGD0EOi1ZWLaJJzgZ98vnc3E18m6LQB2zidv1new5fgGgsP9CDyS9WnOEuZ4y//CQUuOhz9j/oWDq0Vy5tWSy3W4c5Vk0nQN244lLjWKzgBScAPKtRWlMxA6LTntTmlVGYwui0QFKrqzIZHcKBJBoSQSQdBpKXJn+2qnGSVUyyheOVtSjtubEp8tPFrONLQ8djMT3kamtnXlAMVTOzq6cop4Sa0yVe6U6p0YnzJYvbj+J5ESAiWEQ/PHm4S86ekWaLepsHKwcyGvPFXl+RPt9l4CL+Kk6y6+3zkP3/r//B4UKZcSHNBtzfctfRcNGo8e1Z8E9PIqnF3QitrVIie+O+To2pg2eGHkaEU0BU6MHC8r3K/fBcrqd+1QpDlhkHWHfviHgCU8eZrrO1YQX2ToxbPxBHm7U4Y31CMrIdLLKp9fFfTEuIQrIWnMIkpIjD52TctzCvBie6i65NJGZlA7I4AkUpToMJTgbjaWwYnhr9vXyb3w1f3xS0fjf7vm3Y3PCfyfvmueFaa8l48BmqxKgVf0V0NXaSKD7GwgYvDgoJbdyJbTUUGBLEJClQixAf6dI9Q0gAq0CE+81XCUOaUan3/g2rMpzz8cZ1WqzK9wq55r1OzY/7G5WsXm6nFkqm9zlUsmJX+FNrKfTVWwuQ3ubPdUV/FLM+HglpOk1tXP5hqV3Vz+NLAWyHifGY7UtBSH95zX4Qu+5BZx/qqubfdJye3rFl6vQm63+cRLFOy3FV6409hc+ES1k3aKUGgJyZdyGJaM3tO1jPlI7rcffQZIQiHH4oW3gWlFOZQ4NZJs3HxakHFvapokrJFkm225tVotVpg+y2XosF/BVX5ABOlWqggUJiLy6COdKiACdtP04SDDPzTc8G3YLMPHrqrUVKTcGqIxtQHdoSmca9CKlGrjk7hfunkG8YnuFgEolpJpMHrbYrVI7vdsyTkgqeZYvHiBvh8lToxkXFo2fLd6pciKBcmNaGs7q8gWtn8OrcgSEgDYqW8Tm0/E7K8JlU8gpwQCveXN7uNyR1VMU0cCDHWq3eyGbAsjt1yiyKVvEsMteaAuhT8sn4qVWsVIUXMhQJJCpv9UcykA2TZGbg1WOppM/fYm0IQC25isG80C39B+p4Wd2KG/wHJwacdRVXFxB9nNww8fXGzVch44r3vRsv3HDxdcDMywnmsamqfY5jsPFwzE0lwwR1XVLpjXlWleLf++nzw/LlsXG1a1S9nto49nzyvq5ABAceJ0z56T4fZ/vK3d1vYf5cHrPw== \ No newline at end of file diff --git a/ls-bus-guide/images/queuing_bus_operations.svg b/ls-bus-guide/images/queuing_bus_operations.svg deleted file mode 100644 index 839201e..0000000 --- a/ls-bus-guide/images/queuing_bus_operations.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -
FMU
FMU
FMU
FMU
Bus Simulation
Bus Simulation
 1 Transmit
operation
1 Transmi...
1 Confirm
operation
1 Confirm...
(Variable-Step Size)
(Variable-Step Size)
(Variable-Step Size)
(Variable-Step Size)
FMU
FMU
(Fixed-Step Size)
(Fixed-Step Size)
Tx Buffer 1
...
Tx Buffer n
Tx Buffer 1...
Rx Buffer 1
...
Rx Buffer n
Rx Buffer 1...
n Transmit
operations
n Transmit...
m Transmit
operations
m Transmit...
Tx Buffer 1
...
Tx Buffer n
Tx Buffer 1...
Rx Buffer 1
...
Rx Buffer n
Rx Buffer 1...
Tx Buffer 1
...
Tx Buffer n
Tx Buffer 1...
Rx Buffer 1
...
Rx Buffer n
Rx Buffer 1...
 1 Transmit
operation
1 Transmi...
1 Confirm
operation
1 Confirm...
Text is not SVG - cannot display
\ No newline at end of file From bb30d491521fc335786087734784e340e0d92e0b Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Mon, 20 Nov 2023 16:41:42 +0100 Subject: [PATCH 03/15] Fixed code snippets --- ls-bus-guide/4____network_abstraction.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index 0a32324..f2d22e3 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -223,7 +223,7 @@ fmi3Status fmi3SetBinary(fmi3Instance instance, ... for (size_t i = 0; i < nValueReferences; i++) { if (valueReferences[i] == RX_DATA_REFERENCE) { - FMI3_LS_BUS_BUFFER_WRITE(&RXBufferInfoCan, value[i], valueSize[i]); // <1> + FMI3_LS_BUS_BUFFER_WRITE(&RxBufferInfoCan, value[i], valueSize[i]); // <1> } } ... @@ -266,7 +266,7 @@ fmi3Status fmi3DoStep(...) { } /* Reset read/write positions */ - FMI3_LS_BUS_BUFFER_INFO_RESET(&RXBufferInfoCan); + FMI3_LS_BUS_BUFFER_INFO_RESET(&RxBufferInfoCan); ... } } @@ -292,7 +292,7 @@ fmi3Status fmi3SetClock(fmi3Instance instance, for (size_t i = 0; i < nValueReferences; i++) { if (valueReferences[i] == RX_CLOCK_REFERENCE && values[i] == fmi3ClockActive) { /* Processing of received bus operations */ - while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RXBufferInfoCan, hdr)) // <1> + while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)) // <1> { switch (hdr->type) // <2> { From dab1a9f0db00ea24af67d9bbe9b0be38aa06ceaf Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Mon, 20 Nov 2023 17:09:58 +0100 Subject: [PATCH 04/15] Add additional hints --- ls-bus-guide/4____network_abstraction.adoc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index f2d22e3..c4bd04f 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -144,12 +144,12 @@ Within the layered standard, the https://modelica.github.io/fmi-ls-bus/main/#low The https://modelica.github.io/fmi-ls-bus/main/#low-cut-tx-triggered-clock-variables[simplest case represents] a `triggered` clock as `Tx_Clock` that basically allows to signal events when returning from `fmi3DoStep`. The program code below schematically illustrates an implementation. -`fmi3GetClock` is called by the importer after `fmi3DoStep` has completed or ended prematurely. +`fmi3GetClock` is called by the FMU importer after `fmi3DoStep` has completed or ended prematurely. Within `fmi3GetClock` shows `TX_CLOCK_REFERENCE` represents the valueReference of the respective `Tx_Clock`. The usage of the macro `FMI3_LS_BUS_BUFFER_IS_EMPTY` indicates whether there is data to be transferred in the respective buffer. If this is the case, the corresponding `Tx_Clock` will tick. -The content of the `fmi3LsBusUtilBufferInfo` instance is provided to the importer via the FMI variable `Tx_Data` via `fmi3GetBinary`. +The content of the `fmi3LsBusUtilBufferInfo` instance is provided to the FMU importer via the FMI variable `Tx_Data` via `fmi3GetBinary`. The value can be easily passed on to the FMI interface via `FMI3_LS_BUS_BUFFER_START`. `FMI3_LS_BUS_BUFFER_LENGTH` can also be used to set the size of the `fmi3Binary` variable. @@ -314,6 +314,7 @@ fmi3Status fmi3SetClock(fmi3Instance instance, <2> Decide which kind of operation needs to be handled. <3> Casting into the concrete operation underlying structure. +This example assumes that the FMU importer calls `fmi3SetBinary` before `fmi3SetClock`. Depending on the specified application scenario, it should always check which access matches best. [NOTE] From 819d2e26caba62e5c8b0de0aa62bd78cbb02c628 Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Mon, 20 Nov 2023 18:04:10 +0100 Subject: [PATCH 05/15] Fixed links --- ls-bus-guide/4____network_abstraction.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index c4bd04f..ab08084 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -194,7 +194,7 @@ fmi3Status fmi3GetBinary(fmi3Instance instance, <3> Get the start memory address of the buffer. <4> Get the size of the buffer. -It should be clear that, depending on the application, the different FMI clock types each offer advantages and disadvantages. See also the https://modelica.github.io/fmi-ls-bus/main/#_selecting_the_type_of_tx_clock[corresponding chapter in the layered standard]. +It should be clear that, depending on the application, the different FMI clock types each offer advantages and disadvantages. See also the https://modelica.github.io/fmi-ls-bus/main/#low-cut-selecting-tx-variables[corresponding chapter in the layered standard]. [NOTE] .Summary @@ -242,7 +242,7 @@ fmi3Status fmi3SetBinary(fmi3Instance instance, ===== Processing of Bus Operations Depending on the application, the received bus operations can easily be processed within the FMU within an `fmi3DoStep`. This procedure allows very simple implementation, especially when using FMU in a fixed step size way. -It should be clear at this point that this simple implementation is compromised by https://modelica.github.io/fmi-ls-bus/main/#_selecting_the_type_of_tx_clock[limitations in bus simulation]. +It should be clear at this point that this simple implementation is compromised by https://modelica.github.io/fmi-ls-bus/main/#low-cut-selecting-tx-variables[limitations in bus simulation]. In this case, the `FMI3_LS_BUS_READ_NEXT_OPERATION` macro can be used so that all received bus operations are deserialized one after the other into the correct operation structure within `fmi3DoStep`. After this they can be handled. From 19cd86c2807957c4449fa96392da22242bbd1085 Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Mon, 20 Nov 2023 18:14:40 +0100 Subject: [PATCH 06/15] Fixed wording: bus operation --- ls-bus-guide/4____network_abstraction.adoc | 58 +++++++++++----------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index ab08084..0d8742a 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -14,40 +14,40 @@ The following header files are provided by the standard for this purpose, althou * https://github.com/modelica/fmi-ls-bus/blob/main/headers/fmi3LsBus.h[fmi3LsBus.h] provides general functions and structures. These header file applies to all supported bus types of the layered standard. * https://github.com/modelica/fmi-ls-bus/blob/main/headers/fmi3LsBusCan.h[fmi3LsBusCan.h] provides functions and structures explicit for CAN, CAN FD and CAN XL. -Primarily, structures are included here that allow the bus operations specified by the layered standard to be easily created and used. +Primarily, structures are included here that allow the Bus Operations specified by the layered standard to be easily created and used. * https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtil.h[fmi3LsBusUtil.h] provides common utility functions and structures for all supported bus types. * https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] provides CAN, CAN FD and CAN XL explicit utility functions. ===== General Aspects -Bus operations represent protocol units to be transmitted in the environment of the layered standard based on the https://modelica.github.io/fmi-ls-bus/main/#low-cut-layered-standard-bus-protocol[Layered Standard Bus Protocol]. +Bus Operations represent protocol units to be transmitted in the environment of the layered standard based on the https://modelica.github.io/fmi-ls-bus/main/#low-cut-layered-standard-bus-protocol[Layered Standard Bus Protocol]. All FMI variables required for the exchange are grouped by a defined https://modelica.github.io/fmi-ls-bus/main/#low-cut-bus-terminal[Bus Terminal]. -Bus operations are created and processed within an FMU. +Bus Operations are created and processed within an FMU. This can be done either in `Step Mode` or in `Event Mode`. -For a transfer, all bus operations are serialized together in a `fmi3Binary` https://modelica.github.io/fmi-ls-bus/main/#low-cut-tx-rx-data-variables[variable]. +For a transfer, all Bus Operations are serialized together in a `fmi3Binary` https://modelica.github.io/fmi-ls-bus/main/#low-cut-tx-rx-data-variables[variable]. This serialization can be done individually or using the provided <>. After the contents of the binary variables have been transferred to another FMU via an FMU importer, they are deserialized and processed there again inside the receiver. -.Create, process and transfer bus operations. +.Create, process and transfer Bus Operations. [#figure-general-aspects-overview] image::create_process_bus_operations.svg[width=60%, align="center"] -The point in time where bus operations are transferred between different FMUss are defined by variable of type `fmi3Clock`. -For this reason, the exchange of bus operations is always carried out within the `Event Mode`. +The point in time where Bus Operations are transferred between different FMUss are defined by variable of type `fmi3Clock`. +For this reason, the exchange of Bus Operations is always carried out within the `Event Mode`. Details about possible entry points regarding the FMI interface will be provided later in this section. -However, it is important to know that due to the resulting decoupling between the generation, processing and transfer of bus operations, the need for buffer semantics arises. +However, it is important to know that due to the resulting decoupling between the generation, processing and transfer of Bus Operations, the need for buffer semantics arises. This semantics is reflected directly in the structure and handling of the <> provided. ===== Buffer Handling -The exchange of bus operations between FMUs takes place via FMI variables of the `fmi3Binary` type. +The exchange of Bus Operations between FMUs takes place via FMI variables of the `fmi3Binary` type. For this reason, appropriate variables must first be set up that represent the content for this exchange. The buffer type can be easily initialized in the form of an `fmi3UInt8` array of any size. -It should be noted that the entire buffer size must of course provide enough space for all created bus operations during a `fmi3DoStep`. +It should be noted that the entire buffer size must of course provide enough space for all created Bus Operations during a `fmi3DoStep`. Due to better accessibility, the buffer variables in our case are declared with global visibility within the FMU. -Since describing and reading bus operations from a simple array can be quite complicated, the common utility headers provide an `fmi3LsBusUtilBufferInfo` entity. +Since describing and reading Bus Operations from a simple array can be quite complicated, the common utility headers provide an `fmi3LsBusUtilBufferInfo` entity. This abstraction represents a kind of view of the underlying buffer array and allows simplified access using additionally provided functionality. -The following program code shows the declaration and initialization of a buffer for transmitting (Tx) and receiving (Rx) bus operations in the form of an array. +The following program code shows the declaration and initialization of a buffer for transmitting (Tx) and receiving (Rx) Bus Operations in the form of an array. In addition, an `fmi3LsBusUtilBufferInfo` is created for both buffer variables. Using `FMI3_LS_BUS_BUFFER_INFO_INIT`, the underlying buffer is coupled to the respective `fmi3LsBusUtilBufferInfo` instance. @@ -78,12 +78,12 @@ The usage of the `fmi3LsBusUtilBufferInfo` variable is discussed further. [NOTE] .Summary ==== -* The transfer of bus operations must typically be decoupled from creation and processing -* The API provides macros for buffering of bus operations in a FIFO manner +* The transfer of Bus Operations must typically be decoupled from creation and processing +* The API provides macros for buffering of Bus Operations in a FIFO manner ==== ===== Creating Bus Operations -The header file https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] offers macros for all bus operations specified by the layered standard, which minimize the effort required to create and serialize such an operation. +The header file https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] offers macros for all Bus Operations specified by the layered standard, which minimize the effort required to create and serialize such an operation. The macros are always provided according to the following syntax: `FMI3_LS_BUS__CREATE_OP_`. Following these rule, the macro for creating a CAN Transmit operation is `FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT`. A macro for creating an operation also provides the direct possibility of adding it to a `fmi3LsBusUtilBufferInfo` instance. @@ -91,10 +91,10 @@ A macro for creating an operation also provides the direct possibility of adding The following program code shows how to first define the payload and the ID that should be used in the CAN transmit operation. Afterwards, the `fmi3LsBusUtilBufferInfo` is reset using `FMI3_LS_BUS_BUFFER_RESET`. The reset resets the internal position of the `fmi3LsBusUtilBufferInfo` instance, so that it is essentially emptied and written to from the beginning. -The whole thing is necessary to ensure that bus operations that have already been transmitted are not transmitted a second time. +The whole thing is necessary to ensure that Bus Operations that have already been transmitted are not transmitted a second time. `FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT` now creates a new transmit operation with the associated parameters such as CAN ID and payload and adds them directly to the `fmi3LsBusUtilBufferInfo` instance. Querying the status of a `fmi3LsBusUtilBufferInfo` instance allows you to check whether there is still enough space in the underlying buffer. -In the last step, `FMI3_LS_BUS_BUFFER_INFO_LENGTH` is used to check whether there are bus operations in the respective `fmi3LsBusUtilBufferInfo` variable that should be transmitted in `Event Mode`. +In the last step, `FMI3_LS_BUS_BUFFER_INFO_LENGTH` is used to check whether there are Bus Operations in the respective `fmi3LsBusUtilBufferInfo` variable that should be transmitted in `Event Mode`. [source,c] .Creation of a CAN Transmit operation @@ -134,7 +134,7 @@ According to exactly the same principle, any specified operation can be created [NOTE] .Summary ==== -* Bus operations can be created by using the provided FMI3_LS_BUS__CREATE_OP_ macros +* Bus Operations can be created by using the provided FMI3_LS_BUS__CREATE_OP_ macros * The CREATE_OP macros are creating a Bus Operation and updating the given buffer in a single step ==== @@ -189,7 +189,7 @@ fmi3Status fmi3GetBinary(fmi3Instance instance, ... } ---- -<1> Verify if bus operations exists for transfer. +<1> Verify if Bus Operations exists for transfer. <2> Activate specified `Tx_Clock`. <3> Get the start memory address of the buffer. <4> Get the size of the buffer. @@ -203,9 +203,9 @@ It should be clear that, depending on the application, the different FMI clock t ==== ===== Receive of Bus Operations -The operation-receiving FMU gets the bus operations via a `fmi3Binary` variable. +The operation-receiving FMU gets the Bus Operations via a `fmi3Binary` variable. This variable can be transformed back into a `fmi3LsBusUtilBufferInfo` instance. -With the help of this transformation, the bus operations to be processed can be easily accessed. +With the help of this transformation, the Bus Operations to be processed can be easily accessed. `FMI3_LS_BUS_BUFFER_WRITE` can be used for transformation. The code snipped below shows its use within the `fmi3SetBinary` function, which an FMU importer calls when setting the `fmi3Binary` variables. @@ -229,7 +229,7 @@ fmi3Status fmi3SetBinary(fmi3Instance instance, ... } ---- -<1> Building a `fmi3LsBusUtilBufferInfo` instance basing on received bus operations. +<1> Building a `fmi3LsBusUtilBufferInfo` instance basing on received Bus Operations. [NOTE] .Summary @@ -240,11 +240,11 @@ fmi3Status fmi3SetBinary(fmi3Instance instance, ==== ===== Processing of Bus Operations -Depending on the application, the received bus operations can easily be processed within the FMU within an `fmi3DoStep`. +Depending on the application, the received Bus Operations can easily be processed within the FMU within an `fmi3DoStep`. This procedure allows very simple implementation, especially when using FMU in a fixed step size way. It should be clear at this point that this simple implementation is compromised by https://modelica.github.io/fmi-ls-bus/main/#low-cut-selecting-tx-variables[limitations in bus simulation]. -In this case, the `FMI3_LS_BUS_READ_NEXT_OPERATION` macro can be used so that all received bus operations are deserialized one after the other into the correct operation structure within `fmi3DoStep`. +In this case, the `FMI3_LS_BUS_READ_NEXT_OPERATION` macro can be used so that all received Bus Operations are deserialized one after the other into the correct operation structure within `fmi3DoStep`. After this they can be handled. [source,c] @@ -255,7 +255,7 @@ After this they can be handled. fmi3Status fmi3DoStep(...) { fmi3LsBusOperationHeader* hdr; ... - /* Processing of received bus operations */ + /* Processing of received Bus Operations */ while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)){ // <1> switch (hdr->type) // <2> { @@ -275,8 +275,8 @@ fmi3Status fmi3DoStep(...) { <2> Decide which kind of operation needs to be handled. <3> Casting into the concrete operation underlying structure. -A https://modelica.github.io/fmi-ls-bus/main/#low-cut-variables[more fine-grained bus simulation] enables the processing of the bus operations within the `Event Mode`. -This makes it possible to react directly to the receipt of new bus operations using the `Rx_Clock`. +A https://modelica.github.io/fmi-ls-bus/main/#low-cut-variables[more fine-grained bus simulation] enables the processing of the Bus Operations within the `Event Mode`. +This makes it possible to react directly to the receipt of new Bus Operations using the `Rx_Clock`. [source,c] .Processing received Bus Operations in `Event Mode` @@ -291,7 +291,7 @@ fmi3Status fmi3SetClock(fmi3Instance instance, ... for (size_t i = 0; i < nValueReferences; i++) { if (valueReferences[i] == RX_CLOCK_REFERENCE && values[i] == fmi3ClockActive) { - /* Processing of received bus operations */ + /* Processing of received Bus Operations */ while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)) // <1> { switch (hdr->type) // <2> @@ -320,7 +320,7 @@ Depending on the specified application scenario, it should always check which ac [NOTE] .Summary ==== -* Received bus operations can be processed by usage of the FMI3_LS_BUS_READ_NEXT_OPERATION macro +* Received Bus Operations can be processed by usage of the FMI3_LS_BUS_READ_NEXT_OPERATION macro * FMI3_LS_BUS_BUFFER_INFO_RESET allows to reset the buffer after processing ==== From 9f36aa7046f41c947165dbfd1397536c9672cac4 Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Thu, 23 Nov 2023 11:01:53 +0100 Subject: [PATCH 07/15] Fixed wording and examples --- ls-bus-guide/4____network_abstraction.adoc | 142 +++++++++------------ 1 file changed, 61 insertions(+), 81 deletions(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index 0d8742a..b657b47 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -31,16 +31,16 @@ After the contents of the binary variables have been transferred to another FMU [#figure-general-aspects-overview] image::create_process_bus_operations.svg[width=60%, align="center"] -The point in time where Bus Operations are transferred between different FMUss are defined by variable of type `fmi3Clock`. +The point in time where Bus Operations are transferred between different FMUs is defined by the usage of `fmi3Clock` variables. For this reason, the exchange of Bus Operations is always carried out within the `Event Mode`. Details about possible entry points regarding the FMI interface will be provided later in this section. However, it is important to know that due to the resulting decoupling between the generation, processing and transfer of Bus Operations, the need for buffer semantics arises. This semantics is reflected directly in the structure and handling of the <> provided. ===== Buffer Handling -The exchange of Bus Operations between FMUs takes place via FMI variables of the `fmi3Binary` type. -For this reason, appropriate variables must first be set up that represent the content for this exchange. -The buffer type can be easily initialized in the form of an `fmi3UInt8` array of any size. +For exchanging Bus Operations between FMUs variables of type `fmi3Binary` type are used. +For this reason, appropriate variables must first be set up within the implementation that represent the content for this exchange. +The buffer variable can be easily initialized in the form of an `fmi3UInt8` array of any size. It should be noted that the entire buffer size must of course provide enough space for all created Bus Operations during a `fmi3DoStep`. Due to better accessibility, the buffer variables in our case are declared with global visibility within the FMU. @@ -67,7 +67,7 @@ fmi3Instance fmi3InstantiateCoSimulation(...) { FMI3_LS_BUS_BUFFER_INFO_INIT(&RxBufferInfoCan, RxBufferCan, sizeof(RxBufferCan)); } ---- -<1> Necessary include of the fmi3LsBusUtilCan.h header file. +<1> Necessary include of the fmi3LsBusUtil.h header file. <2> Declaration and initialization of a `fmi3Binary` buffer variable. <3> Declaration of `fmi3LsBusUtilBufferInfo` variable instance. <4> Coupling of a Buffer and a `fmi3LsBusUtilBufferInfo` variable. @@ -88,18 +88,18 @@ The macros are always provided according to the following syntax: `FMI3_LS_BUS_< Following these rule, the macro for creating a CAN Transmit operation is `FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT`. A macro for creating an operation also provides the direct possibility of adding it to a `fmi3LsBusUtilBufferInfo` instance. -The following program code shows how to first define the payload and the ID that should be used in the CAN transmit operation. -Afterwards, the `fmi3LsBusUtilBufferInfo` is reset using `FMI3_LS_BUS_BUFFER_RESET`. -The reset resets the internal position of the `fmi3LsBusUtilBufferInfo` instance, so that it is essentially emptied and written to from the beginning. +The following program code shows how to first define the payload and the ID that should be used in the CAN Transmit operation. +Afterwards, the `fmi3LsBusUtilBufferInfo` is reset by using `FMI3_LS_BUS_BUFFER_RESET`. +`FMI3_LS_BUS_BUFFER_RESET` sets the internal position of the `fmi3LsBusUtilBufferInfo` instance to zero, so that it is essentially emptied and written from the beginning. The whole thing is necessary to ensure that Bus Operations that have already been transmitted are not transmitted a second time. -`FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT` now creates a new transmit operation with the associated parameters such as CAN ID and payload and adds them directly to the `fmi3LsBusUtilBufferInfo` instance. +`FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT` now creates a new CAN Transmit operation with the associated parameters such as CAN ID and payload and adds them directly to the `fmi3LsBusUtilBufferInfo` instance. Querying the status of a `fmi3LsBusUtilBufferInfo` instance allows you to check whether there is still enough space in the underlying buffer. In the last step, `FMI3_LS_BUS_BUFFER_INFO_LENGTH` is used to check whether there are Bus Operations in the respective `fmi3LsBusUtilBufferInfo` variable that should be transmitted in `Event Mode`. [source,c] .Creation of a CAN Transmit operation ---- -#include "fmi3LsBusUtilCan.h" +#include "mi3LsBusUtilCan.h" fmi3Status fmi3DoStep(..., eventHandlingNeeded, ...) { fmi3UInt8 msg[] = "Hey guys"; // <1> @@ -111,7 +111,7 @@ fmi3Status fmi3DoStep(..., eventHandlingNeeded, ...) { /* Create a CAN Transmit operation to be send */ FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT(&TxBufferInfoCan, msgId, , sizeof(msg), msg); // <4> - if(!TxBufferInfoCan->status){ // <5> + if(!TxBufferInfoCan.status){ // <5> /* Error: No free buffer space available */ } @@ -127,7 +127,7 @@ fmi3Status fmi3DoStep(..., eventHandlingNeeded, ...) { <3> Resetting of `fmi3LsBusUtilBufferInfo` variable instance. <4> Creation of a CAN Transmit operation and adding it to the specified `fmi3LsBusUtilBufferInfo` variable. <5> Verify that free buffer space is available. -<6> Activate FMI Event Mode if needed. +<6> Activate `Event Mode` if needed. According to exactly the same principle, any specified operation can be created using an existing macro. @@ -145,19 +145,17 @@ The https://modelica.github.io/fmi-ls-bus/main/#low-cut-tx-triggered-clock-varia The program code below schematically illustrates an implementation. `fmi3GetClock` is called by the FMU importer after `fmi3DoStep` has completed or ended prematurely. -Within `fmi3GetClock` shows `TX_CLOCK_REFERENCE` represents the valueReference of the respective `Tx_Clock`. +Within `fmi3GetClock`, `TX_CLOCK_REFERENCE` represents the valueReference of the respective `Tx_Clock`. The usage of the macro `FMI3_LS_BUS_BUFFER_IS_EMPTY` indicates whether there is data to be transferred in the respective buffer. If this is the case, the corresponding `Tx_Clock` will tick. -The content of the `fmi3LsBusUtilBufferInfo` instance is provided to the FMU importer via the FMI variable `Tx_Data` via `fmi3GetBinary`. -The value can be easily passed on to the FMI interface via `FMI3_LS_BUS_BUFFER_START`. +The content of the `fmi3LsBusUtilBufferInfo` instance is provided to the FMU importer via `fmi3GetBinary`. +The value can be easily passed on to the FMI interface by using the `FMI3_LS_BUS_BUFFER_START` macro. `FMI3_LS_BUS_BUFFER_LENGTH` can also be used to set the size of the `fmi3Binary` variable. [source,c] .Transmit Bus Operations via triggered clock ---- -#include "fmi3LsBusUtil.h" - fmi3Status fmi3GetClock(fmi3Instance instance, const fmi3ValueReference valueReferences[], size_t nValueReferences, @@ -191,8 +189,8 @@ fmi3Status fmi3GetBinary(fmi3Instance instance, ---- <1> Verify if Bus Operations exists for transfer. <2> Activate specified `Tx_Clock`. -<3> Get the start memory address of the buffer. -<4> Get the size of the buffer. +<3> Get the start memory address of the buffer, by using `fmi3LsBusUtilBufferInfo` instance. +<4> Get the size of the buffer, by using `fmi3LsBusUtilBufferInfo` instance. It should be clear that, depending on the application, the different FMI clock types each offer advantages and disadvantages. See also the https://modelica.github.io/fmi-ls-bus/main/#low-cut-selecting-tx-variables[corresponding chapter in the layered standard]. @@ -203,17 +201,35 @@ It should be clear that, depending on the application, the different FMI clock t ==== ===== Receive of Bus Operations +The indication whether new operations are pending within the `Rx_Data` variable is done via the `Rx_Clock`. +This clock ticks as soon as new data is available. The operation-receiving FMU gets the Bus Operations via a `fmi3Binary` variable. This variable can be transformed back into a `fmi3LsBusUtilBufferInfo` instance. With the help of this transformation, the Bus Operations to be processed can be easily accessed. `FMI3_LS_BUS_BUFFER_WRITE` can be used for transformation. -The code snipped below shows its use within the `fmi3SetBinary` function, which an FMU importer calls when setting the `fmi3Binary` variables. +The code snipped below shows its use within the `fmi3SetClock` and `fmi3SetBinary` functions, which an FMU importer calls when setting the concrete `Rx_Data` variable. [source,c] .Receiving Bus Operations ---- -#include "fmi3LsBusUtil.h" +fmi3Clock RxClock; +fmi3UInt8 RxBufferCan[2048]; +fmi3LsBusUtilBufferInfo RxBufferInfoCan; + +fmi3Status fmi3SetClock(fmi3Instance instance, + const fmi3ValueReference valueReference[], + size_t nValueReferences, + const fmi3clock values[]) { + ... + for (size_t i = 0; i < nValueReferences; i++) { + if (valueReferences[i] == RX_CLOCK_REFERENCE && values[i] == fmi3ClockActive) { // <1> + /* Set an indicator that clock ticked and new Bus Operations arrived */ + RxClock = values[i]; // <2> + } + } + ... +} fmi3Status fmi3SetBinary(fmi3Instance instance, const fmi3ValueReference valueReferences[], @@ -223,13 +239,15 @@ fmi3Status fmi3SetBinary(fmi3Instance instance, ... for (size_t i = 0; i < nValueReferences; i++) { if (valueReferences[i] == RX_DATA_REFERENCE) { - FMI3_LS_BUS_BUFFER_WRITE(&RxBufferInfoCan, value[i], valueSize[i]); // <1> + FMI3_LS_BUS_BUFFER_WRITE(&RxBufferInfoCan, value[i], valueSize[i]); // <3> } } ... } ---- -<1> Building a `fmi3LsBusUtilBufferInfo` instance basing on received Bus Operations. +<1> Verify that `Rx_Clock` ticked. +<2> Park information for global access within other FMI interface functions. +<3> Building a `fmi3LsBusUtilBufferInfo` instance basing on received Bus Operations. [NOTE] .Summary @@ -240,88 +258,50 @@ fmi3Status fmi3SetBinary(fmi3Instance instance, ==== ===== Processing of Bus Operations -Depending on the application, the received Bus Operations can easily be processed within the FMU within an `fmi3DoStep`. -This procedure allows very simple implementation, especially when using FMU in a fixed step size way. -It should be clear at this point that this simple implementation is compromised by https://modelica.github.io/fmi-ls-bus/main/#low-cut-selecting-tx-variables[limitations in bus simulation]. - -In this case, the `FMI3_LS_BUS_READ_NEXT_OPERATION` macro can be used so that all received Bus Operations are deserialized one after the other into the correct operation structure within `fmi3DoStep`. +The Bus Operations must now be processed on the receiving side. +A suitable place for implementation represents `fmi3UpdateDiscreteStates`. +In this case, the `FMI3_LS_BUS_READ_NEXT_OPERATION` macro can be used so that all received Bus Operations are deserialized one after the other into the correct operation structure. After this they can be handled. [source,c] -.Processing received Bus Operations in `fmi3DoStep` +.Processing received Bus Operations. ---- -#include "fmi3LsBusUtilCan.h" - -fmi3Status fmi3DoStep(...) { +fmi3Status fmi3UpdateDiscreteStates(...) +{ fmi3LsBusOperationHeader* hdr; ... - /* Processing of received Bus Operations */ - while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)){ // <1> - switch (hdr->type) // <2> + if (fmi3ClockActive == RxClock) { + /* Processing of received Bus Operations */ + while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)) // <1> { - case FMI3_LS_BUS_CAN_OP_CAN_TRANSMIT: - fmi3LsBusCanOperationCanTransmit* receivedTransmitOp // <3> - = (fmi3LsBusCanOperationCanTransmit*) hdr; + switch (hdr->type) // <2> + { + case FMI3_LS_BUS_CAN_OP_CAN_TRANSMIT: + fmi3LsBusCanOperationCanTransmit receivedTransmitOp // <3> + = (fmi3LsBusCanOperationCanTransmit*) hdr; ... + } } + + /* Reset clock */ + RxClock = fmi3ClockInactive; /* Reset read/write positions */ FMI3_LS_BUS_BUFFER_INFO_RESET(&RxBufferInfoCan); - ... - } -} ----- -<1> Reading the next operation from the `fmi3LsBusUtilBufferInfo` instance. -<2> Decide which kind of operation needs to be handled. -<3> Casting into the concrete operation underlying structure. - -A https://modelica.github.io/fmi-ls-bus/main/#low-cut-variables[more fine-grained bus simulation] enables the processing of the Bus Operations within the `Event Mode`. -This makes it possible to react directly to the receipt of new Bus Operations using the `Rx_Clock`. - -[source,c] -.Processing received Bus Operations in `Event Mode` ----- -#include "fmi3LsBusUtilCan.h" - -fmi3Status fmi3SetClock(fmi3Instance instance, - const fmi3ValueReference valueReference[], - size_t nValueReferences, - const fmi3clock values[]) { - fmi3LsBusOperationHeader* hdr; - ... - for (size_t i = 0; i < nValueReferences; i++) { - if (valueReferences[i] == RX_CLOCK_REFERENCE && values[i] == fmi3ClockActive) { - /* Processing of received Bus Operations */ - while (FMI3_LS_BUS_READ_NEXT_OPERATION(&RxBufferInfoCan, hdr)) // <1> - { - switch (hdr->type) // <2> - { - case FMI3_LS_BUS_CAN_OP_CAN_TRANSMIT: - fmi3LsBusCanOperationCanTransmit receivedTransmitOp // <3> - = (fmi3LsBusCanOperationCanTransmit*) hdr; - ... - } - } - - /* Reset read/write positions */ - FMI3_LS_BUS_BUFFER_INFO_RESET(&RxBufferInfoCan); - } } ... } + ---- <1> Reading the next operation from the `fmi3LsBusUtilBufferInfo` instance. <2> Decide which kind of operation needs to be handled. <3> Casting into the concrete operation underlying structure. -This example assumes that the FMU importer calls `fmi3SetBinary` before `fmi3SetClock`. -Depending on the specified application scenario, it should always check which access matches best. - [NOTE] .Summary ==== * Received Bus Operations can be processed by usage of the FMI3_LS_BUS_READ_NEXT_OPERATION macro -* FMI3_LS_BUS_BUFFER_INFO_RESET allows to reset the buffer after processing +* FMI3_LS_BUS_BUFFER_INFO_RESET allows to reset the `fmi3LsBusUtilBufferInfo` instance after processing ==== ===== Examples From 2a89f47c50870c957a54d308175894057db8f746 Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Thu, 23 Nov 2023 18:07:15 +0100 Subject: [PATCH 08/15] Add note for using fmi3UpdateDiscreteStates --- ls-bus-guide/4____network_abstraction.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index b657b47..3a0aa72 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -297,6 +297,8 @@ fmi3Status fmi3UpdateDiscreteStates(...) <2> Decide which kind of operation needs to be handled. <3> Casting into the concrete operation underlying structure. +Please note that using `fmi3UpdateDiscreteStates` requires that the capability flag `providesEvaluateDiscreteStates = "true"` be set within the `modelDescription.xml`. + [NOTE] .Summary ==== From 7414f5b006f5fe250abfed55d660a90e0e924a50 Mon Sep 17 00:00:00 2001 From: bmenne-dspace Date: Fri, 24 Nov 2023 08:43:52 +0100 Subject: [PATCH 09/15] Update ls-bus-guide/4____network_abstraction.adoc Co-authored-by: Clemens Boos --- ls-bus-guide/4____network_abstraction.adoc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index 3a0aa72..feeb6c2 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -204,9 +204,7 @@ It should be clear that, depending on the application, the different FMI clock t The indication whether new operations are pending within the `Rx_Data` variable is done via the `Rx_Clock`. This clock ticks as soon as new data is available. The operation-receiving FMU gets the Bus Operations via a `fmi3Binary` variable. -This variable can be transformed back into a `fmi3LsBusUtilBufferInfo` instance. -With the help of this transformation, the Bus Operations to be processed can be easily accessed. -`FMI3_LS_BUS_BUFFER_WRITE` can be used for transformation. +The contents of this variable may then be copied into a buffer described by an `fmi3LsBusUtilBufferInfo` instance using `FMI3_LS_BUS_BUFFER_WRITE`. The code snipped below shows its use within the `fmi3SetClock` and `fmi3SetBinary` functions, which an FMU importer calls when setting the concrete `Rx_Data` variable. From 4f11bcf6f3c2264e94a04c7245dd2f4295758793 Mon Sep 17 00:00:00 2001 From: bmenne-dspace Date: Fri, 24 Nov 2023 08:44:14 +0100 Subject: [PATCH 10/15] Update ls-bus-guide/4____network_abstraction.adoc Co-authored-by: Clemens Boos --- ls-bus-guide/4____network_abstraction.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index feeb6c2..dd1bf37 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -24,7 +24,7 @@ All FMI variables required for the exchange are grouped by a defined https://mod Bus Operations are created and processed within an FMU. This can be done either in `Step Mode` or in `Event Mode`. For a transfer, all Bus Operations are serialized together in a `fmi3Binary` https://modelica.github.io/fmi-ls-bus/main/#low-cut-tx-rx-data-variables[variable]. -This serialization can be done individually or using the provided <>. +This serialization can be done using the provided <> or using a custom approach. After the contents of the binary variables have been transferred to another FMU via an FMU importer, they are deserialized and processed there again inside the receiver. .Create, process and transfer Bus Operations. From c1e994c7a2206248e02194694627dcd47af475e4 Mon Sep 17 00:00:00 2001 From: bmenne-dspace Date: Fri, 24 Nov 2023 08:44:25 +0100 Subject: [PATCH 11/15] Update ls-bus-guide/4____network_abstraction.adoc Co-authored-by: Clemens Boos --- ls-bus-guide/4____network_abstraction.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index dd1bf37..f123063 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -42,7 +42,7 @@ For exchanging Bus Operations between FMUs variables of type `fmi3Binary` type a For this reason, appropriate variables must first be set up within the implementation that represent the content for this exchange. The buffer variable can be easily initialized in the form of an `fmi3UInt8` array of any size. It should be noted that the entire buffer size must of course provide enough space for all created Bus Operations during a `fmi3DoStep`. -Due to better accessibility, the buffer variables in our case are declared with global visibility within the FMU. +To simplify our example, the buffers are declared as global variables within the FMU. Since describing and reading Bus Operations from a simple array can be quite complicated, the common utility headers provide an `fmi3LsBusUtilBufferInfo` entity. This abstraction represents a kind of view of the underlying buffer array and allows simplified access using additionally provided functionality. From 4e73d5933c5f04d071fc4762f257003e728f2dc5 Mon Sep 17 00:00:00 2001 From: bmenne-dspace Date: Fri, 24 Nov 2023 08:44:34 +0100 Subject: [PATCH 12/15] Update ls-bus-guide/4____network_abstraction.adoc Co-authored-by: Clemens Boos --- ls-bus-guide/4____network_abstraction.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index f123063..79d9d41 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -73,7 +73,7 @@ fmi3Instance fmi3InstantiateCoSimulation(...) { <4> Coupling of a Buffer and a `fmi3LsBusUtilBufferInfo` variable. The buffer is always treated by the provided header functionalities using FIFO (First In - First Out) semantics. -The usage of the `fmi3LsBusUtilBufferInfo` variable is discussed further. +The further usage of the `fmi3LsBusUtilBufferInfo` variable is discussed later. [NOTE] .Summary From 9d6198e03a8cdf678787c5a6aee1461b923d77e7 Mon Sep 17 00:00:00 2001 From: bmenne-dspace Date: Fri, 24 Nov 2023 08:45:13 +0100 Subject: [PATCH 13/15] Update ls-bus-guide/4____network_abstraction.adoc Co-authored-by: Clemens Boos --- ls-bus-guide/4____network_abstraction.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index 79d9d41..b282a76 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -99,7 +99,7 @@ In the last step, `FMI3_LS_BUS_BUFFER_INFO_LENGTH` is used to check whether ther [source,c] .Creation of a CAN Transmit operation ---- -#include "mi3LsBusUtilCan.h" +#include "Fmi3LsBusUtilCan.h" fmi3Status fmi3DoStep(..., eventHandlingNeeded, ...) { fmi3UInt8 msg[] = "Hey guys"; // <1> From 87bf2df9e4b5a445602913aaa6d40dd96748bc58 Mon Sep 17 00:00:00 2001 From: bmenne-dspace Date: Fri, 24 Nov 2023 08:45:29 +0100 Subject: [PATCH 14/15] Update ls-bus-guide/4____network_abstraction.adoc Co-authored-by: Clemens Boos --- ls-bus-guide/4____network_abstraction.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index b282a76..5dda272 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -129,7 +129,7 @@ fmi3Status fmi3DoStep(..., eventHandlingNeeded, ...) { <5> Verify that free buffer space is available. <6> Activate `Event Mode` if needed. -According to exactly the same principle, any specified operation can be created using an existing macro. +According to the same principles, any specified operation can be created using the corresponding macro. [NOTE] .Summary From 65ebe5533dc71be3b150c6a3a7462d8208c3942a Mon Sep 17 00:00:00 2001 From: Benedikt Menne Date: Fri, 24 Nov 2023 09:17:18 +0100 Subject: [PATCH 15/15] Fixed wording --- ls-bus-guide/4____network_abstraction.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ls-bus-guide/4____network_abstraction.adoc b/ls-bus-guide/4____network_abstraction.adoc index 5dda272..453e13b 100644 --- a/ls-bus-guide/4____network_abstraction.adoc +++ b/ls-bus-guide/4____network_abstraction.adoc @@ -86,7 +86,7 @@ The further usage of the `fmi3LsBusUtilBufferInfo` variable is discussed later. The header file https://github.com/modelica/fmi-guides/blob/main/ls-bus-guide/headers/fmi3LsBusUtilCan.h[fmi3LsBusUtilCan.h] offers macros for all Bus Operations specified by the layered standard, which minimize the effort required to create and serialize such an operation. The macros are always provided according to the following syntax: `FMI3_LS_BUS__CREATE_OP_`. Following these rule, the macro for creating a CAN Transmit operation is `FMI3_LS_BUS_CAN_CREATE_OP_CAN_TRANSMIT`. -A macro for creating an operation also provides the direct possibility of adding it to a `fmi3LsBusUtilBufferInfo` instance. +A macro for creating an operation also commits it to a buffer described by an `fmi3LsBusUtilBufferInfo` instance. The following program code shows how to first define the payload and the ID that should be used in the CAN Transmit operation. Afterwards, the `fmi3LsBusUtilBufferInfo` is reset by using `FMI3_LS_BUS_BUFFER_RESET`. @@ -144,7 +144,7 @@ Within the layered standard, the https://modelica.github.io/fmi-ls-bus/main/#low The https://modelica.github.io/fmi-ls-bus/main/#low-cut-tx-triggered-clock-variables[simplest case represents] a `triggered` clock as `Tx_Clock` that basically allows to signal events when returning from `fmi3DoStep`. The program code below schematically illustrates an implementation. -`fmi3GetClock` is called by the FMU importer after `fmi3DoStep` has completed or ended prematurely. +`fmi3GetClock` is called by the FMU importer in `Event Mode` after `fmi3DoStep` has completed or ended prematurely. Within `fmi3GetClock`, `TX_CLOCK_REFERENCE` represents the valueReference of the respective `Tx_Clock`. The usage of the macro `FMI3_LS_BUS_BUFFER_IS_EMPTY` indicates whether there is data to be transferred in the respective buffer. If this is the case, the corresponding `Tx_Clock` will tick. @@ -192,6 +192,8 @@ fmi3Status fmi3GetBinary(fmi3Instance instance, <3> Get the start memory address of the buffer, by using `fmi3LsBusUtilBufferInfo` instance. <4> Get the size of the buffer, by using `fmi3LsBusUtilBufferInfo` instance. +Note that in theory, the `fmi3GetClock` may only return `fmi3ClockActive` once per clock activation. + It should be clear that, depending on the application, the different FMI clock types each offer advantages and disadvantages. See also the https://modelica.github.io/fmi-ls-bus/main/#low-cut-selecting-tx-variables[corresponding chapter in the layered standard]. [NOTE] @@ -295,8 +297,6 @@ fmi3Status fmi3UpdateDiscreteStates(...) <2> Decide which kind of operation needs to be handled. <3> Casting into the concrete operation underlying structure. -Please note that using `fmi3UpdateDiscreteStates` requires that the capability flag `providesEvaluateDiscreteStates = "true"` be set within the `modelDescription.xml`. - [NOTE] .Summary ====