mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-09-22 18:13:46 +08:00
Merge branch 'add_fake_library' into 'stable-1.6'
Add fake library See merge request etherlab.org/ethercat!136
This commit is contained in:
@@ -33,6 +33,7 @@ ethercat.spec
|
||||
examples/dc_user/ec_dc_user_example
|
||||
examples/user/ec_user_example
|
||||
examples/user/build/
|
||||
fake_lib/libfakeethercat.la
|
||||
lib/*.cmake
|
||||
lib/libethercat.la
|
||||
lib/libethercat.pc
|
||||
|
||||
+7
-4
@@ -1,5 +1,5 @@
|
||||
image:
|
||||
registry.gitlab.com/etherlab.org/build-container-factory/leap-15.3:linux-syms
|
||||
registry.gitlab.com/etherlab.org/build-container-factory/leap-15.4:linux-syms
|
||||
|
||||
stages:
|
||||
- build
|
||||
@@ -60,14 +60,14 @@ build:
|
||||
|
||||
script:
|
||||
- ./bootstrap
|
||||
- ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --enable-tty --with-devices=2 --enable-ccat
|
||||
- ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --enable-tty --with-devices=2 --enable-ccat --enable-fakeuserlib
|
||||
- make -j8 all modules
|
||||
- make -C lib symbol-version-check
|
||||
- make DISTCHECK_CONFIGURE_FLAGS="--with-linux-dir=/usr/src/linux-obj/$(uname -i)/default" distcheck
|
||||
- make dist
|
||||
- mkdir test_dist && cd test_dist && tar xzf ../ethercat-*.tar.gz && cd ethercat-*/
|
||||
- mkdir build && cd build
|
||||
- ../configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --disable-8139too --enable-tty --with-devices=2 --enable-ccat
|
||||
- ../configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --disable-8139too --enable-tty --with-devices=2 --enable-ccat --enable-fakeuserlib
|
||||
- make -j8 all modules
|
||||
|
||||
artifacts:
|
||||
@@ -124,8 +124,11 @@ doxygen:
|
||||
# It must be named 'pdf' and must produce a 'pdf' directory as an artifact.
|
||||
# All PDF files in this directory will be collected.
|
||||
pdf:
|
||||
needs:
|
||||
- job: commands
|
||||
artifacts: true
|
||||
stage: doc
|
||||
image: registry.gitlab.com/etherlab.org/build-container-factory/leap-15.3:texlive
|
||||
image: registry.gitlab.com/etherlab.org/build-container-factory/leap-15.4:texlive
|
||||
script:
|
||||
- cd documentation
|
||||
- git show -s --format="\def\revision{%h}\def\gitversion{%(describe)}\def\gittag{%(describe:abbrev=0)}\def\gitauthor{%an}\def\isodate#1-#2-#3x{\day=#3 \month=#2 \year=#1}\isodate %csx" HEAD > git.tex
|
||||
|
||||
+1977
-970
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,11 @@ SUBDIRS += \
|
||||
examples
|
||||
endif
|
||||
|
||||
if ENABLE_FAKEUSERLIB
|
||||
SUBDIRS += \
|
||||
fake_lib
|
||||
endif
|
||||
|
||||
if ENABLE_TTY
|
||||
SUBDIRS += tty
|
||||
endif
|
||||
|
||||
@@ -4,6 +4,10 @@ vim: spelllang=en spell tw=78
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Changes in 1.6.1:
|
||||
|
||||
* Added libfakeethercat to simulate Process Data of EtherCAT Slaves.
|
||||
|
||||
Changes in 1.6.0:
|
||||
|
||||
* Added all native Ethernet drivers for kernels 5.14 and 6.1.
|
||||
|
||||
@@ -15,7 +15,7 @@ Contents:
|
||||
This is an open-source EtherCAT master implementation for Linux 2.6 or newer.
|
||||
|
||||
See the [features file](FEATURES.md) for a list of features. For more
|
||||
information, see http://etherlab.org/en/ethercat.
|
||||
information, see https://etherlab.org/ethercat.
|
||||
|
||||
or contact
|
||||
|
||||
@@ -54,7 +54,7 @@ make doc
|
||||
```
|
||||
|
||||
An up-to-date Doxygen output can be found on
|
||||
[docs.etherlab.org](https://docs.etherlab.org/ethercat/1.5/doxygen/index.html).
|
||||
[docs.etherlab.org](https://docs.etherlab.org/ethercat/1.6/doxygen/index.html).
|
||||
|
||||
# Requirements
|
||||
|
||||
@@ -65,13 +65,20 @@ the EtherCAT master.
|
||||
|
||||
## Hardware requirements
|
||||
|
||||
A table of supported hardware can be found at
|
||||
http://etherlab.org/en/ethercat/hardware.php.
|
||||
A table of supported hardware can be found at:
|
||||
https://docs.etherlab.org/ethercat/1.6/doxygen/devicedrivers.html
|
||||
|
||||
# Building and installing
|
||||
|
||||
See the [install file](INSTALL.md).
|
||||
|
||||
# Dry-run and Field Simulation
|
||||
|
||||
A limited set of the userspace API is available in `libfakeethercat`,
|
||||
a library which can be used to run an userspace application
|
||||
without an EtherCAT master or with emulated EtherCAT slaves.
|
||||
Please find some details [here](fake_lib/README.md).
|
||||
|
||||
# Realtime and Tuning
|
||||
|
||||
Realtime patches for the Linux kernel are supported, but not required. The
|
||||
|
||||
+33
-1
@@ -31,7 +31,7 @@ AC_PREREQ(2.59)
|
||||
# - Update version number below
|
||||
# - make dist-bzip2
|
||||
#
|
||||
AC_INIT([ethercat],[1.6.0],[fp@igh.de])
|
||||
AC_INIT([ethercat],[1.6.1],[fp@igh.de])
|
||||
AC_CONFIG_AUX_DIR([autoconf])
|
||||
AM_INIT_AUTOMAKE([-Wall -Wno-override -Werror dist-bzip2 subdir-objects foreign])
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
@@ -1168,6 +1168,37 @@ fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_USERLIB, test "x$userlib" = "x1")
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Fake Userspace library generation
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
AC_MSG_CHECKING([whether to build the fake userspace library])
|
||||
|
||||
AC_ARG_ENABLE([fakeuserlib],
|
||||
AS_HELP_STRING([--enable-fakeuserlib],
|
||||
[Generation of the userspace library (default: no)]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) fakeuserlib=1
|
||||
;;
|
||||
no) fakeuserlib=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-fakeuserlib])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[fakeuserlib=0]
|
||||
)
|
||||
|
||||
if test "x${fakeuserlib}" = "x1"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
PKG_CHECK_MODULES([RTIPC], [librtipc])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_FAKEUSERLIB, test "x$fakeuserlib" = "x1")
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# TTY driver
|
||||
#-----------------------------------------------------------------------------
|
||||
@@ -1389,6 +1420,7 @@ AC_CONFIG_FILES([
|
||||
examples/user/Makefile
|
||||
examples/xenomai/Makefile
|
||||
examples/xenomai_posix/Makefile
|
||||
fake_lib/Makefile
|
||||
include/Makefile
|
||||
lib/Makefile
|
||||
lib/libethercat.pc
|
||||
|
||||
@@ -351,7 +351,7 @@ Public License (GPL \cite{gpl})\index{GPL}, version 2. Other developers, that
|
||||
want to use EtherCAT with Linux systems, are invited to use the master code or
|
||||
even participate on development.
|
||||
|
||||
To allow static linking of userspace application against the master's
|
||||
To allow dynamic linking of userspace application against the master's
|
||||
application interface (see \autoref{chap:api}), the userspace library (see
|
||||
\autoref{sec:userlib}) is licensed under the terms and conditions of the GNU
|
||||
Lesser General Public License (LGPL \cite{lgpl})\index{LGPL}, version 2.1.
|
||||
@@ -962,8 +962,8 @@ be found.
|
||||
The application interface of the EtherCAT master is defined in the header file
|
||||
\textit{include/ecrt.h} (acronym for ``EtherCAT Real-Time'') which is listed
|
||||
in this section. The calling conventions of all methods are documented in the
|
||||
comments of this header. There is also a Doxygen-generated online version at
|
||||
\url{https://docs.etherlab.org}.
|
||||
comments of this header. There is also a Doxygen-generated \cite{doxygen}
|
||||
online version at \url{https://docs.etherlab.org}.
|
||||
|
||||
\lstinputlisting[
|
||||
basicstyle=\ttfamily\scriptsize,
|
||||
@@ -2709,6 +2709,10 @@ installation prefix as \textit{libethercat.a} (for static linking),
|
||||
\textit{libethercat.la} (for the use with \textit{libtool}) and
|
||||
\textit{libethercat.so} (for dynamic linking).
|
||||
|
||||
For running an application without actual EtherCAT hardware or for simulation
|
||||
purposes, there is a special library called \textit{libfakeethercat} (see
|
||||
\autoref{sec:fakelib}).
|
||||
|
||||
\subsection{Using the Library}
|
||||
|
||||
The application interface header \textit{ecrt.h} (see \autoref{sec:ecrt}) can
|
||||
@@ -2750,6 +2754,9 @@ gcc -static ectest.c -o ectest -I/opt/etherlab/include \
|
||||
/opt/etherlab/lib/libethercat.a
|
||||
\end{lstlisting}
|
||||
|
||||
Please keep in mind, that your application has to be licensed under GPLv2
|
||||
then, because the LGPL does only allow dynamic linking.
|
||||
|
||||
\subsection{Implementation}
|
||||
\label{sec:userimp}
|
||||
|
||||
@@ -2836,6 +2843,33 @@ The test results show, that for this configuration, the userspace API causes
|
||||
about \unit{1}{\micro\second} additional delay for each function, compared to
|
||||
the kernel API.
|
||||
|
||||
\subsection{Simulation / Fake Library}
|
||||
\label{sec:fakelib}
|
||||
|
||||
Sometimes is is handy to run your EtherCAT realtime application without an
|
||||
actual EtherCAT network connected, for example for test purposes.
|
||||
Though it is possible to spin up an EtherCAT master and to connect it to a
|
||||
loopback device, this step is not always wanted.
|
||||
|
||||
The EtherCAT master (since version 1.6.1) comes with a library
|
||||
\textit{libfakeethercat} that comes with a reasonable subset of the EtherCAT
|
||||
application interface (see \autoref{chap:api}).
|
||||
|
||||
The \texttt{ecrt} method implementation in the fake library will just accept
|
||||
your input and behave as if everything would be fine. Without further steps,
|
||||
the process data will be all-zero then.
|
||||
|
||||
As a special feature, the \textit{libfakeethercat} will create RtIPC
|
||||
\cite{rtipc} endpoints for registered PDO entries to enable a simulation
|
||||
interface. Another application that either uses RtIPC directly or another
|
||||
(inverted) instance of \textit{libfakeethercat} will then connect to these
|
||||
endpoints and thus create the possibility to provide simulated values to your
|
||||
pristine application.
|
||||
|
||||
The fake library functions an usage is documented in Doxygen~\cite{doxygen}
|
||||
and the most recent version can be found online:
|
||||
\url{https://docs.etherlab.org/ethercat/1.6/doxygen/libfakeethercat.html}
|
||||
|
||||
%------------------------------------------------------------------------------
|
||||
|
||||
\section{RTDM Interface}
|
||||
@@ -3547,6 +3581,9 @@ Applications.
|
||||
\url{http://svn.gna.org/svn/xenomai/tags/v2.4.0/doc/nodist/pdf/RTDM-and-Applications.pdf},
|
||||
2013.
|
||||
|
||||
\bibitem{rtipc} Real-Time Inter-Process-Communication library. Part of the
|
||||
EtherLab toolkit. \url{https://gitlab.com/etherlab.org/rtipc}, 2024.
|
||||
|
||||
\end{thebibliography}
|
||||
|
||||
\printnomenclature
|
||||
|
||||
@@ -3440,7 +3440,7 @@ Il y a plusieurs mani\`eres d'obtenir le logiciel du ma\^itre:
|
||||
|
||||
\item Une version officielle (par exemple \masterversion) peut \^etre
|
||||
t\'el\'echarg\'ee depuis le site web du
|
||||
ma\^itre\footnote{\url{http://etherlab.org/en/ethercat/index.php}}
|
||||
ma\^itre\footnote{\url{https://etherlab.org/ethercat}}
|
||||
dans le projet EtherLab~\cite{etherlab} sous forme d'archive tar.
|
||||
|
||||
\item La r\'evision de d\'eveloppement la plus r\'ecente (mais aussi
|
||||
@@ -3793,7 +3793,7 @@ KERNEL=="EtherCAT[0-9]*", MODE="0664", GROUP="users"
|
||||
|
||||
\bibitem{etherlab} Ingenieurgemeinschaft IgH: EtherLab -- Open Source Toolkit
|
||||
for rapid realtime code generation under Linux with Simulink/RTW and EtherCAT
|
||||
technology. \url{http://etherlab.org/en}, 2008.
|
||||
technology. \url{https://etherlab.org}, 2024.
|
||||
|
||||
\bibitem{dlspec} IEC 61158-4-12: Data-link Protocol Specification.
|
||||
International Electrotechnical Commission (IEC), 2005.
|
||||
|
||||
+3
-3
@@ -26,7 +26,7 @@ Version: @VERSION@
|
||||
Release: 1
|
||||
|
||||
License: GPL
|
||||
URL: http://etherlab.org/en/ethercat
|
||||
URL: https://etherlab.org/ethercat
|
||||
|
||||
Provides: @PACKAGE@
|
||||
Source: %{name}-%{version}.tar.bz2
|
||||
@@ -44,7 +44,7 @@ Group: EtherLab
|
||||
%description
|
||||
This is an open-source EtherCAT master implementation for Linux 2.6. See the
|
||||
FEATURES file for a list of features. For more information, see
|
||||
http://etherlab.org/en/ethercat.
|
||||
https://etherlab.org/ethercat.
|
||||
|
||||
%kernel_module_package
|
||||
|
||||
@@ -60,7 +60,7 @@ Group: EtherLab
|
||||
%description devel
|
||||
This is an open-source EtherCAT master implementation for Linux 2.6. See the
|
||||
FEATURES file for a list of features. For more information, see
|
||||
http://etherlab.org/en/ethercat.
|
||||
https://etherlab.org/ethercat.
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
#
|
||||
# This file is part of the IgH EtherCAT master userspace library.
|
||||
#
|
||||
# The IgH EtherCAT master userspace library is free software; you can
|
||||
# redistribute it and/or modify it under the terms of the GNU Lesser General
|
||||
# Public License as published by the Free Software Foundation; version 2.1 of
|
||||
# the License.
|
||||
#
|
||||
# The IgH EtherCAT master userspace library is distributed in the hope that
|
||||
# it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with the IgH EtherCAT master userspace library. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
lib_LTLIBRARIES = libfakeethercat.la
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
libfakeethercat_la_SOURCES = \
|
||||
fakeethercat.cpp
|
||||
|
||||
noinst_HEADERS = \
|
||||
fakeethercat.h
|
||||
|
||||
libfakeethercat_la_CXXFLAGS = \
|
||||
-fno-strict-aliasing \
|
||||
-Wall \
|
||||
-I$(top_srcdir)/include \
|
||||
-Dethercat_EXPORTS \
|
||||
-fvisibility=hidden \
|
||||
$(RTIPC_CFLAGS)
|
||||
|
||||
libfakeethercat_la_LDFLAGS = -version-info 3:0:2 \
|
||||
$(RTIPC_LIBS) \
|
||||
-Wl,--version-script=$(srcdir)/../lib/libethercat.map \
|
||||
-fvisibility=hidden
|
||||
|
||||
libfakeethercat_la_DEPENDENCIES = ../lib/libethercat.map
|
||||
@@ -0,0 +1,133 @@
|
||||
FakeEtherCAT Library {#libfakeethercat}
|
||||
====================
|
||||
|
||||
Libfakeethercat is a userspace library which has the same API as
|
||||
the EtherCAT master interface library libethercat.
|
||||
Libfakeethercat can be used to spin up your RT application in a dry-run mode,
|
||||
without any master configured or slaves attached.
|
||||
Furthermore, it is possible to emulate EtherCAT slaves on process data level
|
||||
by running two applications back to back.
|
||||
|
||||
## Supported features
|
||||
|
||||
Currently, only a very limited subset of libethercat functionality is supported:
|
||||
|
||||
- Creating master and domain instances
|
||||
- Activating master, `send`/`receive`.
|
||||
- Processing and queuing domains
|
||||
- Configuring PDOs
|
||||
- Configuring SDOs using `ecrt_slave_config_sdo*`
|
||||
|
||||
The SDO config does not do anything,
|
||||
but when activating the master the SDO config will
|
||||
be dumped into a JSON file.
|
||||
|
||||
ecrt_master_state() and ecrt_domain_state() both return states as if
|
||||
the bus works without errors.
|
||||
So currenty, a bus error cannot be simulated.
|
||||
|
||||
## How to build
|
||||
|
||||
[RtIPC](https://gitlab.com/etherlab.org/rtipc) is needed.
|
||||
Simply pass `--enable-fakeuserlib` to your `./configure` call
|
||||
and the library will be built for you.
|
||||
|
||||
## How to set up dry run mode
|
||||
|
||||
### Redirect library loading
|
||||
|
||||
To avoid recompiling your application,
|
||||
we will use `LD_LIBRARY_PATH` to load `libfakeethercat` instead of `libethercat`.
|
||||
|
||||
```sh
|
||||
# pick a location for an empty directory
|
||||
export MY_LIB_LOCATION=$HOME/fake_lib64
|
||||
# create that directory
|
||||
mkdir -p $MY_LIB_LOCATION
|
||||
# create a symlink to libfakeethercat
|
||||
# assuming SOVERSION is 1
|
||||
# debian users, please use /usr/lib/x86_64-linux-gnu/libfakeethercat.so.1
|
||||
ln -s /usr/lib64/libfakeethercat.so.1 $MY_LIB_LOCATION/libethercat.so.1
|
||||
# use MY_LIB_LOCATION to load libraries first
|
||||
export LD_LIBRARY_PATH=$MY_LIB_LOCATION
|
||||
# check whether everything is done right
|
||||
ldd my_application | grep ethercat
|
||||
libethercat.so.1 => /home/vh/fake_lib64/libethercat.so.1 (0x00007fa5a5c59000)
|
||||
```
|
||||
|
||||
### Set up FakeEtherCAT Home
|
||||
|
||||
RtIPC needs a place to store its configuration.
|
||||
Set `FAKE_EC_HOMEDIR` environment variabe to a path to an empty directory,
|
||||
for instance `/tmp/FakeEtherCAT`.
|
||||
`FAKE_EC_NAME` can be set to a useful name of your application,
|
||||
default is `FakeEtherCAT`.
|
||||
|
||||
```sh
|
||||
export FAKE_EC_HOMEDIR=/tmp/FakeEtherCAT
|
||||
rm -rf $FAKE_EC_HOMEDIR
|
||||
mkdir -p $FAKE_EC_HOMEDIR
|
||||
```
|
||||
|
||||
### Spin up your application
|
||||
|
||||
Now it's time to simply launch your application.
|
||||
You will notice that the PDO configuration will be dumped at stderr.
|
||||
The path displayed is the path of the RtIPC variable in the following format:
|
||||
`$FAKE_EC_PREFIX/$MASTER_ID/$DOMAIN_ID/$ALIAS$POSITION/$PDO`.
|
||||
|
||||
## How to emulate EtherCAT slaves
|
||||
|
||||
Let's say you'd like to build virtual EtherCAT slaves to emulate your field.
|
||||
Libfakeethercat makes that possible with the help of RtIPC.
|
||||
|
||||
### Building a simulator
|
||||
|
||||
Your field emulator simply has to swap the sync manager direction setting
|
||||
(EC_DIR_INPUT and EC_DIR_OUTPUT) in ec_sync_info_t.
|
||||
Libfakeethercat instances use shared memory, provided by RtIPC,
|
||||
to exchange process data.
|
||||
The direction setting decides which instance writes and which reads from
|
||||
shared memory.
|
||||
|
||||
For instance, emulating a digial output works in the following way:
|
||||
Create another real time application with the same slave information
|
||||
as your control application.
|
||||
Then, replace all EC_DIR_INPUT with EC_DIR_OUTPUT and vice versa.
|
||||
Now, remember to read process data instead of writing it, and vice versa.
|
||||
So, your EL2004 digital out will be read by your simulating application
|
||||
and has PDO object 0x1600 ff. configured with Sync Manager 2 as EC_DIR_INPUT.
|
||||
|
||||
[EtherLab](https://gitlab.com/etherlab.org/etherlab) provides
|
||||
a convenient way to build an entire simulator using SIMULINK since
|
||||
Version 2.4.0.
|
||||
Run `web(etherlab_help_path('swap_io.html'), '-helpbrowser')`
|
||||
in your MATLAB shell to read more about how to set up a
|
||||
Process Data simulator.
|
||||
|
||||
### Start your application
|
||||
|
||||
First, do all the steps explained above to run your
|
||||
control application in dry run mode.
|
||||
Then, in another shell, do the same thing with your simulator,
|
||||
but do not remove the `FAKE_EC_HOMEDIR` directory and
|
||||
pick another `FAKE_EC_NAME`.
|
||||
|
||||
Carefully watch the PDO configuration on stderr and compare them.
|
||||
All paths configured as Output on the control application have to
|
||||
be configured as Input on your simulator and vice versa.
|
||||
If you use multiple domains and there is a mismatch of the domain IDs,
|
||||
set `FAKE_EC_DOMAIN_PERMUTATION` to a space-separated list of integers to
|
||||
permutate the domain IDs of one application.
|
||||
`FAKE_EC_DOMAIN_PERMUTATION="0 1"` swaps domains 0 and 1, for instance.
|
||||
|
||||
Finally, your control application needs to be restarted
|
||||
so it can find the RtIPC variables which contains the process data of the
|
||||
simulator.
|
||||
|
||||
## Environment variables
|
||||
|
||||
- FAKE_EC_DOMAIN_PERMUTATION: Permutate the domain IDs, useful to match control and simulation applications.
|
||||
- FAKE_EC_HOMEDIR: Directory for RtIPC builletin board and SDO json files
|
||||
- FAKE_EC_NAME: Will be used for naming RtIPC config and SDO json file
|
||||
- FAKE_EC_PREFIX: Prefix for RtIPC variables, useful to run multiple simulators side by side.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,228 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2024 Bjarne von Horn, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
* This file is part of the IgH EtherCAT master userspace library.
|
||||
*
|
||||
* The IgH EtherCAT master userspace library is free software; you can
|
||||
* redistribute it and/or modify it under the terms of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation; version 2.1
|
||||
* of the License.
|
||||
*
|
||||
* The IgH EtherCAT master userspace library is distributed in the hope that
|
||||
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the IgH EtherCAT master userspace library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ecrt.h>
|
||||
#include <rtipc.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct Offset
|
||||
{
|
||||
int bytes;
|
||||
int bits;
|
||||
|
||||
constexpr Offset(int bytes,
|
||||
int bits) : bytes(bytes), bits(bits) {}
|
||||
|
||||
constexpr bool operator!=(const Offset &other) const noexcept
|
||||
{
|
||||
return bytes != other.bytes || bits != other.bits;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr Offset NotFound(-1, -1);
|
||||
|
||||
struct pdo
|
||||
{
|
||||
std::vector<ec_pdo_entry_info_t> entries;
|
||||
|
||||
size_t sizeInBytes() const;
|
||||
|
||||
Offset findEntry(uint16_t idx, uint8_t subindex) const;
|
||||
};
|
||||
|
||||
struct syncManager
|
||||
{
|
||||
ec_direction_t dir;
|
||||
std::map<uint16_t /* address */, pdo> pdos;
|
||||
};
|
||||
|
||||
class ec_address
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
public:
|
||||
ec_address(uint16_t alias, /**< Slave alias. */
|
||||
uint16_t position /**< Slave position. */)
|
||||
: value(static_cast<uint32_t>(alias) << 16 | position)
|
||||
{
|
||||
}
|
||||
|
||||
uint16_t getAlias() const { return value >> 16; }
|
||||
uint16_t getPosition() const { return value & 0xFFFF; }
|
||||
uint32_t getCombined() const { return value; }
|
||||
|
||||
bool operator<(const ec_address &other) const noexcept
|
||||
{
|
||||
return value < other.value;
|
||||
}
|
||||
|
||||
bool operator==(const ec_address &other) const noexcept
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class sdo_address
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
public:
|
||||
sdo_address(uint16_t index, /**< Slave alias. */
|
||||
uint8_t subindex /**< Slave position. */)
|
||||
: value(static_cast<uint32_t>(index) << 8 | subindex)
|
||||
{
|
||||
}
|
||||
|
||||
uint16_t getIndex() const { return value >> 8; }
|
||||
uint8_t getSubIndex() const { return value & 0xFF; }
|
||||
uint32_t getCombined() const { return value; }
|
||||
|
||||
bool operator<(const sdo_address &other) const noexcept
|
||||
{
|
||||
return value < other.value;
|
||||
}
|
||||
|
||||
bool operator==(const sdo_address &other) const noexcept
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
};
|
||||
|
||||
struct ec_slave_config
|
||||
{
|
||||
ec_address address;
|
||||
uint32_t vendor_id; /**< Expected vendor ID. */
|
||||
uint32_t product_code; /**< Expected product code. */
|
||||
std::map<unsigned int, syncManager> sync_managers;
|
||||
std::map<sdo_address, std::basic_string<uint8_t>> sdos;
|
||||
|
||||
ec_slave_config(
|
||||
ec_address address,
|
||||
uint32_t vendor_id, /**< Expected vendor ID. */
|
||||
uint32_t product_code /**< Expected product code. */)
|
||||
: address(address), vendor_id(vendor_id), product_code(product_code)
|
||||
{
|
||||
}
|
||||
|
||||
void dumpJson(std::ostream &out, int indent) const;
|
||||
};
|
||||
|
||||
struct ec_domain
|
||||
{
|
||||
|
||||
private:
|
||||
struct PdoMap
|
||||
{
|
||||
size_t offset;
|
||||
size_t size_bytes;
|
||||
ec_address slave_address;
|
||||
unsigned int syncManager;
|
||||
uint16_t pdo_index;
|
||||
ec_direction_t dir;
|
||||
|
||||
PdoMap(
|
||||
size_t offset,
|
||||
size_t size_bytes,
|
||||
ec_address slave_address,
|
||||
unsigned int syncManager,
|
||||
uint16_t pdo_index,
|
||||
ec_direction_t dir)
|
||||
: offset(offset), size_bytes(size_bytes), slave_address(slave_address), syncManager(syncManager), pdo_index(pdo_index), dir(dir)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
std::vector<unsigned char> connected;
|
||||
std::vector<PdoMap> mapped_pdos;
|
||||
rtipc_group *rt_group;
|
||||
const char *prefix;
|
||||
ec_master_t *master;
|
||||
bool activated_ = false;
|
||||
size_t numSlaves = 0;
|
||||
|
||||
public:
|
||||
explicit ec_domain(struct rtipc *rtipc, const char *prefix, ec_master_t *master);
|
||||
|
||||
uint8_t *getData() const
|
||||
{
|
||||
if (!activated_)
|
||||
return nullptr;
|
||||
return const_cast<uint8_t *>(data.data());
|
||||
}
|
||||
|
||||
int activate(int domain_id);
|
||||
int process();
|
||||
int queue();
|
||||
|
||||
size_t getNumSlaves() const { return numSlaves; }
|
||||
|
||||
ssize_t map(ec_slave_config const &config, unsigned int syncManager,
|
||||
uint16_t pdo_index);
|
||||
|
||||
ec_master_t *getMaster() const { return master; }
|
||||
};
|
||||
|
||||
struct ec_master
|
||||
{
|
||||
private:
|
||||
struct RtIpcDeleter
|
||||
{
|
||||
void operator()(struct rtipc *r) const
|
||||
{
|
||||
rtipc_exit(r);
|
||||
}
|
||||
};
|
||||
|
||||
std::string rt_ipc_dir;
|
||||
std::string rt_ipc_name;
|
||||
std::list<ec_domain> domains;
|
||||
std::map<ec_address, ec_slave_config> slaves;
|
||||
std::unique_ptr<struct rtipc, RtIpcDeleter> rt_ipc;
|
||||
int id_;
|
||||
|
||||
public:
|
||||
explicit ec_master(int id);
|
||||
|
||||
int activate();
|
||||
ec_domain *createDomain();
|
||||
|
||||
int getNoSlaves() const { return slaves.size(); }
|
||||
int getId() const { return id_; }
|
||||
|
||||
ec_slave_config_t *slave_config(
|
||||
uint16_t alias, /**< Slave alias. */
|
||||
uint16_t position, /**< Slave position. */
|
||||
uint32_t vendor_id, /**< Expected vendor ID. */
|
||||
uint32_t product_code /**< Expected product code. */
|
||||
);
|
||||
};
|
||||
@@ -82,6 +82,9 @@ LIBETHERCAT_1.5.2 {
|
||||
ecrt_voe_handler_received_header;
|
||||
ecrt_voe_handler_send_header;
|
||||
ecrt_voe_handler_write;
|
||||
local:
|
||||
# Hide all C++ symbols in libfakeethercat
|
||||
_Z*;
|
||||
};
|
||||
|
||||
LIBETHERCAT_1.5.3 {
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
A list of all native network card drivers can be found
|
||||
<a href="devicedrivers.html">here</a>.
|
||||
|
||||
A <a href="libfakeethercat.html">second userspace library</a> can be used for a dry-run mode
|
||||
or simulating Process Data.
|
||||
|
||||
For information how to build and install, see the INSTALL file in the source
|
||||
root.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user