Skip to content

Ettus USRP E310

Summary

The E31X OSP provides support for the Ettus USRP E310, E312, and E313 Software Defined Radios. On this page E310 is used to refer to all three radios as, when using OpenCPI, all three operate in the same manner.

Hardware Specifications
Specification Description
Processor Zynq 7020 SoC (Arm Cortex-A9 MPCore @ 866 MHz)
FPGA Zynq 7020 SoC (Artix-7) 106400 Flip-flops, 53200 LUT, 220 DSP
RF Channels 2 RX, 2 TX (Second RX / TX channel for MIMO - Not frequency independent)
RF Tuning Range 70 MHz to 6 GHz
RF Sample Rate 3.072 MHz to 61.44 MHz
ADC / DAC Resolution 12 bits
OSP Implementation Details
Specification Description
Project Name ocpi.osp.e3xx
RCC Platform xilinx19_2_aarch32
FPGA Platform e31x
Control plane clock rate 100 MHz
ADC Interface Protocol complex_short_timed_sample
ADC sample value range -2047 to 2047
DAC Interface Protocol complex_short_timed_sample
DAC sample value range -32767 to 32767

Installation

Prerequisites

The following items must be installed first before installing the OSP for the E310:

RCC Platform

The E310 uses the xilinx19_2_aarch32 platform for building RCC workers. This platform uses the 32-bit ARM compiler supplied with Xilinx Vitis 2019.2. The xilinx19_2_aarch32 platform is included in the built-in ocpi.core project.

# Install the RCC platform
ocpiadmin install platform xilinx19_2_aarch32 --minimal

HDL Platform

# Install and build the HDL platform
ocpiadmin install platform e31x -p ocpi.osp.e3xx --minimal -g v2.4.6

cd $OCPI_ROOT_DIR/projects/osps/ocpi.osp.e3xx
# Temporary patch to fix bug
sed -i 's/<property name='\''SINGLE_PORT_p'\'' value='\''true'\''\/>/<property name='\''SINGLE_PORT_p'\'' value='\''false'\''\/>/g' ./hdl/cards/drc_e31x_csts.rcc/drc_e31x_csts.xml
# Build proxy workers within the e3xx OSP for xilinx19_2_aarch32
ocpidev build --rcc --rcc-platform xilinx19_2_aarch32 hdl

Bootable SD card

The E310 OSP includes a Linux boot image based off the Xilinx PetaLinux Pre-build image. OpenCPI can generate a bootable SD card using a combination of this image and the OpenCPI kernel driver.

To generate the SD card files, run the following command:

ocpiadmin deploy platform xilinx19_2_aarch32 e31x
The location of the output files is: $OCPI_ROOT_DIR/exports/e31x/sdcard-xilinx19_2_aarch32

Format an SD card with a single FAT32 partition. Mount the partition and use the following command to copy all files to the SD card:

