1. Disclaimer

Information contained in this publication regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. EXOLIGENT MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Exoligent disclaims all liability arising from this information and its use. Use of Exoligent devices in life support and/or safety applications is entirely at the buyer’s risk, and the buyer agrees to defend, indemnify and hold harmless Exoligent from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Exoligent intellectual property rights unless otherwise stated.

Exoligent SARL
390 rue d’Estienne d’Orves, 92700 Colombes - France
Tel: +33(0) 1 42 42 42 00
Web Site: https://www.exoligent.com/
Copyright © 2022 Exoligent SARL. All rights reserved.

2. Introduction

UAFIP is an open-source software gateway written in C for GNU/Linux operating system whose goal is to create a deterministic gateway between the WorldFIP fieldbus protocol (IEC 61158) and the OPC UA over TSN (IEC 62541) standard for data exchange. This user guide serves as starting point for a user to learn, install and configure this gateway for embedding into their products.

This document is partly based on the very good guide from Kalycito:
How to run OPC UA PubSub on real-time Linux and TSN

The structure of the UAFIP TSN gateway is divided into three entities:

  • Configurator: json-c – an open-source C JSON parser licensed under MIT (github)

  • OPC UA stack: open62541 – an open-source C (C99) implementation of OPC UA licensed under the Mozilla Public License v2.0 (github)

  • WorldFIP stack: powerfip – a C communication stack to interface with the Exoligent’s FIP coprocessor (doc)

gw principle diagram
Figure 1. UAFIP software gateway (Principle Diagram)

3. Prerequisites

3.1. Hardware requirements

  • x86-based system

    • 4-cores

    • Intel i210 Ethernet controller (as this controller supports features necessary for Time-Sensitive Networking)

    • 1 x PCIe slot or 1 x mPCIe slot

  • FIP controller

    • PowerFIP Exoligent’s board (mPCIe and its derivatives)

We used Advantech’s UNO-1483G during our tests.

3.2. Software requirements

  • Debian GNU/Linux 10 and more

    • Pre-compiled real-time kernel

    • A later version of iproute2 package (with support for newer real-time socket options and an IEEE 802.1 Qbv like scheduler)

    • A later version of LinuxPTP package (with support for IEEE 802.1 AS gPTP configuration)

  • FIP library/kernel module + UAFIP TSN gateway sources (see last PowerFIP Package)

We used Debian GNU/Linux 11 (bullseye) with PREEMPT-RT 5.10.0-14-rt-amd64 kernel during our tests

We selected Debian 11, as it is one of the more popular distributions. It also has a pre-compiled real-time kernel that can be installed using the Debian package manager.
As it is not practically possible to provide a variant of the userguide for the many Linux distributions out there, we recommend that you use Debian for your initial tests and then switch to your chosen distribution.

4. Environment setup

In this section, we will set up the environment:

  • Install real-time Linux kernel

  • Install FIP controller

  • Configure Ethernet network interface

  • Configure TSN parameters

  • Build UAFIP TSN gateway

4.1. Install real-time Linux Kernel

After installing the OS, update the node using the below command:

$ sudo apt-get update && apt-get upgrade

It might take a while for the update and upgrade to complete. You can then download and install the real-time kernel that is distributed by Debian and reboot the node using the below commands:

$ sudo apt-get install linux-image-rt-amd64 -y
$ sudo reboot

After reboot, execute the below command and ensure that the newly installed real-time kernel is the one that is currently running.
The appearance of the “rt” keyword in the print message that appears as part of the command output shows that we have booted into the right kernel:

$ uname -r

5.10.0-14-rt-amd64

4.2. Install FIP controller

In this section, we will install FIP controller on your machine.

Once the real time Linux kernel is installed, shutdown your system and plug a PowerFIP PCIe card into a suitable slot

After reboot and log in user, download the archive of the latest version of the library from the Exoligent website (Download section) or get it from the following linux command (here the example is for the v1.4.0 package):

$ cd ~/Documents
$ wget https://www.exoligent.com/wiki/worldfip/pwrfip/download/1.4.0/powerfip-1.4.0-linux.tar.gz
$ tar xzvf powerfip-1.4.0-linux.tar.gz
$ cd powerfip-1.4.0-linux

