RTEMS Tutorial¶
This section serves as a comprehensive guide to assist in creating and understanding the key points of a basic Safe DDS application using RTEMS.
This project has been tested with RTEMS 6.1 and Waf 2.0.19, building for a Xilinx Zynq board, and running through QEMU emulation. Check Supported platforms for more information.
Note
This guide might require adaptations to work with a different hardware, or RTEMS version.
In order to get support please contact support@eProsima.com.
Note
It is recommended to first read the Getting Started section to gain a better understanding of the basic concepts and terminology used in this section.
Project Configuration¶
This section describes how to configure an RTEMS project that uses the Safe DDS library.
1. Install the required dependencies¶
Before starting, ensure that you have the necessary dependencies installed on your system.
To replicate this tutorial on Ubuntu 24.04, the following packages are needed:
sudo apt install apt-utils build-essential vim u-boot-tools git cmake bison flex \
texinfo bzip2 xz-utils unzip libexpat1-dev python3-dev python3 python-is-python3 \
zlib1g-dev libtinfo-dev pax qemu-system-arm wget curl bsdmainutils
2. Download and setup RTEMS¶
Start by downloading RTEMS and configuring it for the target architecture:
# Create a directory for the RTEMS installation
mkdir /rtems
cd /rtems
# Download and install RTEMS Source Builder
wget https://ftp.rtems.org/pub/rtems/releases/6/6.1/sources/rtems-source-builder-6.1.tar.xz
tar xJf rtems-source-builder-6.1.tar.xz
mv rtems-source-builder-6.1 rsb
# Download RTEMS Sources
wget https://ftp.rtems.org/pub/rtems/releases/6/6.1/sources/rtems-6.1.tar.xz
tar xJf rtems-6.1.tar.xz
# Build ARM A9 BSP
cd rsb/rtems
../source-builder/sb-set-builder --prefix=/rtems/rtems/6 --jobs=10 6/rtems-arm
# Build Kernel
../source-builder/sb-set-builder --prefix=/rtems/rtems/6 --jobs=10 \
--target=arm-rtems6 --with-rtems-bsp=arm/xilinx_zynq_a9_qemu --with-rtems-tests=samples 6/rtems-kernel
# Build Network Stack
git clone -b 6-freebsd-14 https://github.com/RTEMS/rtems-libbsd
cd rtems-libbsd
git submodule init
git submodule update rtems_waf
./waf configure --prefix=/rtems/rtems/6 --rtems-bsps=arm/xilinx_zynq_a9_qemu --buildset=buildset/default.ini
./waf
./waf install
3. Create a project for Safe DDS¶
Start by creating a directory for the Safe DDS project.
mkdir Safe-DDS-RTEMS
cd Safe-DDS-RTEMS
Clone rtems_waf and download the Waf tool:
git clone -b main https://gitlab.rtems.org/rtems/tools/rtems_waf.git rtems_waf
curl https://waf.io/waf-2.0.19 > waf
chmod +x waf
4. Add Safe DDS to the project¶
To add the Safe DDS library to the project follow these steps:
Create a new directory for the Safe-DDS sources in the root of the project. Name the folder something like SafeDDS.
Copy the Safe-DDS src and include folders from the Safe-DDS source release to the SafeDDS folder in the project.
Navigate to the support packages folder and copy the rtems_transport folder to the root of the project.
Safe DDS application¶
With the library in place, the next step is to create the application sources:
1. Add the application files to the project¶
Navigate to the tutorial_rtems folder.
Add the provided HelloWorldTypeSupport.hpp file to a new include folder inside the project root.
Add the provided main.cc and rtems_config.c files to the project root.
2. Configure the build system¶
To configure the project, create a wscript file in the root of the project with the following content.
The script will build all the Safe DDS sources, the RTEMS transport, and two different applications that will communicate with each other.
from __future__ import print_function
import os
rtems_version = '6'
try:
import rtems_waf.rtems as rtems
except BaseException:
print('error: no rtems_waf git submodule')
import sys
sys.exit(1)
def init(ctx):
rtems.init(ctx, version=rtems_version, long_commands=True)
def bsp_configure(conf, arch_bsp):
pass
def options(opt):
rtems.options(opt)
def configure(conf):
rtems.configure(conf, bsp_configure=bsp_configure)
def build(bld):
rtems.build(bld)
# Find the source files
srcs = ['main.cc', 'rtems_config.c']
for root, dirs, files in os.walk('SafeDDS/src'):
if 'transport/posix' in root:
continue
for file in files:
if '.cpp' in file:
srcs.append(os.path.join(root, file))
# Add RTEMS transport files
srcs.append('rtems_transport/src/RTEMSUDPv4.cpp')
srcs.append('rtems_transport/src/transport.cpp')
srcs.append('rtems_transport/src/UDPv4.cpp')
# Build the project for part A
bld(features='cxx cxxprogram',
target='safedds_rtems_poc_A',
cflags='-g -O2',
cxxflags='-g -O2',
includes=[
'SafeDDS/include',
'rtems_transport/include',
'include'],
defines=[
'PART_A',
'SAFEDDS_LOGGING_ENABLED',
'SAFEDDS_LOG_LEVEL=DEBUG'],
lib=['m', 'bsd'],
source=srcs)
# Build the project for part B
bld(features='cxx cxxprogram',
target='safedds_rtems_poc_B',
cflags='-g -O2',
cxxflags='-g -O2',
includes=[
'SafeDDS/include',
'rtems_transport/include',
'include'],
defines=[
'PART_B',
'SAFEDDS_LOGGING_ENABLED',
'SAFEDDS_LOG_LEVEL=DEBUG'],
lib=['m', 'bsd'],
source=srcs)
Running the application on QEMU¶
Build the applications using the Waf commands.
./waf configure --rtems /rtems/rtems/6
./waf
To allow the two executables to communicate with each other while running in QEMU, tap interfaces and QEMUBridge can be set up.
# Set up tap and bridge interfaces
sudo ip link add QEMUBridge0 type bridge
sudo ip link set QEMUBridge0 up
sudo ip tuntap add dev tap0 mode tap
sudo ip link set tap0 up
sudo ip link set tap0 master QEMUBridge0
sudo ip tuntap add dev tap1 mode tap
sudo ip link set tap1 up
sudo ip link set tap1 master QEMUBridge0
Note
If developing in a Docker environment, the network commands should be run on the host system, and the Docker container should have net=host.
Run both applications in separate terminals using QEMU:
qemu-system-arm -serial null -serial mon:stdio -nographic -M xilinx-zynq-a9 -m 256M -net nic,model=cadence_gem -net tap,ifname=tap0,script=no,downscript=no -kernel build/arm-rtems6-xilinx_zynq_a9_qemu/safedds_rtems_poc_A
qemu-system-arm -serial null -serial mon:stdio -nographic -M xilinx-zynq-a9 -m 256M -net nic,model=cadence_gem -net tap,ifname=tap1,script=no,downscript=no -kernel build/arm-rtems6-xilinx_zynq_a9_qemu/safedds_rtems_poc_B
The console output should show messages similar to the following after the QEMU emulation starts:
[DW: 0] Message: HelloWorld with index: 1
[DW: 16777216] Message: HelloWorld with index: 12
[DW: 0] Message: HelloWorld with index: 2
[DW: 16777216] Message: HelloWorld with index: 13
[DW: 0] Message: HelloWorld with index: 3
[DW: 0] Message: HelloWorld with index: 4
[DW: 16777216] Message: HelloWorld with index: 14
[DW: 0] Message: HelloWorld with index: 5
[DW: 16777216] Message: HelloWorld with index: 15
[DW: 0] Message: HelloWorld with index: 6
[DW: 16777216] Message: HelloWorld with index: 16
[DW: 0] Message: HelloWorld with index: 7
[DW: 0] Message: HelloWorld with index: 8
Note
It is also possible to flash the firmware to a compatible board instead of using QEMU. If flashing the firmware to a physical device, run the Getting Started example in a local machine on the same network as the device to test the communications.
Cleanup¶
When finished, cleanup the TAP interfaces:
# Remove TAP interfaces
sudo ip link delete tap0
sudo ip link delete tap1
sudo ip link delete QEMUBridge0