cp -r -L $OCPI_ROOT_DIR/exports/e31x/sdcard-xilinx19_2_aarch32/* /PATH/TO/SD/CARD/MOUNT/POINT/
The -L option follows symlinks when copying and is needed to make sure all required files are copied.

Modify Setup Scripts

The default SD card image includes two example setup scripts. default_mysetup.sh configures Standalone Mode and default_mynetsetup.sh configures Network Mode. Create a copy of these examples named mysetup.sh and mynetsetup.sh.

cd /PATH/TO/SD/CARD/MOUNT/POINT/
cd opencpi/
mv default_mynetsetup.sh mynetsetup.sh
mv default_mysetup.sh mysetup.sh

These scripts can be modified as required for your application. The most common modification is to add additional NFS mount points to mynetsetup.sh. See Network Mode for more details.

Modify the Root Filesystem

The default Linux boot image is set to load the root filesystem from a ramdisk. This means any changes to it are non-persistent and reset on a reboot. Information on how to modify the root filesystem is available here.

Creating an Application

Container

The cfg_1rx_1tx_mode_5_cmos_csts and cfg_2rx_2tx_mode_5_cmos_csts platform configurations expose the ADC and DAC of the E31X via the Complex Short Timed Sample protocol. Timed Sample protocols are used by components in the ocpi.comp.sdr project.

Depreciation Warning

All configurations other than cfg_1rx_1tx_mode_5_cmos_csts and cfg_2rx_2tx_mode_5_cmos_csts should be considered depreciated. The majority of assemblies and applications that form part of the ocpi.osp.e3xx project do not use these configurations, and therefore should also be considered depreciated.

When using these configurations a typical container for the platform is shown below.

<HdlContainer config="cfg_1rx_1tx_mode_5_cmos_csts" only="e31x">
  <Connection external="adc_out_asm_in" device="data_src_qadc_csts0" port="out"
              card="e31x_mimo_xcvr_scdcd_csts"/>
  <Connection external="asm_out_dac_in" device="data_sink_qdac_csts0" port="in"
              card="e31x_mimo_xcvr_scdcd_csts"/>
</HdlContainer>
<!-- WARNING!!!! DUAL CHANNEL IS NOT CURRENTLY SUPPORTED IN v2.4.6 -->
<HdlContainer config="cfg_2rx_2tx_mode_5_cmos_csts" only="e31x">
  <Connection external="adc_out_asm_in0" device="data_src_qadc_csts0" port="out"
              card="e31x_mimo_xcvr_scdcd_csts"/>
  <Connection external="asm_out_dac_in0" device="data_sink_qdac_csts0" port="in"
              card="e31x_mimo_xcvr_scdcd_csts"/>
  <Connection external="adc_out_asm_in1" device="data_src_qadc_csts1" port="out"
              card="e31x_mimo_xcvr_scdcd_csts"/>
  <Connection external="asm_out_dac_in1" device="data_sink_qdac_csts1" port="in"
              card="e31x_mimo_xcvr_scdcd_csts"/>
</HdlContainer>

Connections between the E310’s FPGA and its ARM processor can be added to the container using:

<Connection external="<Connection_name>" interconnect="zynq"/>
By default the transmitter on the E310 will remain on whenever the channel is enabled in the DRC. When the transmitter is enabled the E310 has significant local oscillator (LO) leakage out of its transmit port. This can cause issues in time division multiple access (TDMA) applications. In these cases the OSP can allow the transmitter LO to be turned on and off using signaling inline with the transmit I/Q data. To enable this mode the following line must be added to the container:

<Connection device="data_sink_qdac_csts0" port="on_off"
            otherdevice="data_sink_qdac_csts_ad9361_sub" otherport="on_off0"
            card="e31x_mimo_xcvr_scdcd_csts"/>
Disabling the transmitter LO is not
currently supported in dual channel mode

When this connection is present the transmitter LO will be enabled when a Start of message (SOM) is received by the DAC device workers, and disabled when a flush opcode is received by the DAC device workers.

Assembly

A typical assembly when using the above container is shown below.

<HdlAssembly>
  <Instance Worker="<EXAMPLE_TX_WORKER>" />
  <Connection Name="asm_out_dac_in" External="producer">
    <Port Instance="<EXAMPLE_TX_WORKER>" Name="output"/>
  </Connection>
  <Instance Worker="<EXAMPLE_RX_WORKER>" />
  <Connection Name="adc_out_asm_in" External="consumer">
    <Port Instance="<EXAMPLE_RX_WORKER>" Name="input"/>
  </Connection>
</HdlAssembly>
<!-- WARNING!!!! DUAL CHANNEL IS NOT CURRENTLY SUPPORTED IN v2.4.6 -->
<HdlAssembly>
  <Instance Worker="<EXAMPLE_TX_WORKER_CH0>" />
  <Connection Name="asm_out_dac_in0" External="producer">
    <Port Instance="<EXAMPLE_TX_WORKER_CH0>" Name="output"/>
  </Connection>
  <Instance Worker="<EXAMPLE_RX_WORKER_CH0>" />
  <Connection Name="adc_out_asm_in0" External="consumer">
    <Port Instance="<EXAMPLE_RX_WORKER_CH0>" Name="input"/>
  </Connection>
  <Instance Worker="<EXAMPLE_TX_WORKER_CH1>" />
  <Connection Name="asm_out_dac_in1" External="producer">
    <Port Instance="<EXAMPLE_TX_WORKER_CH1>" Name="output"/>
  </Connection>
  <Instance Worker="<EXAMPLE_RX_WORKER_CH1>" />
  <Connection Name="adc_out_asm_in1" External="consumer">
    <Port Instance="<EXAMPLE_RX_WORKER_CH1>" Name="input"/>
  </Connection>
</HdlAssembly>

Application

A typical XML application for the above assembly is shown below.

<Application>
  <Instance Component="ocpi.platform.drc">
    <property name='configurations'
              Value="{description first,
                      channels {{rx true,
                                tuning_freq_MHz 2450,
                                bandwidth_3dB_MHz 4,
                                sampling_rate_Msps 4,
                                samples_are_complex true,
                                gain_mode auto,
                                tolerance_tuning_freq_MHz 0.01,
                                tolerance_sampling_rate_Msps 0.01,
                                tolerance_gain_dB 1},
                                {rx false,
                                tuning_freq_MHz 2450,
                                bandwidth_3dB_MHz 4,
                                sampling_rate_Msps 4,
                                samples_are_complex true,
                                gain_mode manual,gain_dB -30,
                                tolerance_bandwidth_3dB_MHz 0,
                                tolerance_tuning_freq_MHz 0.01,
                                tolerance_sampling_rate_Msps 0.01,
                                tolerance_gain_dB 1}}}"/>
    <property name='start' value='0'/>
    <property name="enable_rx_resampling" value="false" />
    <property name="enable_tx_resampling" value="false" />
    <property name="enable_rx_digital_tuning" value="false" />
    <!-- Set tx_disable_on_flush to false when on_off connection not made in container -->
    <property name="tx_disable_on_flush" value="true" />
  </Instance>

  <Instance Component="<EXAMPLE_TX_COMPONENT>" Connect="drc" from="output" to="tx"/>
  <Instance Component="<EXAMPLE_RX_COMPONENT>"/>

  <Connection>
    <Port Instance="drc" Name="rx"/>
    <Port Instance="<EXAMPLE_RX_COMPONENT>" Name="input"/>
  </Connection>
</Application>
<!-- WARNING!!!! DUAL CHANNEL IS NOT CURRENTLY SUPPORTED IN v2.4.6 -->
<Application>
  <Instance Component="ocpi.platform.drc">
    <property name='configurations'
              Value="{description first,
                      channels {{rx true,
                                tuning_freq_MHz 2450,
                                bandwidth_3dB_MHz 4,
                                sampling_rate_Msps 4,
                                gain_mode auto},
                                {rx false,
                                tuning_freq_MHz 2450,
                                bandwidth_3dB_MHz 4,
                                sampling_rate_Msps 4,
                                gain_mode manual,
                                gain_dB -30},                                    
                                {rx true,
                                tuning_freq_MHz 2350,
                                bandwidth_3dB_MHz 4,
                                sampling_rate_Msps 4
                                gain_mode auto},
                                {rx false,
                                tuning_freq_MHz 2350,
                                bandwidth_3dB_MHz 4,
                                sampling_rate_Msps 4,
                                gain_mode manual,
                                gain_dB -30}}}"/>
    <property name='start' value='0'/>
  </Instance>

  <Instance Component="<EXAMPLE_TX_COMPONENT_CH0>" Connect="drc" from="output" to="tx"/>
  <Instance Component="<EXAMPLE_RX_COMPONENT_CH0>"/>

  <Instance Component="<EXAMPLE_TX_COMPONENT_CH1>" Connect="drc" from="output" to="tx1"/>
  <Instance Component="<EXAMPLE_RX_COMPONENT_CH1>"/>

  <Connection>
    <Port Instance="drc" Name="rx"/>
    <Port Instance="<EXAMPLE_RX_COMPONENT_CH0>" Name="input"/>
  </Connection>

  <Connection>
    <Port Instance="drc" Name="rx1"/>
    <Port Instance="<EXAMPLE_RX_COMPONENT_CH1>" Name="input"/>
  </Connection>
</Application>

Running an application

The E310 OSP supports all three OpenCPI modes of operation on embedded systems: Network Mode, Standalone Mode, and Server Mode.

Network Mode

Network mode uses NFS to mount OpenCPI's cross compiled binaries and bitstreams directly from the development host. Network mode is useful during development as it saves moving files from the development host to the embedded device after each compilation.

NFS Settings

To use network mode you must have set up the development host to share both the directory where OpenCPI is installed, and also the directories of any user-created OpenCPI projects needed for an application.

Instructions for setting up NFS on the development host are available here.

The opencpi/mynetsetup.sh script on the SD card will automatically mount the main OpenCPI directory from the development host, but additional directories need to be added manually.

In the opencpi/mynetsetup.sh script, uncomment the following lines and edit / duplicate to mount all the required directories:

# mkdir -p /mnt/user
# mount -t nfs -o udp,nolock,soft,intr $1:/home/opencpi/<user_project_directory> /mnt/user

For example, to mount the host machine's /home/opencpi/example_project directory in the E310's /mnt/user directory you would add the following commands:

# Example
mkdir -p /mnt/user
mount -t nfs -o udp,nolock,soft,intr $1:/home/opencpi/example_project /mnt/user

Configure networking

By default the E310 uses DHCP to obtain an IP address from the local router. You can check the router settings / logs to identify what IP address the E310 has been assigned.

If you want to connect the E310 directly to the development host, without a router, then it is necessary to assign a static IP address to the E310. This can be done automatically, on boot-up, by following the instructions to modify the E310's root filesystem here. Alternatively, it can be done manually, on each boot, by connecting to the E310 via the USB serial console port, using a terminal application like screen, logging in with username: root, password: root, and finally using ipconfig or ip to set the IP address.

# Use dmesg to check the name of the most recent TTY device
# that has been plugged in. It might not be /dev/ttyUSB0
sudo screen /dev/ttyUSB0 115200 # (1)!
# Set the network settings as desired
ifconfig eth0 10.0.2.2 netmask 255.255.255.0
  1. Screen can be installed with sudo yum install screen or sudo apt-install screen.

Connect via SSH

Once the E310 has an IP address, you can connect to it via SSH.

# ssh root@<E310_IP_ADDRESS>
ssh root@10.0.2.2
The password is root.

Info

The first time you attempt to login via SSH after a reboot, the login will fail. Just enter the password again and it will succeed. This is a bug with Xilinx's example root filesystem.

Since the E310 uses a non-persistent filesystem, it likely that the WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! error will occur. If this, or any other issues occur when connecting, refer to this page.

Once connected via SSH, run the mynetsetup.sh script. It takes two augments: the IP address of the development host, and the full path on the development host to the OpenCPI directory.

cd /run/media/mmcblk0p1/opencpi/
# source ./mynetsetup.sh <IP_OF_DEV_HOST> <PATH_ON_DEV_HOST_TO_OPENCPI_DIR>
source ./mynetsetup.sh 10.0.2.1 /home/opencpi/opencpi

The terminal outputs when successful and unsuccessful are shown below.

Success
An IP address was detected.
My IP address is: 10.0.2.2, and my hostname is: avnet-digilent-zedboard-2019_2
Attempting to set time from time.nist.gov
rdate: bad address 'time.nist.gov'
====YOU HAVE NO NETWORK CONNECTION and NO HARDWARE CLOCK====
Set the time using the "date YYYY.MM.DD-HH:MM[:SS]" command.
Running login script.
OCPI_CDK_DIR is now /mnt/net/cdk
OCPI_ROOT_DIR is now /mnt/net
Executing /home/root/.profile
No reserved DMA memory found on the linux boot command line.
Driver loaded successfully.
OpenCPI ready for zynq.
Loading bitstream
Bitstream successfully loaded
Discovering available containers...
Available containers:
#  Model Platform            OS     OS-Version  Arch     Name
0  hdl   e31x                                            PL:0
1  rcc   xilinx19_2_aarch32  linux  19_2        aarch32  rcc0
Network Configuration Issue
An IP address was detected.
My IP address is: 10.0.2.2, and my hostname is: avnet-digilent-zedboard-2019_2
mount: mounting 10.0.2.50:/home/opencpi/opencpi on /mnt/net failed: Connection timed out
NFS Configuration Issue
An IP address was detected.
My IP address is: 10.0.2.2, and my hostname is: avnet-digilent-zedboard-2019_2
mount: mounting 10.0.2.1:/home/opencpi/opencpi_fake on /mnt/net failed: Permission denied

Once the setup script completes successfully, configure OCPI_LIBRARY_PATH to include all the directories needed for the desired application, and then execute the application. An example is shown below:

export OCPI_LIBRARY_PATH=$OCPI_LIBRARY_PATH:/mnt/user/example_project
cd /mnt/user/example_project/applications/example_app
ocpirun -t 10 -d example_app.xml

Info

In most cases /mnt/net/projects/osps/ocpi.osp.e3xx/artifacts should be added to the OCPI_LIBRARY_PATH. This is the directory where the the .so for the DRC proxy lives.

Since the binaries and bitstreams for the application remain on the development host, when they are rebuilt there is no need to copy the files across. The application can just be rerun on the embedded system, and it will automatically use the latest files.

Standalone Mode

In standalone mode the E310 can run an application "standalone" without any connection to a development host.

To run an OpenCPI application standalone, all the files needed to run the application must be copied to the SD card. For most applications this includes:

  • XML Application file (OAS)
  • ACI application binary (if not using ocpirun)
  • *.so files for each RCC worker used in the application
  • *.so files for any RCC proxy workers used by the application or platform (i.e. DRC worker)
  • *.bitz bitstream for the FPGA (if required)

The files can be stored anywhere on the SD card.

Info

When copying the various OpenCPI artifacts to the SD card, watch out for accidentally copying symbolic links to the files, instead of the files themselves. Using cp -L <SRC> <DST> will copy the actual file, even if <SRC> is actually just a symbolic link.

Most users will want to modify the E310's root filesystem to automatically start an OpenCPI application. To do this, follow these instructions to add an autorun.sh script that gets executed on boot.

Once this is done, create / edit the autorun.sh script (in the root directory of the SD card) such that it performs the required setup steps needed to run the application.

In the example below, all the RCC workers and FPGA bitstreams have been stored on the SD card in /my_assets/, and the application binaries and OAS XML files have been stored in /my_apps/.

Example autorun.sh
# Setup standalone mode
cd /run/media/mmcblk0p1/opencpi/
source ./mysetup.sh
# Set up the OCPI_LIBRARY_PATH to include all required asset directories
export OCPI_LIBRARY_PATH=$OCPI_LIBRARY_PATH:/run/media/mmcblk0p1/my_assets
# Run a custom ACI application that takes location of OAS file as an argument
/run/media/mmcblk0p1/my_apps/test_app /run/media/mmcblk0p1/my_apps/test_app.xml

Info

The root of the SD card is automatically mounted at /run/media/mmcblk0p1/ on the E310's root filesystem.

Server Mode

Server mode allows the containers on a remote platform to be connected directly to the development host. This mode is especially useful for running unit tests on a number of different platforms.

Firstly, OpenCPI needs to copy the files needed to enable server mode on the E310. This is done by running the ocpiremote load application on the development host.

# Set the IP address to the E310's IP
# Port 12345 is the default for ocpiserve
export OCPI_SERVER_ADDRESSES=10.0.2.2:12345

# Check which interfaces are active using:
ocpihdl ethers
# And then set the correct interface to use
export OCPI_SOCKET_INTERFACE=enp0s3

# ocpiremote copies files to the E310 via SCP
ocpiremote load --rcc-platform xilinx19_2_aarch32 --hdl-platform e31x -p root

Terminal output on success
Preparing remote sandbox...
Sun May 28 20:38:19 UTC 2023
Creating server package...
Sending server package...
Server package sent successfully
Getting status (no server expected to be running):
Executing remote configuration command: status
No ocpiserve appears to be running: no pid file

Next, the ocpiserve application must be started on the E310 by running the following command on the development host.

ocpiremote start -b -p root
Terminal output on sucess
Executing remote configuration command: start -B
The driver module is not loaded. No action was taken.
Reloading kernel driver: 
No reserved DMA memory found on the linux boot command line.
Driver loaded successfully.
Loading opencpi bitstream
PATH=/home/root/sandbox/xilinx19_2_aarch32/bin:/home/root/sandbox/xilinx19_2_aarch32/sdk/bin:/usr/bin:/bin
LD_LIBRARY_PATH=xilinx19_2_aarch32/sdk/lib
VALGRIND_LIB=
nohup ocpiserve -v -p 12345 > 20230528-203910.log
Server (ocpiserve) started with pid: 1244.  Initial log is:
Discovery options:  discoverable: 0, loopback: 0, onlyloopback: 0
Container server at <ANY>:12345
  Available TCP server addresses are:
    On interface eth0: 10.0.2.2:12345
Artifacts stored/cached in the directory "artifacts", which will be retained on exit.
Containers offered to clients are:
  0: PL:0, model: hdl, os: , osVersion: , platform: e31x
  1: rcc0, model: rcc, os: linux, osVersion: 19_2, platform: xilinx19_2_aarch32
--- end of server startup log success above

Once ocpiserve is running on the E310, run ocpirun -C on the development host to see all available containers. The list should now include e31x and xilinx19_2_aarch32.

Available containers:
 #  Model Platform            OS     OS-Version  Arch     Name
 0  hdl   e31x                                            10.0.2.2:12345/PL:0
 1  rcc   xilinx19_2_aarch32  linux  19_2        aarch32  10.0.2.2:12345/rcc0
 2  rcc   centos7             linux  c7          x86_64   rcc0

In server mode OpenCPI uses several high-numbered ports to communicate between the embedded system and the development host. Before running an application, it is likely that a firewall rule will need to be added to the development host:

# Either temporarily add E310's IP to trusted zone
sudo firewall-cmd --zone=trusted --add-source=10.0.2.2
# OR add it permanently
sudo firewall-cmd --zone=trusted --add-source=10.0.2.2 --permanent
# OR just allow any connections on a specified interface
firewall-cmd --zone=trusted --add-interface=enp0s3

Once everything is setup, applications can be run on the development host using ocpirun. The -p <INSTANCE>=<PLATFORM> option can be used to force a worker to run on a specific platform.

For example, to run the testbias application:

cd $OCPI_ROOT_DIR/projects/assets/applications
export OCPI_LIBRARY_PATH=$OCPI_ROOT_DIR/projects/core/artifacts/:$OCPI_ROOT_DIR/projects/assets/artifacts

# Force bias to run on the E310's ARM processor
ocpirun -v -P bias=xilinx19_2_aarch32 testbias.xml
# Force bias to run on the E310's FPGA
ocpirun -v -P bias=e31x testbias.xml

Terminal output on success - xilinx19_2_aarch32
Received server information from "10.0.2.2:12345".  Available containers are:
  10.0.2.2:12345/PL:0                  platform e31x, model hdl, os , version , arch , build 
    Transports: ocpi-dma-pio,00:0a:35:00:01:22,0,0,0x41,0x101|ocpi-socket-rdma, ,1,0,0x42,0x41|
  10.0.2.2:12345/rcc0                  platform xilinx19_2_aarch32, model rcc, os linux, version 19_2, arch aarch32, build 
    Transports: ocpi-dma-pio,00:0a:35:00:01:22,1,0,0x103,0x103|ocpi-smb-pio,00:0a:35:00:01:22,0,0,0xb,0xb|ocpi-socket-rdma, ,1,0,0x42,0x43|
Available containers are:  0: 10.0.2.2:12345/PL:0 [model: hdl os:  platform: e31x], 1: 10.0.2.2:12345/rcc0 [model: rcc os: linux platform: xilinx19_2_aarch32], 2: rcc0 [model: rcc os: linux platform: centos7]
Actual deployment is:
  Instance  0 file_read (spec ocpi.core.file_read) on rcc container 2: rcc0, using file_read in /home/opencpi/opencpi/projects/core/artifacts//ocpi.core.file_read.rcc.0.centos7.so dated Mon May  8 13:13:34 2023
  Instance  1 bias (spec ocpi.core.bias) on rcc container 1: 10.0.2.2:12345/rcc0, using bias_cc in /home/opencpi/opencpi/projects/core/artifacts//ocpi.core.bias_cc.rcc.0.xilinx19_2_aarch32.so dated Sun May 14 11:48:05 2023
  Instance  2 file_write (spec ocpi.core.file_write) on rcc container 2: rcc0, using file_write in /home/opencpi/opencpi/projects/core/artifacts//ocpi.core.file_write.rcc.0.centos7.so dated Mon May  8 13:13:37 2023
Application XML parsed and deployments (containers and artifacts) chosen [0 s 91 ms]
Application established: containers, workers, connections all created [0 s 50 ms]
Application started/running [0 s 1 ms]
Waiting for application to finish (no time limit)
Application finished [0 s 142 ms]
Terminal output on success - e31x
Received server information from "10.0.2.2:12345".  Available containers are:
  10.0.2.2:12345/PL:0                  platform e31x, model hdl, os , version , arch , build 
    Transports: ocpi-dma-pio,00:0a:35:00:01:22,0,0,0x41,0x101|ocpi-socket-rdma, ,1,0,0x42,0x41|
  10.0.2.2:12345/rcc0                  platform xilinx19_2_aarch32, model rcc, os linux, version 19_2, arch aarch32, build 
    Transports: ocpi-dma-pio,00:0a:35:00:01:22,1,0,0x103,0x103|ocpi-smb-pio,00:0a:35:00:01:22,0,0,0xb,0xb|ocpi-socket-rdma, ,1,0,0x42,0x43|
Available containers are:  0: 10.0.2.2:12345/PL:0 [model: hdl os:  platform: e31x], 1: 10.0.2.2:12345/rcc0 [model: rcc os: linux platform: xilinx19_2_aarch32], 2: rcc0 [model: rcc os: linux platform: centos7]
Actual deployment is:
  Instance  0 file_read (spec ocpi.core.file_read) on rcc container 2: rcc0, using file_read in /home/opencpi/opencpi/projects/core/artifacts//ocpi.core.file_read.rcc.0.centos7.so dated Mon May  8 13:13:34 2023
  Instance  1 bias (spec ocpi.core.bias) on hdl container 0: 10.0.2.2:12345/PL:0, using bias_vhdl/a/bias_vhdl in /home/opencpi/opencpi/projects/assets/artifacts/ocpi.assets.testbias_e31x_base.hdl.0.e31x.bitz dated Sun May 14 14:06:11 2023
  Instance  2 file_write (spec ocpi.core.file_write) on rcc container 2: rcc0, using file_write in /home/opencpi/opencpi/projects/core/artifacts//ocpi.core.file_write.rcc.0.centos7.so dated Mon May  8 13:13:37 2023
Application XML parsed and deployments (containers and artifacts) chosen [0 s 66 ms]
Application established: containers, workers, connections all created [0 s 59 ms]
Application started/running [0 s 3 ms]
Waiting for application to finish (no time limit)
Application finished [0 s 172 ms]
Error: EOF on socket read

If you see the message below, it is likely that firewall settings are preventing OpenCPI communicating over the network. OpenCPI uses random high-numbered ports to communicate.

Application XML parsed and deployments (containers and artifacts) chosen [0 s 40 ms]
OCPI( 2:176.0999): Exception during application shutdown: error reading from container server "": EOF on socket read
Exiting for exception: error reading from container server "": EOF on socket read
Fix the firewall settings, run ocpiremote start -b -p root, and try running the application again.