diff --git a/.hgignore b/.hgignore
index c5d9806d..e71d8ebb 100644
--- a/.hgignore
+++ b/.hgignore
@@ -32,6 +32,48 @@ devices/e1000/Kbuild
devices/e1000/Makefile
devices/e1000/Makefile.in
devices/modules.order
+documentation/ethercat_doc.aux
+documentation/ethercat_doc.idx
+documentation/ethercat_doc.lof
+documentation/ethercat_doc.log
+documentation/ethercat_doc.lot
+documentation/ethercat_doc.nlo
+documentation/ethercat_doc.out
+documentation/ethercat_doc.pdf
+documentation/ethercat_doc.toc
+documentation/external
+documentation/graphs/fsm_change.pdf
+documentation/graphs/fsm_change.ps
+documentation/graphs/fsm_eoe.pdf
+documentation/graphs/fsm_eoe.ps
+documentation/graphs/fsm_master.pdf
+documentation/graphs/fsm_master.ps
+documentation/graphs/fsm_pdo_conf.pdf
+documentation/graphs/fsm_pdo_conf.ps
+documentation/graphs/fsm_pdo_entry_conf.pdf
+documentation/graphs/fsm_pdo_entry_conf.ps
+documentation/graphs/fsm_pdo_entry_read.pdf
+documentation/graphs/fsm_pdo_entry_read.ps
+documentation/graphs/fsm_pdo_read.pdf
+documentation/graphs/fsm_pdo_read.ps
+documentation/graphs/fsm_sii.pdf
+documentation/graphs/fsm_sii.ps
+documentation/graphs/fsm_slave_conf.pdf
+documentation/graphs/fsm_slave_conf.ps
+documentation/graphs/fsm_slave_scan.pdf
+documentation/graphs/fsm_slave_scan.ps
+documentation/images/app-config.pdf
+documentation/images/architecture.pdf
+documentation/images/attach.pdf
+documentation/images/dc.pdf
+documentation/images/fmmus.pdf
+documentation/images/fsm-coedown.pdf
+documentation/images/fsm-eoe.pdf
+documentation/images/interrupt.pdf
+documentation/images/master-locks.pdf
+documentation/images/masters.pdf
+documentation/images/phases.pdf
+documentation/images/statetrans.pdf
examples/Kbuild
examples/Makefile
examples/Makefile.in
diff --git a/FEATURES b/FEATURES
index 99a503e1..123a01c9 100644
--- a/FEATURES
+++ b/FEATURES
@@ -14,13 +14,16 @@ General Features:
- Runs as kernel module for Linux 2.6.
- Multiple masters possible on one machine.
-* EtherCAT-capable versions of standard Linux drivers for wide-spread
- Ethernet devices.
- - Interrupt-less operation of Ethernet devices.
- - Easy implementation of additional Ethernet drivers through common device
- interface.
+* Native EtherCAT-capable versions of standard Linux drivers for wide-spread
+ Ethernet devices, as well as a generic driver for all chips supported by the
+ Linux kernel.
+ - Interrupt-less operation of Ethernet devices when using native drivers.
+ - Easy implementation of additional native Ethernet drivers through common
+ device interface.
- Operation possible with any device supported by the standard drivers,
including PCMCIA devices.
+ - For any other hardware, the generic driver can be used. It uses the lower
+ layers of the Linux network stack.
* Supports any realtime environment through independent architecture.
- RTAI, Xenomai, RT-Preempt, etc.
diff --git a/documentation/ethercat_doc.tex b/documentation/ethercat_doc.tex
index 91c6f59f..31282cc0 100644
--- a/documentation/ethercat_doc.tex
+++ b/documentation/ethercat_doc.tex
@@ -16,7 +16,7 @@
\usepackage{makeidx}
\usepackage[refpage]{nomencl}
\usepackage{listings}
-\usepackage{svn}
+\usepackage[nofancy]{rcsinfo}
\usepackage{SIunits}
\usepackage{amsmath} % for \text{}
\usepackage{hyperref}
@@ -62,8 +62,7 @@
\newcommand{\IgH}{\raisebox{-0.7667ex}
{\includegraphics[height=2.2ex]{images/ighsign}}}
-\SVN $Date$
-\SVN $Revision$
+\rcsInfo $RCSId$
\newcommand{\masterversion}{1.5.0}
\newcommand{\linenum}[1]{\normalfont\textcircled{\tiny #1}}
@@ -71,6 +70,10 @@
\makeindex
\makenomenclature
+% Revision and date on inner footer
+\ifoot[\scriptsize\rcsInfoRevision, \rcsInfoDate]
+ {\scriptsize\rcsInfoRevision, \rcsInfoDate}
+
%------------------------------------------------------------------------------
\begin{document}
@@ -84,7 +87,7 @@
{\Huge\bf IgH \includegraphics[height=2.4ex]{images/ethercat}
Master \masterversion\\[1ex]
- Preliminary Documentation}
+ Documentation}
\vspace{1ex}
\rule{\textwidth}{1.5mm}
@@ -93,13 +96,15 @@
\url{fp@igh-essen.com}\\[1ex] Ingenieurgemeinschaft \IgH}
\vspace{\fill}
- {\Large Essen, \SVNDate\\[1ex]
- Revision \SVNRevision}
+ {\Large Essen, \rcsInfoLongDate\\[1ex]
+ Revision \rcsInfoRevision}
\end{center}
\end{titlepage}
%------------------------------------------------------------------------------
+\pagestyle{scrplain}
+
\tableofcontents
\listoftables
\listoffigures
@@ -172,15 +177,20 @@ The list below gives a short summary of the master features.
\item Implemented according to IEC 61158-12 \cite{dlspec} \cite{alspec}.
-\item Comes with EtherCAT-capable drivers for several common Ethernet devices.
+\item Comes with EtherCAT-capable native drivers for several common Ethernet
+chips, as well as a generic driver for all chips supported by the Linux
+kernel.
\begin{itemize}
- \item The Ethernet hardware is operated without interrupts.
+ \item The native drivers operate the hardware without interrupts.
- \item Drivers for additional Ethernet hardware can easily be implemented
- using the common device interface (see sec.~\ref{sec:ecdev}) provided by the
- master module.
+ \item Native drivers for additional Ethernet hardware can easily be
+ implemented using the common device interface (see sec.~\ref{sec:ecdev})
+ provided by the master module.
+
+ \item For any other hardware, the generic driver can be used. It uses the
+ lower layers of the Linux network stack.
\end{itemize}
@@ -192,9 +202,9 @@ independent architecture.
\begin{itemize}
- \item RTAI\nomenclature{RTAI}{Realtime Application Interface},
+ \item RTAI\nomenclature{RTAI}{Realtime Application Interface} \cite{rtai},
ADEOS\nomenclature{ADEOS}{Adaptive Domain Environment for Operating
- Systems}, etc.
+ Systems}, RT-Preempt \cite{rt-preempt}, etc.
\item It runs well even without realtime extensions.
@@ -362,7 +372,7 @@ Figure~\ref{fig:arch} gives a general overview of the master architecture.
\begin{figure}[htbp]
\centering
- \includegraphics[width=.9\textwidth]{images/architecture}
+ \includegraphics[width=\textwidth]{images/architecture}
\caption{Master Architecture}
\label{fig:arch}
\end{figure}
@@ -933,8 +943,29 @@ The EtherCAT protocol is based on the Ethernet standard, so a master relies on
standard Ethernet hardware to communicate with the bus.
The term \textit{device} is used as a synonym for Ethernet network interface
-hardware. There are device driver modules that handle Ethernet hardware, which
-a master can use to connect to an EtherCAT bus.
+hardware.
+
+\paragraph{Native Ethernet Device Drivers} There are native device driver
+modules (see sec.~\ref{sec:native-drivers}) that handle Ethernet hardware,
+which a master can use to connect to an EtherCAT bus. They offer their
+Ethernet hardware to the master module via the device interface (see
+sec.~\ref{sec:ecdev}) and must be capable to prepare Ethernet devices either
+for EtherCAT (realtime) operation or for ``normal'' operation using the
+kernel's network stack. The advantage of this approach is that the master can
+operate nearly directly on the hardware, which allows a high performance. The
+disadvantage is, that there has to be an EtherCAT-capable version of the
+original Ethernet driver.
+
+\paragraph{Generic Ethernet Device Driver} From master version 1.5, there is a
+generic Ethernet device driver module (see sec.~\ref{sec:generic-driver}),
+that uses the lower layers of the network stack to connect to the hardware.
+The advantage is, that arbitrary Ethernet hardware can be used for EtherCAT
+operation, independently of the actual hardware driver (so all Linux Ethernet
+drivers are supported without modifications). The disadvantage is, that this
+approach does not support realtime extensions like RTAI, because the Linux
+network stack is addressed. Moreover the performance is a little worse than
+the native approach, because the Ethernet frame data have to traverse the
+network stack.
%------------------------------------------------------------------------------
@@ -947,52 +978,44 @@ Ethernet device to communicate with the bus. Therefore it is necessary
to understand how Linux handles network devices and their drivers,
respectively.
-\paragraph{Tasks of a Network Driver}
+\paragraph{Tasks of a Network Driver} Network device drivers usually handle
+the lower two layers of the OSI model, that is the physical layer and the
+data-link layer. A network device itself natively handles the physical layer
+issues: It represents the hardware to connect to the medium and to send and
+receive data in the way, the physical layer protocol describes. The network
+device driver is responsible for getting data from the kernel's networking
+stack and forwarding it to the hardware, that does the physical transmission.
+If data is received by the hardware respectively, the driver is notified
+(usually by means of an interrupt) and has to read the data from the hardware
+memory and forward it to the network stack. There are a few more tasks, a
+network device driver has to handle, including queue control, statistics and
+device dependent features.
-Network device drivers usually handle the lower two layers of the OSI model,
-that is the physical layer and the data-link layer. A network device itself
-natively handles the physical layer issues: It represents the hardware to
-connect to the medium and to send and receive data in the way, the physical
-layer protocol describes. The network device driver is responsible for getting
-data from the kernel's networking stack and forwarding it to the hardware,
-that does the physical transmission. If data is received by the hardware
-respectively, the driver is notified (usually by means of an interrupt) and
-has to read the data from the hardware memory and forward it to the network
-stack. There are a few more tasks, a network device driver has to handle,
-including queue control, statistics and device dependent features.
+\paragraph{Driver Startup} Usually, a driver searches for compatible devices
+on module loading. For PCI drivers, this is done by scanning the PCI bus and
+checking for known device IDs. If a device is found, data structures are
+allocated and the device is taken into operation.
-\paragraph{Driver Startup}
+\paragraph{Interrupt Operation}\index{Interrupt} A network device usually
+provides a hardware interrupt that is used to notify the driver of received
+frames and success of transmission, or errors, respectively. The driver has to
+register an interrupt service routine
+(ISR\index{ISR}\nomenclature{ISR}{Interrupt Service Routine}), that is
+executed each time, the hardware signals such an event. If the interrupt was
+thrown by the own device (multiple devices can share one hardware interrupt),
+the reason for the interrupt has to be determined by reading the device's
+interrupt register. For example, if the flag for received frames is set, frame
+data has to be copied from hardware to kernel memory and passed to the network
+stack.
-Usually, a driver searches for compatible devices on module loading.
-For PCI drivers, this is done by scanning the PCI bus and checking for
-known device IDs. If a device is found, data structures are allocated
-and the device is taken into operation.
-
-\paragraph{Interrupt Operation}
-\index{Interrupt}
-
-A network device usually provides a hardware interrupt that is used to
-notify the driver of received frames and success of transmission, or
-errors, respectively. The driver has to register an interrupt service
-routine (ISR\index{ISR}\nomenclature{ISR}{Interrupt Service Routine}),
-that is executed each time, the hardware signals such an event. If the
-interrupt was thrown by the own device (multiple devices can share one
-hardware interrupt), the reason for the interrupt has to be determined
-by reading the device's interrupt register. For example, if the flag
-for received frames is set, frame data has to be copied from hardware
-to kernel memory and passed to the network stack.
-
-\paragraph{The \lstinline+net_device+ Structure}
-\index{net\_device}
-
-The driver registers a \lstinline+net_device+ structure for each device to
-communicate with the network stack and to create a ``network interface''. In
-case of an Ethernet driver, this interface appears as \textit{ethX}, where X
-is a number assigned by the kernel on registration. The \lstinline+net_device+
-structure receives events (either from userspace or from the network stack)
-via several callbacks, which have to be set before registration. Not every
-callback is mandatory, but for reasonable operation the ones below are needed
-in any case:
+\paragraph{The \lstinline+net_device+ Structure}\index{net\_device} The driver
+registers a \lstinline+net_device+ structure for each device to communicate
+with the network stack and to create a ``network interface''. In case of an
+Ethernet driver, this interface appears as \textit{ethX}, where X is a number
+assigned by the kernel on registration. The \lstinline+net_device+ structure
+receives events (either from userspace or from the network stack) via several
+callbacks, which have to be set before registration. Not every callback is
+mandatory, but for reasonable operation the ones below are needed in any case:
\newsavebox\boxopen
\sbox\boxopen{\lstinline+open()+}
@@ -1027,17 +1050,15 @@ error happened, the appropriate counter in this structure has to be increased.
The actual registration is done with the \lstinline+register_netdev()+ call,
unregistering is done with \lstinline+unregister_netdev()+.
-\paragraph{The \lstinline+netif+ Interface}
-\index{netif}
-
-All other communication in the direction interface $\to$ network stack is done
-via the \lstinline+netif_*()+ calls. For example, on successful device opening,
-the network stack has to be notified, that it can now pass frames to the
+\paragraph{The \lstinline+netif+ Interface}\index{netif} All other
+communication in the direction interface $\to$ network stack is done via the
+\lstinline+netif_*()+ calls. For example, on successful device opening, the
+network stack has to be notified, that it can now pass frames to the
interface. This is done by calling \lstinline+netif_start_queue()+. After this
call, the \lstinline+hard_start_xmit()+ callback can be called by the network
-stack. Furthermore a network driver usually manages a frame transmission queue.
-If this gets filled up, the network stack has to be told to stop passing
-further frames for a while. This happens with a call to
+stack. Furthermore a network driver usually manages a frame transmission
+queue. If this gets filled up, the network stack has to be told to stop
+passing further frames for a while. This happens with a call to
\lstinline+netif_stop_queue()+. If some frames have been sent, and there is
enough space again to queue new frames, this can be notified with
\lstinline+netif_wake_queue()+. Another important call is
@@ -1049,48 +1070,42 @@ network performance on Linux. Read more in
network stack, that was just received by the device. Frame data has to be
included in a so-called ``socket buffer'' for that (see below).
-\paragraph{Socket Buffers}
-\index{Socket buffer}
-
-Socket buffers are the basic data type for the whole network stack. They serve
-as containers for network data and are able to quickly add data headers and
-footers, or strip them off again. Therefore a socket buffer consists of an
-allocated buffer and several pointers that mark beginning of the buffer
-(\lstinline+head+), beginning of data (\lstinline+data+), end of data
-(\lstinline+tail+) and end of buffer (\lstinline+end+). In addition, a socket
-buffer holds network header information and (in case of received data) a
-pointer to the \lstinline+net_device+, it was received on. There exist
-functions that create a socket buffer (\lstinline+dev_alloc_skb()+), add data
-either from front (\lstinline+skb_push()+) or back (\lstinline+skb_put()+),
-remove data from front (\lstinline+skb_pull()+) or back
-(\lstinline+skb_trim()+), or delete the buffer (\lstinline+kfree_skb()+). A
-socket buffer is passed from layer to layer, and is freed by the layer that
-uses it the last time. In case of sending, freeing has to be done by the
-network driver.
+\paragraph{Socket Buffers}\index{Socket buffer} Socket buffers are the basic
+data type for the whole network stack. They serve as containers for network
+data and are able to quickly add data headers and footers, or strip them off
+again. Therefore a socket buffer consists of an allocated buffer and several
+pointers that mark beginning of the buffer (\lstinline+head+), beginning of
+data (\lstinline+data+), end of data (\lstinline+tail+) and end of buffer
+(\lstinline+end+). In addition, a socket buffer holds network header
+information and (in case of received data) a pointer to the
+\lstinline+net_device+, it was received on. There exist functions that create
+a socket buffer (\lstinline+dev_alloc_skb()+), add data either from front
+(\lstinline+skb_push()+) or back (\lstinline+skb_put()+), remove data from
+front (\lstinline+skb_pull()+) or back (\lstinline+skb_trim()+), or delete the
+buffer (\lstinline+kfree_skb()+). A socket buffer is passed from layer to
+layer, and is freed by the layer that uses it the last time. In case of
+sending, freeing has to be done by the network driver.
%------------------------------------------------------------------------------
-\section{EtherCAT Device Drivers}
-\label{sec:drivers}
+\section{Native EtherCAT Device Drivers}
+\label{sec:native-drivers}
-There are a few requirements for Ethernet network devices to function as
-EtherCAT devices, when connected to an EtherCAT bus.
+There are a few requirements, that applies to Ethernet hardware when used with
+a native Ethernet driver with EtherCAT functionality.
-\paragraph{Dedicated Interfaces}
+\paragraph{Dedicated Hardware} For performance and realtime purposes, the
+EtherCAT master needs direct and exclusive access to the Ethernet hardware.
+This implies that the network device must not be connected to the kernel's
+network stack as usual, because the kernel would try to use it as an ordinary
+Ethernet device.
-For performance and realtime purposes, the EtherCAT master needs direct and
-exclusive access to the Ethernet hardware. This implies that the network device
-must not be connected to the kernel's network stack as usual, because the
-kernel would try to use it as an ordinary Ethernet device.
-
-\paragraph{Interrupt-less Operation}
-\index{Interrupt}
-
-EtherCAT frames travel through the logical EtherCAT ring and are then sent back
-to the master. Communication is highly deterministic: A frame is sent and will
-be received again after a constant time, so there is no need to notify the
-driver about frame reception: The master can instead query the hardware for
-received frames, if it expects them to be already received.
+\paragraph{Interrupt-less Operation}\index{Interrupt} EtherCAT frames travel
+through the logical EtherCAT ring and are then sent back to the master.
+Communication is highly deterministic: A frame is sent and will be received
+again after a constant time, so there is no need to notify the driver about
+frame reception: The master can instead query the hardware for received
+frames, if it expects them to be already received.
Figure~\ref{fig:interrupt} shows two workflows for cyclic frame transmission
and reception with and without interrupts.
@@ -1123,16 +1138,15 @@ incidences contribute to increasing the jitter. Besides, if a realtime
extension (like RTAI) is used, some additional effort would have to be made to
prioritize interrupts.
-\paragraph{Ethernet and EtherCAT Devices}
-
-Another issue lies in the way Linux handles devices of the same type. For
-example, a PCI\nomenclature{PCI}{Peripheral Component Interconnect, Computer
-Bus} driver scans the PCI bus for devices it can handle. Then it registers
-itself as the responsible driver for all of the devices found. The problem is,
-that an unmodified driver can not be told to ignore a device because it will
-be used for EtherCAT later. There must be a way to handle multiple devices of
-the same type, where one is reserved for EtherCAT, while the other is treated
-as an ordinary Ethernet device.
+\paragraph{Ethernet and EtherCAT Devices} Another issue lies in the way Linux
+handles devices of the same type. For example, a
+PCI\nomenclature{PCI}{Peripheral Component Interconnect, Computer Bus} driver
+scans the PCI bus for devices it can handle. Then it registers itself as the
+responsible driver for all of the devices found. The problem is, that an
+unmodified driver can not be told to ignore a device because it will be used
+for EtherCAT later. There must be a way to handle multiple devices of the same
+type, where one is reserved for EtherCAT, while the other is treated as an
+ordinary Ethernet device.
For all this reasons, the author decided that the only acceptable solution is
to modify standard Ethernet drivers in a way that they keep their normal
@@ -1160,15 +1174,64 @@ The chosen approach has the following disadvantages:
%------------------------------------------------------------------------------
-\section{Device Selection}
-\label{sec:deviceselection}
+\section{Generic EtherCAT Device Driver}
+\label{sec:generic-driver}
-After loading the master module, at least one EtherCAT-capable network driver
-module has to be loaded, that offers its devices to the master (see
-sec.~\ref{sec:ecdev}. The master module knows the devices to choose from the
-module parameters (see sec.~\ref{sec:mastermod}). If the init script is used
-to start the master, the drivers and devices to use can be specified in the
-sysconfig file (see sec.~\ref{sec:sysconfig}).
+Since there are approaches to enable the complete Linux kernel for realtime
+operation \cite{rt-preempt}, it is possible to operate without native
+implementations of EtherCAT-capable Ethernet device drivers and use the Linux
+network stack instead. Fig.~\ref{fig:arch} shows the ``Generic Ethernet Driver
+Module'', that connects to local Ethernet devices via the network stack. The
+kernel module is named \lstinline+ec_generic+ and can be loaded after the
+master module like a native EtherCAT-capable Ethernet driver.
+
+The generic device driver scans the network stack for interfaces, that have
+been registered by Ethernet device drivers. It offers all possible devices to
+the EtherCAT master. If the master accepts a device, the generic driver
+creates a packet socket (see \lstinline+man 7 packet+) with
+\lstinline+socket_type+ set to \lstinline+SOCK_RAW+, bound to that device. All
+functions of the device interface (see sec.~\ref{sec:ecdev}) will then operate
+on that socket.
+
+Below are the advantages of this solution:
+
+\begin{itemize}
+\item Any Ethernet hardware, that is covered by a Linux Ethernet driver can be
+used for EtherCAT.
+\item No modifications have to be made to the actual Ethernet drivers.
+\end{itemize}
+
+The generic approach has the following disadvantages:
+
+\begin{itemize}
+\item The performance is a little worse than the native approach, because the
+frame data have to traverse the lower layers of the network stack.
+\item It is not possible to use in-kernel realtime extensions like RTAI with
+the generic driver, because the network stack code uses dynamic memory
+allocations and other things, that could cause the system to freeze in
+realtime context.
+\end{itemize}
+
+%------------------------------------------------------------------------------
+
+\section{Providing Ethernet Devices}
+\label{sec:providing-devices}
+
+After loading the master module, additional module(s) have to be loaded to
+offer devices to the master(s) (see sec.~\ref{sec:ecdev}). The master module
+knows the devices to choose from the module parameters (see
+sec.~\ref{sec:mastermod}). If the init script is used to start the master, the
+drivers and devices to use can be specified in the sysconfig file (see
+sec.~\ref{sec:sysconfig}).
+
+Modules offering Ethernet devices can be
+
+\begin{itemize}
+\item native EtherCAT-capable network driver modules (see
+sec.~\ref{sec:native-drivers}) or
+\item the generic EtherCAT device driver module (see
+sec.~\ref{sec:generic-driver}).
+\end{itemize}
%------------------------------------------------------------------------------
@@ -1196,14 +1259,15 @@ sec.~\ref{sec:gendoc} for generation instructions).
%------------------------------------------------------------------------------
-\section{Patching Network Drivers}
+\section{Patching Native Network Drivers}
\label{sec:patching}
\index{Network drivers}
This section will describe, how to make a standard Ethernet driver
-EtherCAT-capable. Unfortunately, there is no standard procedure to enable an
-Ethernet driver for use with the EtherCAT master, but there are a few common
-techniques.
+EtherCAT-capable, using the native approach (see
+sec.~\ref{sec:native-drivers}). Unfortunately, there is no standard procedure
+to enable an Ethernet driver for use with the EtherCAT master, but there are a
+few common techniques.
\begin{enumerate}
@@ -2605,14 +2669,21 @@ the EtherCAT master. It has to be executed with one of the parameters
EtherCAT buses can always be monitored by inserting a switch between master
and slaves. This allows to connect another PC with a network monitor like
-Wireshark~\cite{wireshark}, for example.
+Wireshark~\cite{wireshark}, for example. It is also possible to listen to
+local network interfaces on the machine running the EtherCAT master directly.
+If the generic Ethernet driver (see sec.~\ref{sec:generic-driver}) is used,
+the network monitor can directly listen on the network interface connected to
+the EtherCAT bus.
-For convenience, so-called ``debug interfaces'' are supported. Debug
-interfaces are virtual network interfaces allowing to capture EtherCAT traffic
-with a network monitor (like Wireshark or tcpdump) running on the master
-machine without using external hardware. To use this functionality, the master
-sources have to be configured with the \lstinline+--enable-debug-if+ switch
-(see sec.~\ref{sec:installation}).
+When using native Ethernet drivers (see sec.~\ref{sec:native-drivers}), there
+are no local network interfaces to listen to, because the Ethernet devices
+used for EtherCAT are not registered at the network stack. For that case,
+so-called ``debug interfaces'' are supported, which are virtual network
+interfaces allowing to capture EtherCAT traffic with a network monitor (like
+Wireshark or tcpdump) running on the master machine without using external
+hardware. To use this functionality, the master sources have to be configured
+with the \lstinline+--enable-debug-if+ switch (see
+sec.~\ref{sec:installation}).
Every EtherCAT master registers a read-only network interface per attached
physical Ethernet device. The network interfaces are named \textit{ecdbgmX}
@@ -2644,8 +2715,8 @@ Please note, that the frame rate can be very high. With an application
connected, the debug interface can produce thousands of frames per second.
\paragraph{Attention} The socket buffers needed for the operation of debug
-interfaces have to be allocated dynamically. Some Linux realtime extensions do
-not allow this in realtime context!
+interfaces have to be allocated dynamically. Some Linux realtime extensions
+(like RTAI) do not allow this in realtime context!
%------------------------------------------------------------------------------
@@ -2832,6 +2903,11 @@ Table~\ref{tab:config} lists important configuration switches and options.
\hline
+\lstinline+--enable-tool+ & Build the command-line tool ``ethercat'' (see
+sec.~\ref{sec:tool}). & yes\\
+
+\lstinline+--enable-userlib+ & Build the userspace library. & yes\\
+
\lstinline+--enable-eoe+ & Enable EoE support & yes\\
\lstinline+--enable-cycles+ & Use CPU timestamp counter. Enable this on Intel
@@ -2855,6 +2931,13 @@ architecture to get finer timing calculation. & no\\
\lstinline+--with-e1000-kernel+ & e1000 kernel & $\dagger$\\
+\lstinline+--enable-r8169+ & Enable r8169 driver & no\\
+
+\lstinline+--with-r8169-kernel+ & r8169 kernel & $\dagger$\\
+
+\lstinline+--enable-generic+ & Build the generic Ethernet driver (see
+sec.~\ref{sec:generic-driver}). & no\\
+
\end{tabular}
\vspace{2mm}
@@ -3049,7 +3132,10 @@ misunderstandings. In: IEE journal ``Computing and Control Engineering'',
2004.
\bibitem{rtai} RTAI. The RealTime Application Interface for Linux from DIAPM.
-\url{http://www.rtai.org}, 2006.
+\url{https://www.rtai.org}, 2010.
+
+\bibitem{rt-preempt} RT PREEMPT HOWTO.
+\url{http://rt.wiki.kernel.org/index.php/RT_PREEMPT_HOWTO}, 2010.
\bibitem{doxygen} Doxygen. Source code documentation generator tool.
\url{http://www.stack.nl/~dimitri/doxygen}, 2008.
diff --git a/documentation/images/Makefile b/documentation/images/Makefile
index 8863062a..cfd80647 100644
--- a/documentation/images/Makefile
+++ b/documentation/images/Makefile
@@ -6,7 +6,6 @@
FIGS := \
app-config.fig \
- architecture.fig \
attach.fig \
dc.fig \
fmmus.fig \
diff --git a/documentation/images/architecture.fig b/documentation/images/architecture.fig
deleted file mode 100644
index 499f7bfb..00000000
--- a/documentation/images/architecture.fig
+++ /dev/null
@@ -1,176 +0,0 @@
-#FIG 3.2
-Portrait
-Center
-Metric
-A4
-100.00
-Single
--2
-1200 2
-5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 7245.000 5985.000 6975 5985 7245 5715 7515 5985
-6 5085 7965 5850 8820
-2 3 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 8
- 5175 7965 5760 7965 5760 8775 5175 8775 5175 8415 5085 8415
- 5085 7965 5175 7965
-2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
- 5490 8190 5670 8190 5670 8370 5490 8370 5490 8190
-2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
- 5310 8505 5400 8505 5400 8595 5310 8595 5310 8505
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8055 5085 8055
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8145 5085 8145
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8190 5085 8190
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8280 5085 8280
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8235 5085 8235
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8100 5085 8100
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8010 5085 8010
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8325 5085 8325
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5175 8370 5085 8370
-2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
- 5850 8775 5085 8775 5085 8815 5850 8815 5850 8775
--6
-6 6435 7965 7200 8820
-2 3 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 8
- 6525 7965 7110 7965 7110 8775 6525 8775 6525 8415 6435 8415
- 6435 7965 6525 7965
-2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
- 6840 8190 7020 8190 7020 8370 6840 8370 6840 8190
-2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
- 6660 8505 6750 8505 6750 8595 6660 8595 6660 8505
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8055 6435 8055
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8145 6435 8145
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8190 6435 8190
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8280 6435 8280
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8235 6435 8235
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8100 6435 8100
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8010 6435 8010
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8325 6435 8325
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 6525 8370 6435 8370
-2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
- 7200 8775 6435 8775 6435 8815 7200 8815 7200 8775
--6
-6 4905 5445 5985 6030
-5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 5445.000 5985.000 4950 5985 5445 5490 5940 5985
-4 1 0 50 -1 16 10 0.0000 4 120 465 5445 5760 Device\001
-4 1 0 50 -1 16 10 0.0000 4 120 615 5445 5925 Interface\001
--6
-6 3870 4275 4500 5355
-5 1 0 1 0 7 50 -1 20 0.000 0 0 0 0 3958.125 4815.000 3915 4320 4455 4815 3915 5310
-4 1 0 49 -1 16 10 4.7124 4 150 765 4162 4822 Application\001
-4 1 0 49 -1 16 10 4.7124 4 120 615 3997 4822 Interface\001
--6
-6 5205 2648 6480 3293
-5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 5842.000 2655.000 6472 2655 5842 3285 5212 2655
-4 1 0 50 -1 16 12 0.0000 4 135 600 5842 3105 Device\001
-4 1 0 50 -1 16 12 0.0000 4 135 825 5842 2880 Character\001
--6
-6 3870 945 4500 2025
-5 1 0 1 0 7 49 -1 -1 0.000 0 0 0 0 3958.125 1485.000 3915 990 4455 1485 3915 1980
-4 1 0 48 -1 16 10 4.7124 4 150 765 4162 1492 Application\001
-4 1 0 48 -1 16 10 4.7124 4 120 615 3997 1492 Interface\001
--6
-6 2160 855 3420 2115
-1 3 0 1 0 7 50 -1 20 0.000 1 0.0000 2790 1485 585 585 2790 1485 3375 1485
-4 1 0 49 -1 16 12 0.0000 4 180 945 2790 1665 Application\001
-4 1 0 49 -1 16 12 0.0000 4 180 885 2790 1440 Userspace\001
--6
-1 4 0 1 0 7 50 -1 -1 0.000 1 0.0000 2484 4871 459 459 2025 4860 2944 4882
-1 2 0 1 0 7 50 -1 -1 0.000 1 0.0000 5445 4815 810 495 4635 4320 6255 5310
-1 4 0 1 0 7 50 -1 -1 4.000 1 0.0000 7058 1658 495 495 7553 2153 6563 1163
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 5445 7965 5445 7425
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 6795 7965 6795 7425
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 5445 6885 5445 5985
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
- 5535 8820 5625 8820 5625 8910 5535 8910 5535 8820
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
- 6885 8820 6975 8820 6975 8910 6885 8910 6885 8820
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 7245 6885 7245 5985
-2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5
- 7605 7605 7605 6345 4635 6345 4635 7605 7605 7605
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
- 4905 6885 5985 6885 5985 7425 4905 7425 4905 6885
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
- 6255 6885 7335 6885 7335 7425 6255 7425 6255 6885
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 5445 5490 5445 5310
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 4635 4815 4455 4815
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 3915 4815 3465 4815
-2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
- 7605 3645 6885 3645 6885 5985 7605 5985 7605 3645
-2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 1575 7785 7785 7785
-2 4 0 1 0 7 50 -1 -1 0.000 0 0 9 0 0 5
- 1755 5985 1755 3645 3465 3645 3465 5985 1755 5985
-2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 7785 8280 7785 2205
-2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 1575 8280 1575 2205
-2 4 0 1 0 7 50 -1 -1 0.000 0 0 8 0 0 5
- 6435 5985 6435 3645 3915 3645 3915 5985 6435 5985
-2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 7785 2655 1575 2655
-2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
- 5850 3285 5850 3645
-2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
- 3915 1485 3375 1485
-2 4 0 1 0 7 50 -1 20 0.000 0 0 7 0 0 5
- 5040 2250 3915 2250 3915 720 5040 720 5040 2250
-3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 3
- 5580 8910 5355 9045 4770 9090
- 0.000 -1.000 0.000
-3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 3
- 6931 8910 6390 9270 4770 9450
- 0.000 -1.000 0.000
-3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 3
- 6570 1665 6120 1890 5985 2655
- 0.000 -1.000 0.000
-3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 3
- 5040 1485 5580 1800 5715 2655
- 0.000 -1.000 0.000
-4 1 0 50 -1 16 10 0.0000 4 150 750 5445 7200 net_device\001
-4 1 0 50 -1 16 10 0.0000 4 150 750 6795 7200 net_device\001
-4 2 0 50 -1 12 10 0.0000 4 105 810 5355 6210 ecdev_*()\001
-4 1 0 50 -1 16 12 0.0000 4 135 1545 6345 6570 EtherCAT Network\001
-4 1 0 50 -1 16 12 0.0000 4 135 1200 6345 6750 Driver Module\001
-4 0 0 50 -1 16 12 0.0000 4 135 2130 4005 3870 EtherCAT Master Module\001
-4 1 0 50 -1 16 12 1.5708 4 135 1200 7290 4815 Network Stack\001
-4 2 0 50 -1 16 12 0.0000 4 135 810 4725 9135 EtherCAT\001
-4 2 0 50 -1 16 12 0.0000 4 135 690 4725 9495 Ethernet\001
-4 2 0 50 -1 16 12 0.0000 4 135 315 4995 8100 NIC\001
-4 2 0 50 -1 16 12 0.0000 4 135 315 6345 8100 NIC\001
-4 0 0 50 -1 16 12 0.0000 4 135 810 1665 8010 Hardware\001
-4 2 0 50 -1 12 10 4.7124 4 105 720 3645 4725 ecrt_*()\001
-4 0 0 50 -1 16 12 0.0000 4 180 945 1845 3870 Application\001
-4 0 0 50 -1 16 12 0.0000 4 135 630 1845 4095 Module\001
-4 1 0 50 -1 16 12 0.0000 4 135 390 2475 4950 Task\001
-4 0 0 50 -1 16 12 0.0000 4 180 1050 1665 2880 Kernelspace\001
-4 0 0 50 -1 16 12 0.0000 4 180 885 1665 2565 Userspace\001
-4 1 0 50 -1 16 12 4.7124 4 135 870 4635 1530 libethercat\001
-4 2 0 50 -1 12 10 4.7124 4 105 720 3645 1395 ecrt_*()\001
-4 2 0 50 -1 12 10 0.0000 4 105 810 7155 6210 netif_*()\001
-4 1 0 50 -1 16 12 0.0000 4 135 735 5445 4905 Master 0\001
-4 1 0 50 -1 16 12 0.0000 4 135 360 7065 1845 Tool\001
-4 1 0 50 -1 16 12 0.0000 4 135 765 7065 1620 'ethercat'\001
diff --git a/documentation/images/architecture.svg b/documentation/images/architecture.svg
new file mode 100644
index 00000000..dbacbce1
--- /dev/null
+++ b/documentation/images/architecture.svg
@@ -0,0 +1,1036 @@
+
+
+
+
+
diff --git a/include/ecrt.h b/include/ecrt.h
index 7cd6c0cc..e73068e1 100644
--- a/include/ecrt.h
+++ b/include/ecrt.h
@@ -208,8 +208,6 @@ typedef struct {
/*****************************************************************************/
-#ifndef __KERNEL__
-
/** Master information.
*
* This is used as an output parameter of ecrt_master().
@@ -246,8 +244,6 @@ typedef struct {
char name[EC_MAX_STRING_LENGTH]; /**< Name of the slave. */
} ec_slave_info_t;
-#endif // #ifndef __KERNEL__
-
/*****************************************************************************/
/** Domain working counter interpretation.
@@ -539,8 +535,6 @@ ec_slave_config_t *ecrt_master_slave_config(
uint32_t product_code /**< Expected product code. */
);
-#ifndef __KERNEL__
-
/** Obtains master information.
*
* No memory is allocated on the heap in
@@ -573,6 +567,8 @@ int ecrt_master_get_slave(
information */
);
+#ifndef __KERNEL__
+
/** Returns the proposed configuration of a slave's sync manager.
*
* Fills a given ec_sync_info_t structure with the attributes of a sync
diff --git a/lib/master.c b/lib/master.c
index 41ccf954..0a3806f1 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -156,7 +156,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
slave_info->error_flag = data.error_flag;
slave_info->sync_count = data.sync_count;
slave_info->sdo_count = data.sdo_count;
- strncpy(slave_info->name, data.name, EC_IOCTL_STRING_SIZE);
+ strncpy(slave_info->name, data.name, EC_MAX_STRING_LENGTH);
return 0;
}
diff --git a/master/master.c b/master/master.c
index 3919f463..f9443333 100644
--- a/master/master.c
+++ b/master/master.c
@@ -2138,6 +2138,56 @@ ec_slave_config_t *ecrt_master_slave_config(ec_master_t *master,
/*****************************************************************************/
+int ecrt_master(ec_master_t *master, ec_master_info_t *master_info)
+{
+ if (master->debug_level)
+ EC_DBG("ecrt_master(master = 0x%p, master_info = 0x%p)\n",
+ master, master_info);
+
+ master_info->slave_count = master->slave_count;
+ master_info->link_up = master->main_device.link_state;
+ master_info->scan_busy = master->scan_busy;
+ master_info->app_time = master->app_time;
+ return 0;
+}
+
+/*****************************************************************************/
+
+int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
+ ec_slave_info_t *slave_info)
+{
+ const ec_slave_t *slave;
+
+ if (down_interruptible(&master->master_sem)) {
+ return -EINTR;
+ }
+
+ slave = ec_master_find_slave_const(master, 0, slave_position);
+
+ slave_info->position = slave->ring_position;
+ slave_info->vendor_id = slave->sii.vendor_id;
+ slave_info->product_code = slave->sii.product_code;
+ slave_info->revision_number = slave->sii.revision_number;
+ slave_info->serial_number = slave->sii.serial_number;
+ slave_info->alias = slave->sii.alias;
+ slave_info->current_on_ebus = slave->sii.current_on_ebus;
+ slave_info->al_state = slave->current_state;
+ slave_info->error_flag = slave->error_flag;
+ slave_info->sync_count = slave->sii.sync_count;
+ slave_info->sdo_count = ec_slave_sdo_count(slave);
+ if (slave->sii.name) {
+ strncpy(slave_info->name, slave->sii.name, EC_MAX_STRING_LENGTH);
+ } else {
+ slave_info->name[0] = 0;
+ }
+
+ up(&master->master_sem);
+
+ return 0;
+}
+
+/*****************************************************************************/
+
void ecrt_master_callbacks(ec_master_t *master,
void (*send_cb)(void *), void (*receive_cb)(void *), void *cb_data)
{
@@ -2218,6 +2268,8 @@ EXPORT_SYMBOL(ecrt_master_send);
EXPORT_SYMBOL(ecrt_master_send_ext);
EXPORT_SYMBOL(ecrt_master_receive);
EXPORT_SYMBOL(ecrt_master_callbacks);
+EXPORT_SYMBOL(ecrt_master);
+EXPORT_SYMBOL(ecrt_master_get_slave);
EXPORT_SYMBOL(ecrt_master_slave_config);
EXPORT_SYMBOL(ecrt_master_state);
EXPORT_SYMBOL(ecrt_master_application_time);
diff --git a/tty/module.c b/tty/module.c
index a7c92055..bf506d3a 100644
--- a/tty/module.c
+++ b/tty/module.c
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
#include "../master/globals.h"
#include "../include/ectty.h"
@@ -379,7 +380,11 @@ static int ec_tty_write(
/*****************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+static int ec_tty_put_char(struct tty_struct *tty, unsigned char ch)
+#else
static void ec_tty_put_char(struct tty_struct *tty, unsigned char ch)
+#endif
{
ec_tty_t *t = (ec_tty_t *) tty->driver_data;
@@ -390,8 +395,14 @@ static void ec_tty_put_char(struct tty_struct *tty, unsigned char ch)
if (ec_tty_tx_space(t)) {
t->tx_buffer[t->tx_write_idx] = ch;
t->tx_write_idx = (t->tx_write_idx + 1) % EC_TTY_TX_BUFFER_SIZE;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ return 1;
+#endif
} else {
printk(KERN_WARNING PFX "%s(): Dropped a byte!\n", __func__);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
+ return 0;
+#endif
}
}
@@ -506,11 +517,19 @@ static void ec_tty_hangup(struct tty_struct *tty)
/*****************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+static int ec_tty_break(struct tty_struct *tty, int break_state)
+#else
static void ec_tty_break(struct tty_struct *tty, int break_state)
+#endif
{
#if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s(break_state = %i).\n", __func__, break_state);
#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+ return -EIO; // not implemented
+#endif
}
/*****************************************************************************/