Build and install the kernel module for FIP controller:

$ cd ~/Documents/powerfip-1.4.0-linux/driver/linux
$ make
$ sudo ./install.sh

If you have a PowerFIP PCIe device connected to your machine, you should get the following console trace with the dmesg command:

$ dmesg

[78983.022874] powerfip: ==> Init
[78983.022934] powerfip: ==> Device probing
[78983.023186] powerfip: BAR 0 (0xf6000000 - 0xf6000fff), len = 4096, flags = 0x040200
[78983.023205] powerfip: BAR 1 (0xf4000000 - 0xf5ffffff), len = 33554432, flags = 0x040200
[78983.023883] powerfip: DMA Capability = YES
[78983.023887] powerfip: MSI Capability = YES
[78983.023888] powerfip: IRQ pin  = #1 (0=none, 1=INTA#...4=INTD#)
[78983.023890] powerfip: IRQ line = #69
[78983.023891] powerfip: IRQ vectors = 4

Now, install FIP firmware and library:

$ cd ../../
$ sudo ./install.sh
Following files will be copied to your system
  1. powerfip-firmware.bin file to the path:
    /usr/local/lib/firmware

  2. libpowerfip.a and libpowerfip.so files to the path:
    /usr/local/lib

  3. header (*.h) files to the path:
    /usr/local/include/powerfip

The FIP controller is now ready for operation! If you want to test it, refer you to the turnkey examples in the tools/ directory of the distribution.

4.3. Configure Ethernet network interface

In this section, we will set up static IP address and VLAN configuration to the i210 interface. Open the interfaces file using the below commands:

$ sudo nano /etc/network/interfaces

Copy and paste the following lines at the end of the interfaces file in both the nodes and replace “X” as shown in the screenshot below and save the file. E.g., In node 1 (ex: ua_pong node example), set the IP address as 192.168.100.1, and in node 2 (ex: uafip tsn gateway node), set the IP address as 192.168.100.2. The PubSub TSN applications are configured to run with VLAN Id 8. For this purpose, VLAN configuration is done in the i210 interface as below:

auto enp7s0
iface enp7s0 inet static
    address 192.168.100.X
    netmask 255.255.255.0
    broadcast 192.168.100.255
auto enp7s0.8
iface enp7s0.8 inet static
    address 192.168.8.X
    netmask 255.255.255.0

Throughout this QSG we will be using enp7s0 for the interface name, replace it with your nodes’ i210 interface name.

Below is the screenshot of the interfaces files of the two nodes: node_1_2_net_interface

Save the interfaces file and restart the networking service:

$ sudo /etc/init.d/networking restart

Now verify the static IP address and the connection between two nodes (from node 1 ping node 2 and vice versa) using the below commands:

$ ip a

[...]

3: enp7s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdpgeneric/id:34 qdisc mqprio state UP group default qlen 1000
    link/ether 74:fe:48:30:39:eb brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.2/24 brd 192.168.100.255 scope global enp7s0
       valid_lft forever preferred_lft forever
    inet6 fe80::76fe:48ff:fe30:39eb/64 scope link
       valid_lft forever preferred_lft forever

[...]
$ ping 192.168.100.X

4.4. Configure TSN parameters

In this section, we will run some scripts from the Kalycito company (setup.sh, application_dependencies.sh) to configure the TSN parameters.
The setup.sh available in the package does the following,

  • Updates the installed packages in the node

  • Installs iproute2 package for kernel version 5.10

  • Installs Linux PTP version 2.0

  • Checks if 8021q module is loaded; if not, adds the same

The application_dependencies.sh available in the package does the following,

  • Configures traffic control parameters to transmit and receive

  • Sets Egress and Ingress policies

  • Tunes real-time behaviors

  • Runs Linux PTP and PHC2SYS

  • Kernel mechanism to allocate CPU to the processes

The above scripts are included in the powerfip package. To access them, go to the kalycito directory, and run the setup.sh script using the below command:

