# HG changeset patch # User Florian Pose # Date 1159288718 0 # Node ID 4cf9c3e9f0bded240566708b23186a7407c87eb2 # Parent 861f4715ed6fef527e95730f78015effefa4e892 MERGE trunk -r564:568 -> branches/stable-1.1 (doc, master output, atomic flag) diff -r 861f4715ed6f -r 4cf9c3e9f0bd Makefile.am --- a/Makefile.am Mon Sep 25 17:28:31 2006 +0000 +++ b/Makefile.am Tue Sep 26 16:38:38 2006 +0000 @@ -70,7 +70,8 @@ $(MINI_FILES) $(RTAI_FILES) $(MSR_FILES) mydist: - $(MAKE) dist distdir=$(PACKAGE)-$(VERSION)-r`svnversion $(srcdir)` + @SVNREV=`svnversion $(srcdir)` && \ + $(MAKE) dist-bzip2 distdir=$(PACKAGE)-$(VERSION)-r$${SVNREV} dist-hook: if which svnversion >/dev/null 2>&1; then \ diff -r 861f4715ed6f -r 4cf9c3e9f0bd documentation/ethercat_doc.tex --- a/documentation/ethercat_doc.tex Mon Sep 25 17:28:31 2006 +0000 +++ b/documentation/ethercat_doc.tex Tue Sep 26 16:38:38 2006 +0000 @@ -4300,9 +4300,10 @@ \label{sec:make} \index{Master!Compilation} -The current EtherCAT master code is available at~\cite{etherlab}. -After downloading the \textit{tar.bz2} file, it has to be unpacked -with the command below (or similar): +The current EtherCAT master code is available at~\cite{etherlab} or +can be obtained from the EtherLab\textsuperscript{\textregistered} CD. +The \textit{tar.bz2} file has to be unpacked with the command below +(or similar): \begin{lstlisting} host> `\textbf{tar xjf ethercat-1.1-rXXX.tar.bz2}` @@ -4340,10 +4341,12 @@ host# `\textbf{make install}` \end{lstlisting} -If the EtherCAT master shall be run as a service (recommended), the -init script and the sysconfig file have to be copied to the -appropriate locations. The below example is suitable for SUSE Linux. -It may vary for other distributions. +If the EtherCAT master shall be run as a service +(recommended\footnote{Even if the EtherCAT master shall not be loaded + on system startup, the use of the init script is recommended for + manual (un-)loading.}), the init script and the sysconfig file have +to be copied to the appropriate locations. The below example is +suitable for SUSE Linux. It may vary for other distributions. \begin{lstlisting} host# `\textbf{cd /opt/etherlab}` @@ -4352,14 +4355,33 @@ host# `\textbf{insserv ethercat}` \end{lstlisting} -Now the sysconfig file has to be customized. For the contents of the -file, see section~\ref{sec:sysconfig}. To give a short summary: The -most important thing is to adjust the \textit{DEVICE\_INDEX} variable. -It has to be set to the index of the compatible network device to use +Now the sysconfig file \texttt{/etc/sysconfig/ethercat} (see +section~\ref{sec:sysconfig}) has to be customized: This is mainly done +by uncommenting and adjusting the \textit{DEVICE\_INDEX} variable. It +has to be set to the index of the compatible network device to use with EtherCAT, where the order of devices is dependent on their -position in the PCI bus. If this is not known, the index can be -determinded with trial and error, but it has to be considered that a -wrong value can cause a loss of network connection. +position in the PCI bus: + +\begin{lstlisting}[numbers=left,basicstyle=\ttfamily\scriptsize] + host# `\textbf{lspci}` + 00:00.0 Host bridge: VIA Technologies, Inc. VT8363/8365 [KT133/KM133] (rev 03) + 00:01.0 PCI bridge: VIA Technologies, Inc. VT8363/8365 [KT133/KM133 AGP] + 00:04.0 ISA bridge: VIA Technologies, Inc. VT82C686 [Apollo Super South] (rev 40) + 00:04.1 IDE interface: VIA Technologies, Inc. VT82C586A/B/VT82C686/A/B/VT823x/A/C... + 00:04.2 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller... + 00:04.3 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controller... + 00:04.4 Bridge: VIA Technologies, Inc. VT82C686 [Apollo Super ACPI] (rev 40) + 00:09.0 Ethernet controller: D-Link System Inc RTL8139 Ethernet (rev 10) + 00:0a.0 Ethernet controller: Intel Corporation 82557/8/9 [Ethernet Pro 100] (rev 08) + 00:0b.0 Ethernet controller: D-Link System Inc RTL8139 Ethernet (rev 10) + 00:0c.0 VGA compatible controller: ATI Technologies Inc Rage XL (rev 27) + 00:11.0 Unknown mass storage controller: Promise Technology, Inc. PDC20265... +\end{lstlisting} + +In the above output of the \textit{lspci} command, two compatible +network devices can be found in lines~\textcircled{\tiny 9} and +\textcircled{\tiny 11}. The \textit{DEVICE\_INDEX} variable should be +set to $0$ or $1$, respectively. After the basic configuration is done, the master can be started with the below command: diff -r 861f4715ed6f -r 4cf9c3e9f0bd master/domain.c --- a/master/domain.c Mon Sep 25 17:28:31 2006 +0000 +++ b/master/domain.c Tue Sep 26 16:38:38 2006 +0000 @@ -357,7 +357,7 @@ } } - EC_INFO("Domain %i - Allocated %i bytes in %i datagram%s\n", + EC_INFO("Domain %i - Allocated %i bytes in %i datagram%s.\n", domain->index, domain->data_size, datagram_count, datagram_count == 1 ? "" : "s"); diff -r 861f4715ed6f -r 4cf9c3e9f0bd master/master.c --- a/master/master.c Mon Sep 25 17:28:31 2006 +0000 +++ b/master/master.c Tue Sep 26 16:38:38 2006 +0000 @@ -108,7 +108,7 @@ master->index = index; master->device = NULL; - master->reserved = 0; + atomic_set(&master->available, 1); INIT_LIST_HEAD(&master->slaves); INIT_LIST_HEAD(&master->datagram_queue); INIT_LIST_HEAD(&master->domains); @@ -1041,9 +1041,10 @@ /** Measures the time, a frame is on the bus. -*/ - -void ec_master_measure_bus_time(ec_master_t *master) + \return 0 in case of success, else < 0 +*/ + +int ec_master_measure_bus_time(ec_master_t *master) { ec_datagram_t datagram; cycles_t cycles_start, cycles_end, cycles_timeout; @@ -1054,7 +1055,7 @@ if (ec_datagram_brd(&datagram, 0x130, 2)) { EC_ERR("Failed to allocate datagram for bus time measuring.\n"); ec_datagram_clear(&datagram); - return; + return -1; } cycles_timeout = (cycles_t) EC_IO_TIMEOUT * (cpu_khz / 1000); @@ -1093,11 +1094,13 @@ EC_INFO("Bus time is (min/avg/max) %u/%u.%u/%u us.\n", min, sum / 100, sum % 100, max); + return 0; error: // Dequeue and free datagram list_del(&datagram.queue); ec_datagram_clear(&datagram); + return -1; } /****************************************************************************** diff -r 861f4715ed6f -r 4cf9c3e9f0bd master/master.h --- a/master/master.h Mon Sep 25 17:28:31 2006 +0000 +++ b/master/master.h Tue Sep 26 16:38:38 2006 +0000 @@ -44,6 +44,7 @@ #include #include #include +#include #include "device.h" #include "domain.h" @@ -91,7 +92,7 @@ struct ec_master { struct list_head list; /**< list item for module's master list */ - unsigned int reserved; /**< non-zero, if the master is reserved for RT */ + atomic_t available; /**< zero, if the master is reserved for RT */ unsigned int index; /**< master index */ struct kobject kobj; /**< kobject */ @@ -158,7 +159,7 @@ // misc. void ec_master_output_stats(ec_master_t *); void ec_master_clear_slaves(ec_master_t *); -void ec_master_measure_bus_time(ec_master_t *); +int ec_master_measure_bus_time(ec_master_t *); // other methods void ec_sync_config(const ec_sii_sync_t *, const ec_slave_t *, uint8_t *); diff -r 861f4715ed6f -r 4cf9c3e9f0bd master/module.c --- a/master/module.c Mon Sep 25 17:28:31 2006 +0000 +++ b/master/module.c Tue Sep 26 16:38:38 2006 +0000 @@ -401,71 +401,78 @@ if (!(master = ec_find_master(master_index))) goto out_return; - if (master->reserved) { + if (!atomic_dec_and_test(&master->available)) { + atomic_inc(&master->available); EC_ERR("Master %i is already in use!\n", master_index); goto out_return; } - master->reserved = 1; if (!master->device) { EC_ERR("Master %i has no assigned device!\n", master_index); goto out_release; } - if (!try_module_get(master->device->module)) { + if (!try_module_get(master->device->module)) { // possible race? EC_ERR("Failed to reserve device module!\n"); goto out_release; } - ec_master_measure_bus_time(master); - ec_master_idle_stop(master); - ec_master_reset(master); + if (!master->device->link_state) { + EC_ERR("Link is DOWN.\n"); + goto out_module_put; + } + + ec_master_reset(master); // also stops idle mode master->mode = EC_MASTER_MODE_OPERATION; - if (!master->device->link_state) EC_WARN("Link is DOWN.\n"); + if (ec_master_measure_bus_time(master)) { + EC_ERR("Bus time measuring failed!\n"); + goto out_reset; + } if (ec_master_bus_scan(master)) { EC_ERR("Bus scan failed!\n"); - goto out_module_put; - } - - EC_INFO("Master %i is ready.\n", master_index); + goto out_reset; + } + + EC_INFO("Successfully requested master %i.\n", master_index); return master; + out_reset: + ec_master_reset(master); + ec_master_idle_start(master); out_module_put: module_put(master->device->module); + out_release: + atomic_inc(&master->available); + out_return: + EC_ERR("Failed to request master %i.\n", master_index); + return NULL; +} + +/*****************************************************************************/ + +/** + Releases a reserved EtherCAT master. + \ingroup RealtimeInterface +*/ + +void ecrt_release_master(ec_master_t *master /**< EtherCAT master */) +{ + EC_INFO("Releasing master %i...\n", master->index); + + if (atomic_read(&master->available)) { + EC_ERR("Master %i was never requested!\n", master->index); + return; + } + ec_master_reset(master); ec_master_idle_start(master); - out_release: - master->reserved = 0; - out_return: - EC_ERR("Failed requesting master %i.\n", master_index); - return NULL; -} - -/*****************************************************************************/ - -/** - Releases a reserved EtherCAT master. - \ingroup RealtimeInterface -*/ - -void ecrt_release_master(ec_master_t *master /**< EtherCAT master */) -{ - EC_INFO("Releasing master %i...\n", master->index); - - if (!master->reserved) { - EC_ERR("Master %i was never requested!\n", master->index); - return; - } - - ec_master_reset(master); - ec_master_idle_start(master); module_put(master->device->module); - master->reserved = 0; - - EC_INFO("Released master %i.\n", master->index); + atomic_inc(&master->available); + + EC_INFO("Successfully released master %i.\n", master->index); return; }