$ cd ~/Documents/powerfip-1.4.0-linux/tools/uafip_tsn_gateway/scripts/kalycito
$ sudo ./setup.sh

We have modified the grub settings, so reboot is required.

Reboot the nodes after completing the initial setup

$ sudo reboot
Run PTP and PHC2SYS

After the reboot, run the application_dependencies.sh. As shown in the architecture diagram, configure one of the nodes as PTP master and the other node as PTP slave.

To configure the node as PTP master use the below command:

$ cd ~/Documents/powerfip-1.4.0-linux/tools/uafip_tsn_gateway/scripts/kalycito
$ sudo ./application_dependencies.sh -i enp2s0 -m

To configure the node as PTP slave use the below command:

$ sudo ./application_dependencies.sh -i enp2s0 -s

After configuring the node as PTP master or slave, the output log can be verified using the below command:

$ tail -f /var/log/ptp4l.log

If you have configured your node as a PTP master, your output log should be similar to the below image. The text “assuming the grand master role” ensures that you have configured the node as PTP master. Once you have seen the output, press Ctrl + C to return to the console.

$ tail -f /var/log/ptp4l.log

  ptp4l[3194.498]: port 1: link up
  ptp4l[3194.558]: port 1: FAULTY to LISTENING on INIT_COMPLETE
  ptp4l[3205.493]: port 1: LISTENING to MASTER on ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES
  ptp4l[3205.493]: selected local clock 74fe48.fffe.42c2e4 as best master
  ptp4l[3205.493]: port 1: assuming the grand master role

If you have configured your node as a PTP slave, your output log should be similar to the below image.

The master offset values are represented in nanosecond (ns). This value should be within the range of -1000 ns to +1000 ns

$ tail -f /var/log/ptp4l.log

  ptp4l[4527.664]: master offset          4 s2 freq  +39804 path delay       -17
  ptp4l[4527.789]: master offset          5 s2 freq  +39806 path delay       -17
  ptp4l[4527.914]: master offset          0 s2 freq  +39799 path delay       -17
  ptp4l[4528.039]: master offset          0 s2 freq  +39799 path delay       -17
  ptp4l[4528.165]: master offset         -6 s2 freq  +39791 path delay       -17
  ptp4l[4528.290]: master offset         -4 s2 freq  +39793 path delay       -17

The application_dependencies.sh would have run PHC2SYS utility to synchronize user clock and hardware clock. You can verify the output log of PHC2SYS in both the nodes using the below command:

$ tail -f /var/log/phc2sys.log

Your PHC2SYS log should be similar to the below image.

The sys offset values are represented in nanosecond (ns). This value should be within the range of -1000 ns to +1000 ns

Once you have seen the output, press Ctrl + C to return to the console.

4.5. Build UAFIP TSN gateway

4.5.1. XDP Pre-requisties

XDP (Express Data Path) is used by the gateway subscriber for faster processing the data.

For our test with the Debian 11 OS (5.10.0-14-rt-amd64) we use the bpf library v0.3.

To build and install libbpf library, use the following commands:

$ sudo apt install llvm
$ sudo apt install clang

$ cd ~/Documents
$ git clone https://github.com/libbpf/libbpf.git
$ cd libbpf/
$ git checkout 051a4009f94d5633a8f734ca4235f0a78ee90469
$ cd src/
$ sudo OBJDIR=/usr/lib make install

4.5.2. Build open62541

$ sudo apt install build-essential gcc pkg-config cmake python

$ cd ~/Documents
$ wget https://github.com/open62541/open62541/archive/refs/tags/v1.3.tar.gz -O open62541-1.3.0.tar.gz
$ tar xzvf open62541-1.3.0.tar.gz
$ cd open62541-1.3.0
$ mkdir build
$ cd build
$ cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DOPEN62541_VERSION=v1.3.0 -DUA_ENABLE_PUBSUB=ON -DUA_ENABLE_PUBSUB_ETH_UADP=ON -DUA_ENABLE_MALLOC_SINGLETON=ON -DUA_ENABLE_IMMUTABLE_NODES=ON -DUA_ENABLE_PUBSUB_INFORMATIONMODEL=ON -DUA_MULTITHREADING=150
$ make
$ sudo make install

4.5.3. Build the gateway

$ sudo apt install libjson-c-dev

$ cd ~/Documents/powerfip-1.4.0-linux/tools/uafip_tsn_gateway
$ make

4.5.4. Start the gateway

$ cd ~/Documents/powerfip-1.4.0-linux/tools/uafip_tsn_gateway
$ sudo setcap cap_sys_nice+ep uafipd
$ ./uafipd -f ./config/2sta/sta1.json

4.5.5. Install the gateway as a daemon

Install UAFIP gateway as a daemon:

$ cd ~/Documents/powerfip-1.4.0-linux/tools/uafip_tsn_gateway/svc/
$ sudo ./install_svc.sh

Created symlink /etc/systemd/system/multi-user.target.wants/uafipd.service → /etc/systemd/system/uafipd.service.

Once installed, you can manipulate the daemon with the classic commands of systemd:

Daemon status:

$ sudo systemctl status uafipd

● uafipd.service - OPC UA Pub/Sub TSN <-> FIP/WorldFIP gateway
     Loaded: loaded (/etc/systemd/system/uafipd.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2022-06-10 15:01:52 CEST; 59s ago
   Main PID: 5910 (uafipd)
      Tasks: 5 (limit: 9383)
     Memory: 3.6M
        CPU: 1.241s
     CGroup: /system.slice/uafipd.service
             └─5910 /usr/bin/uafipd -f /etc/exoligent/uafip/config/performance/sta1.json -L /var/log/uafipd.log

Stop the daemon:

$ sudo systemctl stop uafipd

Start the daemon:

$ sudo systemctl start uafipd

Enable the daemon at system startup:

$ sudo systemctl enable uafipd

Created symlink /etc/systemd/system/multi-user.target.wants/uafipd.service → /etc/systemd/system/uafipd.service.

Disable the daemon at system startup:

$ sudo systemctl disable uafipd

Removed /etc/systemd/system/multi-user.target.wants/uafipd.service.

5. Gateway configuration

The UAFIP TSN gateway can be configured using a JSON file. The OPC PUB/SUB parameters are defined there as well as the parameters of the embedded FIP node.

Example of UAFIP gateway configuration file (config/ping/uno/sta1.json)
{
  "opc": {
    "publisher" : {
      "network_interface":"enp7s0",
      "url":"opc.eth://74-fe-48-42-c2-e4:8.3",
      "publisher_id":"5671",
      "dataset_writer_id":"62541",
      "writer_group_id":"101",
      "publish_period_us":"250"
    },
    "subscriber" : {
      "network_interface":"enp7s0",
      "url":"opc.eth://74-fe-48-30-39-eb:8.3",
      "publisher_id":"5670",
      "dataset_writer_id":"62541",
      "writer_group_id":"100"
    }
  },
  "fip": {
    "name":"FIP node 1",
    "address":"1",
    "segment":"0",
    "frame_type":"worldfip",
    "bitrate":"1mbps",
    "turn_around_us":"30",
    "silence_us":"150",
    "vars": [
      {
        "name":"[0x3800]",
        "type":"cons",
        "id":"0x3800",
        "payload_bsz":"8",
        "refreshment":"yes",
        "promptness":"yes",
        "prompt_us":"7500",
        "event":"none"
      },
      {
        "name":"[0x3801]",
        "type":"prod",
        "id":"0x3801",
        "payload_bsz":"8",
        "refreshment":"yes",
        "refresh_us":"7500",
        "event":"none"
      },
      {
        "name":"[0xFF00]",
        "type":"sync",
        "id":"0xFF00",
        "event":"w_op"
      },
      {
        "name":"[0xFF01]",
        "type":"sync",
        "id":"0xFF01",
        "event":"r_op"
      }
    ]
  }
}

See appendix sta0.json to get a gateway configuration example with a master FIP node (Bus Arbiter enabled).

The JSON file is a data tree structure composed of nodes (containers) and leaves (data).
Below is a description of the layout of the containers and [arrays]:

  • rounded square rgb 5555bb opc

    • rounded square rgb 7575bb publisher

      • rounded square rgb 9595bb network_interface, (…​)

    • rounded square rgb 7575bb subcriber

      • rounded square rgb 9595bb network_interface, (…​)

  • rounded square rgb ffaaaa fip

    • rounded square rgb ffaaaa name, (…​), [vars]

      • rounded square rgb ffcaca name, (…​)

    • rounded square rgb ffbaba bus_arbiter

      • rounded square rgb ffcaca enable, (…​), [cycles]

        • rounded square rgb ffdada [windows]

          • rounded square rgb ffeaea type, (…​)

          • rounded square rgb ffeaea [requests] (only inside periodic window)

            • rounded square rgb fffafa type, (…​)

Name Status Type Description

opc

required

object

OPC-UA configuration container

publisher

required

object

OPC-UA PUB container

network_interface

required

string

Publisher network interface

url

required

string

Publisher MAC address
ex: opc.eth://74-fe-48-30-39-eb:8.3 (where 8 is the VLAN ID and 3 is the PCP)
ex: opc.udp://224.0.0.32:4840/ (multicast address)

publisher_id

required

u16

Unique ID for a publisher with the message-oriented middleware

dataset_writer_id

required

u16

The dataset writer Id identifies the dataset writer in the writer group. It is unique across all dataset writers for a publisher ID

writer_group_id

required

u16

Writer Group Identifier. It is unique across writer groups for a publisher ID

publish_period_us

required

u32

Publisher cycle time in microseconds

subscriber

required

object

OPC-UA SUB container

network_interface

required

string

Subscriber network interface

url

required

string

Subscriber MAC address
ex: opc.eth://74-fe-48-42-c2-e4:8.3 (where 8 is the VLAN ID and 3 is the PCP)
ex: opc.udp://224.0.0.22:4840/ (multicast address)

publisher_id

required

u16

Unique ID of the publisher to subscribe to

dataset_writer_id

required

u16

Dataset Writer ID to subscribe to

writer_group_id

required

u16

Writer Group ID to subscribe to

fip

required

object

FIP configuration container

name

optional

string

FIP node identification label

address

required

u8

FIP node physical address

segment

required

u8

FIP node segment number

frame_type

required

enum

Values:

  • worldfip
    WorldFIP frame encoding type (IEC [International Electrotechnical Commission])

  • fip
    FIP frame encoding type (UTE [Union Technique de l'Electricité])

bitrate

required

enum

Values:

  • 31.25kbps
    FIP/WorldFIP bitrate at 31.25Kbps

  • 1mbps
    FIP/WorldFIP bitrate at 1Mbps

  • 2.5mbps
    FIP/WorldFIP bitrate at 2.5Mbps

  • 5mbps
    FIP/WorldFIP bitrate at 5Mbps

  • 12.5mbps
    FIP/WorldFIP bitrate at 12.5Mbps [experimental]

  • 25mbps
    FIP/WorldFIP bitrate at 25Mbps [experimental]

turn_around_us

required

u32

Turn-Around time in microseconds

silence_us

required

u32

Silence time in microseconds

vars

optional

array

Array of FIP variables configuration

name

optional

string

FIP variable identification label

type

required

enum

Values:

  • cons
    Input FIP variable (consumed)

  • prod
    Output FIP variable (produced)

id

required

u16

Unique identifier of a FIP variable

payload_bsz

required

u16

FIP variable payload size in bytes

Only significant for FIP prod and cons variable type.

refreshment

optional

boolean

Enable/Disable the production status byte (refreshement) for the FIP variable

refresh_us

optional

u32

Refreshment period in microseconds

Only significant for FIP prod variable type.

promptness

optional

boolean

Enable/Disable the promptness status for a FIP consumed variable

Only significant for FIP cons variable type.

prompt_us

optional

u32

Promptness period in microseconds

Only significant for FIP cons variable type.

event

optional

enum

Values:

  • none
    No FIP event attached to the variable

  • r_op
    Read operation of the FIP variables by the gateway

  • w_op
    Write operation of the FIP variables by the gateway

  • rw_op
    Read and write operation of the FIP variables by the gateway

bus_arbiter

optional

object

FIP master configuration container

enable

required

boolean

Enable/Disable bus arbiter (master) capability

priority

required

u8

Should be in [0..15] range (0: highest priority)

cycles

required

array

Array of Fip master macrocycles

windows

required

array

Array of BA windows inside a macrocycle

type

required

enum

Values:

  • periodic
    Periodic BA window

  • aperiodic_var
    Aperiodic Variable BA window

  • aperiodic_msg
    Aperiodic Message BA window

  • wait
    Internal Resync waiting BA window

end_ustime

optional

u32

End time of the aperiodic BA window in microseconds

Only significant for aperiodic_var, aperiodic_msg and wait BA window types

The end time is relative to the first macrocycle operation

requests

optional

array

Only significant for periodic BA window type

type

required

enum

Values:

  • id_dat
    FIP variable BA request

  • id_msg
    FIP message BA request

id

required

u16

FIP identifier to request during a periodic BA window

6. Ping-Pong example

ping pong diagram
Figure 2. Ping/Pong Test (Principle Diagram)

The "ping-pong" example is a test between a FIP master node (BA) and an OPC-UA node (client) where an UAFIP TSN gateway acts as an intermediary between the two heterogeneous nodes.

  1. The FIP node increments a PING counter (64-bit value) at each macrocycle and produces a RP_DAT[0x3800] FIP frame with the updated counter to the FIP network.

  2. This FIP data is consumed by the UAFIP gateway and is transfered via an OPC-UA publisher to the Ethernet network.

  3. A remote OPC-UA node (client) subscribes to the gateway’s publisher and returns this value by republishing it (PONG counter).

  4. The gateway in turn consumes this OPC value via a subscriber and produces a RP_DAT[0x3801] FIP frame with the updated PONG counter (64-bit value).

  5. At each new macrocycle, the FIP node consumes the RP_DAT[0x3801] data [PONG] and compares it to the new value of the RP_DAT[0x3800] variable to be produced [PING].
    If the real time capacity of the whole system is maintained, the difference between the consumed and produced counters should never exceed 1 unit for the FIP node.

In order to avoid cycle losses due to initial conditions, the starting order of the different nodes is important!
You should start by launching UAFIP_GATEWAY, then UA_PONG and finally FIP_PING.

UAFIP_GATEWAY
uno1483g@uno1483g:~/Documents/powerfip/tools/uafip_tsn_gateway$ sudo ./start_rt_gateway.sh "./uafipd -f ./config/ping/uno/sta1.json"
  1. Here we use the start_rt_gateway.sh script to start the gateway, locks the process to a specific CPU, and sets the scheduling policy.

  2. We configure the gateway using the config/ping/uno/sta1.json file (see its description here)

Console trace of the UAFIP TSN gateway started

uafipd_console_trace

UA_PONG

Then, launch the OPC node which will play the PONG role with the command below:

uno2372g@uno2372g:~/Documents/powerfip/tools/uafip_tsn_gateway/tools/ua_pong$ sudo ./ua_pong

Make sure that the settings defined in the powerfip/tools/uafip_tsn_gateway/tools/ua_pong/test.h header file match those of the UAFIP gateway.

Console trace of the UA_PONG example started

uapong_console_trace

FIP_PING

Finally, launch the FIP node which will play the PING role with the command below:

pctest@pctest:~/Documents/powerfip/tools/pwrfip_ping$ sudo ./pwrfip_ping -i 1 -n 0 -c 10000

Here we use the parameters:

  • -i 1: FIP device index number 1

  • -n 0: FIP node address 0 (.i.e: PING station)

  • -c 10000: FIP macrocycle period of 10ms

Console trace of the FIP_PING example started

fipping_console_trace

If all goes well, the bus arbiter should start and the ping/pong ok counter start to increment. No loss of FIP macrocycle occurs while the nok counter remains at 0.

Appendix A: JSON files examples

A.1. Ping (FIP Node 0)

config/ping/uno/sta0.json
{
  "opc": {
    "publisher" : {
      "network_interface":"enp2s0",
      "url":"opc.eth://74-fe-48-30-39-eb:8.3",
      "publisher_id":"5670",
      "dataset_writer_id":"62541",
      "writer_group_id":"100",
      "publish_period_us":"250"
    },
    "subscriber" : {
      "network_interface":"enp2s0",
      "url":"opc.eth://74-fe-48-42-c2-e4:8.3",
      "publisher_id":"5671",
      "dataset_writer_id":"62541",
      "writer_group_id":"101"
    }
  },
  "fip": {
    "name":"FIP node 0",
    "address":"0",
    "segment":"0",
    "frame_type":"worldfip",
    "bitrate":"1mbps",
    "turn_around_us":"30",
    "silence_us":"150",
    "vars": [
      {
        "name":"[0x3800]",
        "type":"prod",
        "id":"0x3800",
        "payload_bsz":"8",
        "refreshment":"yes",
        "refresh_us":"7500",
        "event":"none"
      },
      {
        "name":"[0x3801]",
        "type":"cons",
        "id":"0x3801",
        "payload_bsz":"8",
        "refreshment":"yes",
        "promptness":"yes",
        "prompt_us":"7500",
        "event":"none"
      },
      {
        "name":"[0xFF00]",
        "type":"sync",
        "id":"0xFF00",
        "event":"r_op"
      },
      {
        "name":"[0xFF01]",
        "type":"sync",
        "id":"0xFF01",
        "event":"w_op"
      }
    ],
    "bus_arbiter": {
      "enable":"yes",
      "priority":"1",
      "cycles": [
        {
          "windows": [
            {
              "type":"periodic",
              "requests": [
                {
                  "type":"id_dat",
                  "id":"0x3800"
                },
                {
                  "type":"id_dat",
                  "id":"0xFF00"
                }
              ]
            },
            {
              "type":"wait",
              "end_ustime":"2500"
            },
            {
              "type":"periodic",
              "requests": [
                {
                  "type":"id_dat",
                  "id":"0x3801"
                },
                {
                  "type":"id_dat",
                  "id":"0xFF01"
                }
              ]
            },
            {
              "type":"wait",
              "end_ustime":"5000"
            }
          ]
        }
      ]
    }
  }
}

A.2. Pong (FIP Node 1)

config/ping/uno/sta1.json
{
  "opc": {
    "publisher" : {
      "network_interface":"enp7s0",
      "url":"opc.eth://74-fe-48-42-c2-e4:8.3",
      "publisher_id":"5671",
      "dataset_writer_id":"62541",
      "writer_group_id":"101",
      "publish_period_us":"250"
    },
    "subscriber" : {
      "network_interface":"enp7s0",
      "url":"opc.eth://74-fe-48-30-39-eb:8.3",
      "publisher_id":"5670",
      "dataset_writer_id":"62541",
      "writer_group_id":"100"
    }
  },
  "fip": {
    "name":"FIP node 1",
    "address":"1",
    "segment":"0",
    "frame_type":"worldfip",
    "bitrate":"1mbps",
    "turn_around_us":"30",
    "silence_us":"150",
    "vars": [
      {
        "name":"[0x3800]",
        "type":"cons",
        "id":"0x3800",
        "payload_bsz":"8",
        "refreshment":"yes",
        "promptness":"yes",
        "prompt_us":"7500",
        "event":"none"
      },
      {
        "name":"[0x3801]",
        "type":"prod",
        "id":"0x3801",
        "payload_bsz":"8",
        "refreshment":"yes",
        "refresh_us":"7500",
        "event":"none"
      },
      {
        "name":"[0xFF00]",
        "type":"sync",
        "id":"0xFF00",
        "event":"w_op"
      },
      {
        "name":"[0xFF01]",
        "type":"sync",
        "id":"0xFF01",
        "event":"r_op"
      }
    ]
  }
}

Appendix B: Glossary of acronyms

BA

Bus Arbiter

FIP

Factory Instrumentation Protocol

OPC-UA

Open Platform Communications Unified Architecture

TSN

Time-Sensitive Networking

Appendix C: Revision History

Revision Changes Authors Date

1.0.0

First version

MC

2022-06-21