MERGE -r908:HEAD svn://yak/vol/projekte/msr_messen_steuern_regeln/ethercat/rep/trunk (1.3.1 changes)
--- a/Makefile.am Fri Aug 10 15:27:08 2007 +0000
+++ b/Makefile.am Thu Sep 13 11:08:46 2007 +0000
@@ -39,7 +39,8 @@
Doxyfile \
FEATURES \
globals.h \
- Kbuild
+ Kbuild \
+ README.EoE
modules:
$(MAKE) -C "$(LINUX_SOURCE_DIR)" M="@abs_srcdir@" modules
--- a/NEWS Fri Aug 10 15:27:08 2007 +0000
+++ b/NEWS Thu Sep 13 11:08:46 2007 +0000
@@ -4,17 +4,33 @@
-------------------------------------------------------------------------------
+Changes in version 1.3.1:
+
+* Improved EoE handling: Avoided skipping of datagrams and release lock
+ while processing.
+* Added some statistics to the datagram structure.
+* Master state machine clears all station addresses with a broadcast datagram
+ before setting them.
+* Added --enable-eoe conditional.
+* Minor extensions of the master info file.
+* Improved handling of unexpected working counters.
+* Create network interfaces for EoE devices with alias as eoeXaY.
+* Fixed problems on big-endian systems.
+* Added documentation on how to set up an EoE network.
+
+-------------------------------------------------------------------------------
+
Changes in version 1.3.0:
-* Added Intel PRO/1000 gigabit ethernet driver (e1000).
-* Added testing version of Intel PRO/100 ethernet driver (e100).
-* Added testing version of NVIDIA nForce ethernet driver (forcedeth).
+* Added Intel PRO/1000 Gigabit Ethernet driver (e1000).
+* Added testing version of Intel PRO/100 Ethernet driver (e100).
+* Added testing version of NVIDIA nForce Ethernet driver (forcedeth).
* Removed "ec_eoeif_count" master module parameter. EoE handlers are created
dynamically instead.
* Added "main" and "backup" parameters to master module to hand over the
MAC addresses of the devices to wait for. This made the ec_device_index
- parameter of the ethernet drivers obsolete. The broadcast MAC address means,
- that the master accepts the first device offered by any ethernet driver.
+ parameter of the Ethernet drivers obsolete. The broadcast MAC address means,
+ that the master accepts the first device offered by any Ethernet driver.
* Changed format of sysconfig file and accordingly adjusted functionality
of the init script to handle the above MAC address lists.
* Realtime interface changes:
@@ -48,7 +64,7 @@
state machine.
* Master state machine scheduled with timeout if idle, otherwise is executed
as fast as possible (with schedule()).
-* Added dummy module for simulation purpuses.
+* Added dummy module for simulation purposes.
* Limited infinite EEPROM reading, if 0xffff limiter word is missing.
* Init script works now properly on non-SUSE distros (no rc.status dependency
any more).
@@ -58,7 +74,7 @@
Changes in version 1.2.0:
-* Serveral fixes of bugs and stability issues. Master should now run fine
+* Several fixes of bugs and stability issues. Master should now run fine
with kernels 2.6.17 to 2.6.19.
* Realtime interface changes:
- Re-introduced ecrt_domain_queue() to allow datagram queuing apart
@@ -93,7 +109,7 @@
* Device modules for kernel 2.6.17.
* SDO configurations available in Sysfs.
* FMMU configurations cleared when going to INIT.
-* Slave-specific logs only at debug level 1 (for large busses).
+* Slave-specific logs only at debug level 1 (for large buses).
* Slave flags (error, online) available in Sysfs.
* Acknowledging of spontaneous state changes in master FSMs.
* ecrt_master_deactivate() deprecated.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README.EoE Thu Sep 13 11:08:46 2007 +0000
@@ -0,0 +1,24 @@
+-------------------------------------------------------------------------------
+
+$Id$
+
+This file shall give additional information on how to set up a network
+environment with Ethernet-over-EtherCAT devices.
+
+A virtual network interface will appear for every EoE-capable slave. The
+interface naming scheme is eoeXsY, where X is the master index and Y is the
+slave's ring position. Please provide a network configuration file for any of
+these interfaces. On SUSE systems, these can look like the following:
+
+/etc/sysconfig/network/ifcfg-eoe0s14:
+IPADDRESS=10.0.0.14/8
+STARTMODE=auto
+
+This will tell the ifupd to configure and open the device after it appears.
+
+If the interfaces shall be part of a network bridge, the IPADDRESS line is not
+necessary. Instead, copy the file script/ifup-eoe.sh to your systems if-up.d
+directory (on SUSE, this is /etc/sysconfig/network/if-up.d), and customize the
+included variables.
+
+-------------------------------------------------------------------------------
--- a/TODO Fri Aug 10 15:27:08 2007 +0000
+++ b/TODO Thu Sep 13 11:08:46 2007 +0000
@@ -13,12 +13,13 @@
- Redundancy with 2 network adapters.
- Mailbox handler
- Support slaves, that don't support the LRW datagram, only LRD/LWR.
+ - PDO reading in IDLE mode.
+ - Replace Sysfs interface with cdev and user space program.
* Smaller issues:
- Clear sync managers in INIT.
- Simplify FSMs with <state>_enter() functions.
- Output intermediate results during lsec.
- - State change FSM: Follow spontaneous state changes.
- Read out CRC counters.
- Calculate expected working counter for domains.
- Optimize alignment of process data.
--- a/configure.ac Fri Aug 10 15:27:08 2007 +0000
+++ b/configure.ac Thu Sep 13 11:08:46 2007 +0000
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
AC_PREREQ(2.59)
-AC_INIT([ethercat],[1.3.0],[fp@igh-essen.com])
+AC_INIT([ethercat],[1.3.1],[fp@igh-essen.com])
AC_CONFIG_AUX_DIR([autoconf])
AM_INIT_AUTOMAKE([-Wall -Werror dist-bzip2])
AC_PREFIX_DEFAULT([/opt/etherlab])
@@ -414,6 +414,31 @@
AM_CONDITIONAL(ENABLE_DUMMY, test "x$dummy" = "x1")
#------------------------------------------------------------------------------
+# Ethernet-over-EtherCAT support
+#------------------------------------------------------------------------------
+
+AC_ARG_ENABLE([eoe],
+ AS_HELP_STRING([--enable-eoe],
+ [Enable EoE support (default: yes)]),
+ [
+ case "${enableval}" in
+ yes) eoe=1
+ ;;
+ no) eoe=0
+ ;;
+ *) AC_MSG_ERROR([Invalid value for --enable-eoe])
+ ;;
+ esac
+ ],
+ [eoe=1]
+)
+
+if test "x${eoe}" = "x1"; then
+ AC_DEFINE([EC_EOE], [1], [EoE support enabled])
+fi
+AM_CONDITIONAL(ENABLE_EOE, test "x$eoe" = "x1")
+
+#------------------------------------------------------------------------------
# Create config.kbuild
@@ -433,6 +458,7 @@
MSR_DIR := "${msrdir}"
ENABLE_DEBUG_IF := ${dbg}
ENABLE_DUMMY := ${dummy}
+ENABLE_EOE := ${eoe}
EOF
#------------------------------------------------------------------------------
--- a/documentation/graphs/Makefile Fri Aug 10 15:27:08 2007 +0000
+++ b/documentation/graphs/Makefile Thu Sep 13 11:08:46 2007 +0000
@@ -4,7 +4,7 @@
#
#-----------------------------------------------------------------------------
-GRAPHS := fsm_slave_conf.ps fsm_pdo_mapping.ps
+GRAPHS := fsm_slave_conf.ps fsm_pdo_mapping.ps fsm_master.ps
all: $(GRAPHS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/documentation/graphs/fsm_master.dot Thu Sep 13 11:08:46 2007 +0000
@@ -0,0 +1,79 @@
+digraph master {
+ size="7,9"
+ center=1
+ ratio=fill
+
+ action_process_eeprom [shape=point,label=""]
+ action_process_sdo [shape=point,label=""]
+ action_configure [shape=point,label=""]
+ action_next_slave_state [shape=point,label=""]
+ action_process_states [shape=point,label=""]
+ action_addresses [shape=point,label=""]
+
+ start -> broadcast [weight=10]
+
+ //broadcast -> error
+ broadcast -> end
+ broadcast -> clear_addresses
+ broadcast -> read_states [weight=10]
+
+ action_process_eeprom -> write_eeprom
+
+ action_process_sdo -> sdo_request
+
+ action_configure -> configure_slave
+
+ action_next_slave_state -> read_states
+ action_next_slave_state -> validate_vendor
+ action_next_slave_state -> action_process_states
+
+ action_process_states -> action_configure
+ action_process_states -> action_process_sdo
+ action_process_states -> action_process_eeprom
+ action_process_states -> sdodict
+ action_process_states -> end
+
+ //read_states -> error
+ read_states -> action_next_slave_state
+ read_states -> acknowledge
+
+ //acknowledge -> error
+ acknowledge -> action_next_slave_state
+
+ //validate_vendor -> error
+ validate_vendor -> validate_product
+
+ action_addresses -> end
+ action_addresses -> rewrite_addresses
+
+ //validate_product -> error
+ validate_product -> validate_vendor
+ validate_product -> action_addresses
+
+ //rewrite_addresses -> error
+ rewrite_addresses -> end
+ rewrite_addresses -> action_addresses
+
+ //clear_addresses -> error
+ clear_addresses -> scan_slaves
+
+ scan_slaves -> scan_slaves
+ scan_slaves -> end
+
+ configure_slave -> action_configure
+ configure_slave -> end
+
+ //write_eeprom -> error
+ write_eeprom -> end
+
+ //sdodict -> error
+ sdodict -> end
+
+ //sdo_request -> error
+ sdo_request -> action_process_sdo
+ sdo_request -> end
+
+ //error -> start
+
+ //end -> start
+}
--- a/include/ecdb.h Fri Aug 10 15:27:08 2007 +0000
+++ b/include/ecdb.h Thu Sep 13 11:08:46 2007 +0000
@@ -34,6 +34,10 @@
/**
\file
EtherCAT Slave Database.
+
+ \warn Please do not create any dependencies to this file! It may be changed
+ between releases. Provide a copy, if you want to use it in foreign
+ projects.
*/
/*****************************************************************************/
@@ -51,10 +55,16 @@
#define Beckhoff_EL1004_PDO_Inputs 0x3101, 1
#define Beckhoff_EL1004_Inputs Beckhoff_EL1004, Beckhoff_EL1004_PDO_Inputs
+#define Beckhoff_EL1004v2_PDO_Inputs 0x6000, 1
+#define Beckhoff_EL1004v2_Inputs Beckhoff_EL1004, Beckhoff_EL1004v2_PDO_Inputs
+
#define Beckhoff_EL1014 0x00000002, 0x03F63052
#define Beckhoff_EL1014_PDO_Inputs 0x3101, 1
#define Beckhoff_EL1014_Inputs Beckhoff_EL1014, Beckhoff_EL1014_PDO_Inputs
+#define Beckhoff_EL1014v2_PDO_Inputs 0x6000, 1
+#define Beckhoff_EL1014v2_Inputs Beckhoff_EL1014, Beckhoff_EL1014v2_PDO_Inputs
+
#define Beckhoff_EL2004 0x00000002, 0x07D43052
#define Beckhoff_EL2004_PDO_Outputs 0x3001, 1
#define Beckhoff_EL2004_Outputs Beckhoff_EL2004, Beckhoff_EL2004_PDO_Outputs
--- a/include/ecrt.h Fri Aug 10 15:27:08 2007 +0000
+++ b/include/ecrt.h Thu Sep 13 11:08:46 2007 +0000
@@ -325,7 +325,7 @@
#define EC_WRITE_U32(DATA, VAL) \
do { \
*((uint32_t *) (DATA)) = (uint32_t) (VAL); \
- cpu_to_le16s(DATA); \
+ cpu_to_le32s(DATA); \
} while (0)
/**
--- a/master/Kbuild Fri Aug 10 15:27:08 2007 +0000
+++ b/master/Kbuild Thu Sep 13 11:08:46 2007 +0000
@@ -36,9 +36,12 @@
obj-m := ec_master.o
ec_master-objs := module.o master.o device.o pdo.o sync.o fmmu.o slave.o \
- datagram.o domain.o mailbox.o canopen.o ethernet.o fsm_sii.o fsm_change.o \
+ datagram.o domain.o mailbox.o canopen.o fsm_sii.o fsm_change.o \
fsm_coe.o fsm_mapping.o fsm_slave.o fsm_master.o
+ifeq ($(ENABLE_EOE),1)
+ ec_master-objs += ethernet.o
+endif
ifeq ($(ENABLE_DEBUG_IF),1)
ec_master-objs += debug.o
endif
--- a/master/datagram.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/datagram.c Thu Sep 13 11:08:46 2007 +0000
@@ -71,7 +71,7 @@
{
INIT_LIST_HEAD(&datagram->queue); // mark as unqueued
datagram->type = EC_DATAGRAM_NONE;
- datagram->address.logical = 0x00000000;
+ memset(datagram->address, 0x00, EC_ADDR_LEN);
datagram->data = NULL;
datagram->mem_size = 0;
datagram->data_size = 0;
@@ -82,6 +82,9 @@
datagram->jiffies_sent = 0;
datagram->cycles_received = 0;
datagram->jiffies_received = 0;
+ datagram->skip_count = 0;
+ datagram->stats_output_jiffies = 0;
+ datagram->name[0] = 0x00;
}
/*****************************************************************************/
@@ -147,8 +150,8 @@
EC_FUNC_HEADER;
datagram->type = EC_DATAGRAM_NPRD;
- datagram->address.physical.slave = node_address;
- datagram->address.physical.mem = offset;
+ EC_WRITE_U16(datagram->address, node_address);
+ EC_WRITE_U16(datagram->address + 2, offset);
EC_FUNC_FOOTER;
}
@@ -175,8 +178,8 @@
EC_FUNC_HEADER;
datagram->type = EC_DATAGRAM_NPWR;
- datagram->address.physical.slave = node_address;
- datagram->address.physical.mem = offset;
+ EC_WRITE_U16(datagram->address, node_address);
+ EC_WRITE_U16(datagram->address + 2, offset);
EC_FUNC_FOOTER;
}
@@ -200,8 +203,8 @@
{
EC_FUNC_HEADER;
datagram->type = EC_DATAGRAM_APRD;
- datagram->address.physical.slave = (int16_t) ring_position * (-1);
- datagram->address.physical.mem = offset;
+ EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
+ EC_WRITE_U16(datagram->address + 2, offset);
EC_FUNC_FOOTER;
}
@@ -225,8 +228,8 @@
{
EC_FUNC_HEADER;
datagram->type = EC_DATAGRAM_APWR;
- datagram->address.physical.slave = (int16_t) ring_position * (-1);
- datagram->address.physical.mem = offset;
+ EC_WRITE_S16(datagram->address, (int16_t) ring_position * (-1));
+ EC_WRITE_U16(datagram->address + 2, offset);
EC_FUNC_FOOTER;
}
@@ -248,8 +251,8 @@
{
EC_FUNC_HEADER;
datagram->type = EC_DATAGRAM_BRD;
- datagram->address.physical.slave = 0x0000;
- datagram->address.physical.mem = offset;
+ EC_WRITE_U16(datagram->address, 0x0000);
+ EC_WRITE_U16(datagram->address + 2, offset);
EC_FUNC_FOOTER;
}
@@ -271,8 +274,8 @@
{
EC_FUNC_HEADER;
datagram->type = EC_DATAGRAM_BWR;
- datagram->address.physical.slave = 0x0000;
- datagram->address.physical.mem = offset;
+ EC_WRITE_U16(datagram->address, 0x0000);
+ EC_WRITE_U16(datagram->address + 2, offset);
EC_FUNC_FOOTER;
}
@@ -294,8 +297,51 @@
{
EC_FUNC_HEADER;
datagram->type = EC_DATAGRAM_LRW;
- datagram->address.logical = offset;
- EC_FUNC_FOOTER;
-}
-
-/*****************************************************************************/
+ EC_WRITE_U32(datagram->address, offset);
+ EC_FUNC_FOOTER;
+}
+
+/*****************************************************************************/
+
+/**
+ * Evaluates the working counter of a single-cast datagram.
+ * Outputs an error message.
+ */
+
+void ec_datagram_print_wc_error(
+ const ec_datagram_t *datagram
+ )
+{
+ if (datagram->working_counter == 0)
+ printk("No response.");
+ else if (datagram->working_counter > 1)
+ printk("%u slaves responded!", datagram->working_counter);
+ else
+ printk("Success.");
+ printk("\n");
+}
+
+/*****************************************************************************/
+
+/**
+ * Outputs datagram statistics at most every second.
+ */
+
+void ec_datagram_output_stats(
+ ec_datagram_t *datagram
+ )
+{
+ if (jiffies - datagram->stats_output_jiffies < HZ) {
+ datagram->stats_output_jiffies = jiffies;
+
+ if (unlikely(datagram->skip_count)) {
+ EC_WARN("Datagram %x (%s) was SKIPPED %u time%s.\n",
+ (unsigned int) datagram, datagram->name,
+ datagram->skip_count,
+ datagram->skip_count == 1 ? "" : "s");
+ datagram->skip_count = 0;
+ }
+ }
+}
+
+/*****************************************************************************/
--- a/master/datagram.h Fri Aug 10 15:27:08 2007 +0000
+++ b/master/datagram.h Thu Sep 13 11:08:46 2007 +0000
@@ -49,6 +49,11 @@
/*****************************************************************************/
+/** size of the datagram description string */
+#define EC_DATAGRAM_NAME_SIZE 20
+
+/*****************************************************************************/
+
/**
EtherCAT datagram type.
*/
@@ -84,28 +89,6 @@
/*****************************************************************************/
/**
- EtherCAT address.
-*/
-
-typedef union
-{
- /**
- * Physical address.
- */
- struct
- {
- uint16_t slave; /**< configured or autoincrement address */
- uint16_t mem; /**< physical memory address */
- }
- physical;
-
- uint32_t logical; /**< logical address */
-}
-ec_address_t;
-
-/*****************************************************************************/
-
-/**
EtherCAT datagram.
*/
@@ -115,7 +98,7 @@
struct list_head queue; /**< master datagram queue item */
struct list_head sent; /**< master list item for sent datagrams */
ec_datagram_type_t type; /**< datagram type (APRD, BWR, etc) */
- ec_address_t address; /**< recipient address */
+ uint8_t address[EC_ADDR_LEN]; /**< recipient address */
uint8_t *data; /**< datagram data */
size_t mem_size; /**< datagram \a data memory size */
size_t data_size; /**< size of the data in \a data */
@@ -125,7 +108,10 @@
cycles_t cycles_sent; /**< time, the datagram was sent */
unsigned long jiffies_sent; /**< jiffies, when the datagram was sent */
cycles_t cycles_received; /**< time, when the datagram was received */
- unsigned long jiffies_received; /**< jiffies, when the datagram was rec. */
+ unsigned long jiffies_received; /**< jiffies the datagram was received */
+ unsigned int skip_count; /**< number of requeues when not yet received */
+ unsigned long stats_output_jiffies; /**< last statistics output */
+ char name[EC_DATAGRAM_NAME_SIZE]; /**< description of the datagram */
}
ec_datagram_t;
@@ -143,6 +129,9 @@
int ec_datagram_bwr(ec_datagram_t *, uint16_t, size_t);
int ec_datagram_lrw(ec_datagram_t *, uint32_t, size_t);
+void ec_datagram_print_wc_error(const ec_datagram_t *);
+void ec_datagram_output_stats(ec_datagram_t *datagram);
+
/*****************************************************************************/
#endif
--- a/master/domain.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/domain.c Thu Sep 13 11:08:46 2007 +0000
@@ -269,6 +269,8 @@
}
ec_datagram_init(datagram);
+ snprintf(datagram->name, EC_DATAGRAM_NAME_SIZE,
+ "domain%u-%u", domain->index, offset);
if (ec_datagram_lrw(datagram, offset, data_size)) {
kfree(datagram);
@@ -298,7 +300,7 @@
ec_fmmu_t *fmmu;
unsigned int i, j, datagram_count;
uint32_t pdo_off, pdo_off_datagram;
- uint32_t datagram_offset;
+ uint32_t datagram_offset, log_addr;
size_t datagram_data_size, sync_size;
ec_datagram_t *datagram;
@@ -350,8 +352,9 @@
pdo_off = fmmu->logical_start_address + data_reg->sync_offset;
// search datagram
list_for_each_entry(datagram, &domain->datagrams, list) {
- pdo_off_datagram = pdo_off - datagram->address.logical;
- if (pdo_off >= datagram->address.logical &&
+ log_addr = EC_READ_U32(datagram->address);
+ pdo_off_datagram = pdo_off - log_addr;
+ if (pdo_off >= log_addr &&
pdo_off_datagram < datagram->mem_size) {
*data_reg->data_ptr = datagram->data +
pdo_off_datagram;
@@ -546,6 +549,7 @@
working_counter_sum = 0;
domain->state = 0;
list_for_each_entry(datagram, &domain->datagrams, list) {
+ ec_datagram_output_stats(datagram);
if (datagram->state == EC_DATAGRAM_RECEIVED) {
working_counter_sum += datagram->working_counter;
}
--- a/master/ethernet.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/ethernet.c Thu Sep 13 11:08:46 2007 +0000
@@ -94,11 +94,12 @@
{
ec_eoe_t **priv;
int result, i;
- char name[20];
+ char name[EC_DATAGRAM_NAME_SIZE];
eoe->slave = slave;
ec_datagram_init(&eoe->datagram);
+ eoe->queue_datagram = 0;
eoe->state = ec_eoe_state_rx_start;
eoe->opened = 0;
eoe->rx_skb = NULL;
@@ -117,12 +118,20 @@
eoe->tx_rate = 0;
eoe->rate_jiffies = 0;
- /* device name eoe<MASTER>s<SLAVE>, because system tools don't like
- * hyphens etc. in interface names. */
- sprintf(name, "eoe%us%u", slave->master->index, slave->ring_position);
+ /* device name eoe<MASTER>[as]<SLAVE>, because networking scripts don't
+ * like hyphens etc. in interface names. */
+ if (slave->sii_alias) {
+ snprintf(name, EC_DATAGRAM_NAME_SIZE,
+ "eoe%ua%u", slave->master->index, slave->sii_alias);
+ } else {
+ snprintf(name, EC_DATAGRAM_NAME_SIZE,
+ "eoe%us%u", slave->master->index, slave->ring_position);
+ }
+
+ snprintf(eoe->datagram.name, EC_DATAGRAM_NAME_SIZE, name);
if (!(eoe->dev = alloc_netdev(sizeof(ec_eoe_t *), name, ether_setup))) {
- EC_ERR("Unable to allocate net_device for EoE handler!\n");
+ EC_ERR("Unable to allocate net_device %s for EoE handler!\n", name);
goto out_return;
}
@@ -275,7 +284,7 @@
(eoe->tx_frame_number & 0x0F) << 12));
memcpy(data + 4, eoe->tx_frame->skb->data + eoe->tx_offset, current_size);
- ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
+ eoe->queue_datagram = 1;
eoe->tx_offset += current_size;
eoe->tx_fragment_number++;
@@ -292,6 +301,10 @@
{
if (!eoe->opened) return;
+ // if the datagram was not sent, or is not yet received, skip this cycle
+ if (eoe->queue_datagram || eoe->datagram.state == EC_DATAGRAM_SENT)
+ return;
+
// call state function
eoe->state(eoe);
@@ -303,6 +316,22 @@
eoe->tx_counter = 0;
eoe->rate_jiffies = jiffies;
}
+
+ ec_datagram_output_stats(&eoe->datagram);
+}
+
+/*****************************************************************************/
+
+/**
+ * Queues the datagram, if necessary.
+ */
+
+void ec_eoe_queue(ec_eoe_t *eoe /**< EoE handler */)
+{
+ if (eoe->queue_datagram) {
+ ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
+ eoe->queue_datagram = 0;
+ }
}
/*****************************************************************************/
@@ -334,7 +363,7 @@
return;
ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram);
- ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
+ eoe->queue_datagram = 1;
eoe->state = ec_eoe_state_rx_check;
}
@@ -360,7 +389,7 @@
}
ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->datagram);
- ec_master_queue_datagram(eoe->slave->master, &eoe->datagram);
+ eoe->queue_datagram = 1;
eoe->state = ec_eoe_state_rx_fetch;
}
--- a/master/ethernet.h Fri Aug 10 15:27:08 2007 +0000
+++ b/master/ethernet.h Thu Sep 13 11:08:46 2007 +0000
@@ -74,6 +74,7 @@
struct list_head list; /**< list item */
ec_slave_t *slave; /**< pointer to the corresponding slave */
ec_datagram_t datagram; /**< datagram */
+ unsigned int queue_datagram; /**< the datagram is ready for queuing */
void (*state)(ec_eoe_t *); /**< state function for the state machine */
struct net_device *dev; /**< net_device for virtual ethernet device */
struct net_device_stats stats; /**< device statistics */
@@ -102,6 +103,7 @@
int ec_eoe_init(ec_eoe_t *, ec_slave_t *);
void ec_eoe_clear(ec_eoe_t *);
void ec_eoe_run(ec_eoe_t *);
+void ec_eoe_queue(ec_eoe_t *);
int ec_eoe_is_open(const ec_eoe_t *);
/*****************************************************************************/
--- a/master/fsm_change.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_change.c Thu Sep 13 11:08:46 2007 +0000
@@ -190,13 +190,14 @@
fsm->jiffies_start = datagram->jiffies_sent;
}
- if (datagram->working_counter != 1) {
+ if (datagram->working_counter == 0) {
if (datagram->jiffies_received - fsm->jiffies_start >= 3 * HZ) {
char state_str[EC_STATE_STRING_SIZE];
ec_state_string(fsm->requested_state, state_str);
fsm->state = ec_fsm_change_state_error;
- EC_ERR("Failed to set state %s on slave %i: Slave did not"
- " respond.\n", state_str, fsm->slave->ring_position);
+ EC_ERR("Failed to set state %s on slave %i: ",
+ state_str, fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -207,6 +208,16 @@
return;
}
+ if (unlikely(datagram->working_counter > 1)) {
+ char state_str[EC_STATE_STRING_SIZE];
+ ec_state_string(fsm->requested_state, state_str);
+ fsm->state = ec_fsm_change_state_error;
+ EC_ERR("Failed to set state %s on slave %i: ",
+ state_str, fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
+ return;
+ }
+
fsm->take_time = 1;
// read AL status from slave
@@ -242,8 +253,9 @@
char req_state[EC_STATE_STRING_SIZE];
ec_state_string(fsm->requested_state, req_state);
fsm->state = ec_fsm_change_state_error;
- EC_ERR("Failed to check state %s on slave %i.\n",
+ EC_ERR("Failed to check state %s on slave %i: ",
req_state, slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -372,7 +384,8 @@
}
if (datagram->working_counter != 1) {
- EC_WARN("Reception of AL status code datagram failed.\n");
+ EC_WARN("Reception of AL status code datagram failed: ");
+ ec_datagram_print_wc_error(datagram);
}
else {
if ((code = EC_READ_U16(datagram->data))) {
@@ -433,8 +446,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_change_state_error;
- EC_ERR("Reception of state ack datagram failed - slave %i did not"
- " respond.\n", slave->ring_position);
+ EC_ERR("Reception of state ack datagram failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -471,8 +485,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_change_state_error;
- EC_ERR("Reception of state ack check datagram failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of state ack check datagram failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
--- a/master/fsm_coe.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_coe.c Thu Sep 13 11:08:46 2007 +0000
@@ -289,8 +289,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE dictionary request failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE dictionary request failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -325,9 +326,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
- " not respond.\n",
+ EC_ERR("Reception of CoE mailbox check datagram failed on slave %i: ",
slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -381,8 +382,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE dictionary response failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE dictionary response failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -506,8 +508,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE SDO description request failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE SDO description"
+ " request failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -542,8 +545,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE mailbox check"
+ " datagram failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -596,8 +600,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE SDO description response failed - slave %i"
- " did not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE SDO description"
+ " response failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -709,8 +714,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE SDO entry request failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE SDO entry request failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -746,8 +752,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE mailbox check"
+ " datagram failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -801,8 +808,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE SDO description response failed - slave %i"
- " did not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE SDO description"
+ " response failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -991,8 +999,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE download request failed - slave %i did not"
- " respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE download request failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1027,8 +1036,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE mailbox check"
+ " datagram failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1080,8 +1090,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE download response failed - slave %i did not"
- " respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE download response failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1200,8 +1211,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE upload request failed - slave %i did not"
- " respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE upload request failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1236,8 +1248,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE mailbox check"
+ " datagram failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1294,8 +1307,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE upload response failed - slave %i did not"
- " respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE upload response failed on slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1439,8 +1453,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE upload segment request failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE upload segment"
+ " request failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1475,8 +1490,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE mailbox check datagram failed - slave %i did"
- " not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE mailbox check"
+ " datagram failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1533,8 +1549,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_coe_error;
- EC_ERR("Reception of CoE upload segment response failed - slave %i"
- " did not respond.\n", slave->ring_position);
+ EC_ERR("Reception of CoE upload segment"
+ " response failed on slave %i: ", slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
--- a/master/fsm_master.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_master.c Thu Sep 13 11:08:46 2007 +0000
@@ -41,7 +41,9 @@
#include "globals.h"
#include "master.h"
#include "mailbox.h"
+#ifdef EC_EOE
#include "ethernet.h"
+#endif
#include "fsm_master.h"
/*****************************************************************************/
@@ -54,6 +56,7 @@
void ec_fsm_master_state_validate_product(ec_fsm_master_t *);
void ec_fsm_master_state_rewrite_addresses(ec_fsm_master_t *);
void ec_fsm_master_state_configure_slave(ec_fsm_master_t *);
+void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *);
void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *);
void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *);
void ec_fsm_master_state_sdodict(ec_fsm_master_t *);
@@ -238,8 +241,10 @@
fsm->idle = 0;
fsm->scan_jiffies = jiffies;
+#ifdef EC_EOE
ec_master_eoe_stop(master);
ec_master_clear_eoe_handlers(master);
+#endif
ec_master_destroy_slaves(master);
master->slave_count = datagram->working_counter;
@@ -276,13 +281,13 @@
list_add_tail(&slave->list, &master->slaves);
}
- EC_INFO("Scanning bus.\n");
-
- // begin scanning of slaves
- fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
- fsm->state = ec_fsm_master_state_scan_slaves;
- ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave);
- ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
+ if (master->debug_level)
+ EC_DBG("Clearing station addresses...\n");
+
+ ec_datagram_bwr(datagram, 0x0010, 2);
+ EC_WRITE_U16(datagram->data, 0x0000);
+ fsm->retries = EC_FSM_RETRIES;
+ fsm->state = ec_fsm_master_state_clear_addresses;
return;
}
}
@@ -587,18 +592,21 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
EC_ERR("Failed to receive AL state datagram for slave %i"
- " (datagram state %i)\n", slave->ring_position, datagram->state);
+ " (datagram state %i)\n",
+ slave->ring_position, datagram->state);
fsm->state = ec_fsm_master_state_error;
return;
}
// did the slave not respond to its station address?
- if (datagram->working_counter != 1) {
+ if (datagram->working_counter == 0) {
ec_slave_set_online_state(slave, EC_SLAVE_OFFLINE);
ec_fsm_master_action_next_slave_state(fsm);
return;
}
+ // FIXME what to to on multiple response?
+
// slave responded
ec_slave_set_state(slave, EC_READ_U8(datagram->data)); // set app state first
ec_slave_set_online_state(slave, EC_SLAVE_ONLINE);
@@ -774,8 +782,9 @@
}
if (datagram->working_counter != 1) {
- EC_ERR("Failed to write station address - slave %i did not respond.\n",
+ EC_ERR("Failed to write station address of slave %i: ",
slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
fsm->state = ec_fsm_master_state_error;
return;
}
@@ -794,6 +803,43 @@
/*****************************************************************************/
/**
+ * Master state: CLEAR ADDRESSES.
+ */
+
+void ec_fsm_master_state_clear_addresses(
+ ec_fsm_master_t *fsm /**< master state machine */
+ )
+{
+ ec_master_t *master = fsm->master;
+ ec_datagram_t *datagram = fsm->datagram;
+
+ if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
+ return;
+
+ if (datagram->state != EC_DATAGRAM_RECEIVED) {
+ EC_ERR("Failed to receive address clearing datagram (state %i).\n",
+ datagram->state);
+ fsm->state = ec_fsm_master_state_error;
+ return;
+ }
+
+ if (datagram->working_counter != master->slave_count) {
+ EC_WARN("Failed to clear all station addresses: Cleared %u of %u",
+ datagram->working_counter, master->slave_count);
+ }
+
+ EC_INFO("Scanning bus.\n");
+
+ // begin scanning of slaves
+ fsm->slave = list_entry(master->slaves.next, ec_slave_t, list);
+ fsm->state = ec_fsm_master_state_scan_slaves;
+ ec_fsm_slave_start_scan(&fsm->fsm_slave, fsm->slave);
+ ec_fsm_slave_exec(&fsm->fsm_slave); // execute immediately
+}
+
+/*****************************************************************************/
+
+/**
* Master state: SCAN SLAVES.
* Executes the sub-statemachine for the scanning of a slave.
*/
@@ -808,6 +854,7 @@
if (ec_fsm_slave_exec(&fsm->fsm_slave)) // execute slave state machine
return;
+#ifdef EC_EOE
if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
// create EoE handler for this slave
ec_eoe_t *eoe;
@@ -824,6 +871,7 @@
list_add_tail(&eoe->list, &master->eoe_handlers);
}
}
+#endif
// another slave to fetch?
if (slave->list.next != &master->slaves) {
@@ -836,8 +884,10 @@
EC_INFO("Bus scanning completed in %u ms.\n",
(u32) (jiffies - fsm->scan_jiffies) * 1000 / HZ);
+#ifdef EC_EOE
// check if EoE processing has to be started
ec_master_eoe_start(master);
+#endif
master->scan_state = EC_REQUEST_COMPLETE;
wake_up_interruptible(&master->scan_queue);
--- a/master/fsm_sii.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_sii.c Thu Sep 13 11:08:46 2007 +0000
@@ -196,8 +196,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_sii_error;
- EC_ERR("Reception of SII read datagram failed - slave %i did not"
- " respond.\n", fsm->slave->ring_position);
+ EC_ERR("Reception of SII read datagram failed on slave %i: ",
+ fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -242,8 +243,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_sii_error;
- EC_ERR("Reception of SII check/fetch datagram failed - slave %i did"
- " not respond\n", fsm->slave->ring_position);
+ EC_ERR("Reception of SII check/fetch datagram failed on slave %i: ",
+ fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -338,8 +340,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_sii_error;
- EC_ERR("Reception of SII write datagram failed - slave %i did not"
- " respond.\n", fsm->slave->ring_position);
+ EC_ERR("Reception of SII write datagram failed on slave %i: ",
+ fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -375,8 +378,9 @@
if (datagram->working_counter != 1) {
fsm->state = ec_fsm_sii_error;
- EC_ERR("Reception of SII write check datagram failed - slave %i did"
- " not respond.\n", fsm->slave->ring_position);
+ EC_ERR("Reception of SII write check datagram failed on slave %i: ",
+ fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
--- a/master/fsm_slave.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/fsm_slave.c Thu Sep 13 11:08:46 2007 +0000
@@ -226,8 +226,9 @@
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
- EC_ERR("Failed to write station address - slave %i did not respond.\n",
+ EC_ERR("Failed to write station address on slave %i: ",
fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -243,7 +244,9 @@
Slave scan state: STATE.
*/
-void ec_fsm_slave_scan_state_state(ec_fsm_slave_t *fsm /**< slave state machine */)
+void ec_fsm_slave_scan_state_state(
+ ec_fsm_slave_t *fsm /**< slave state machine */
+ )
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
@@ -262,8 +265,9 @@
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
- EC_ERR("Failed to read AL state - slave %i did not respond.\n",
+ EC_ERR("Failed to read AL state of slave %i: ",
fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -306,8 +310,9 @@
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
- EC_ERR("Failed to read base data - slave %i did not respond.\n",
+ EC_ERR("Failed to read base data from slave %i: ",
slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -352,8 +357,9 @@
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
- EC_ERR("Failed to read DL status - slave %i did not respond.\n",
+ EC_ERR("Failed to read DL status from slave %i: ",
slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -644,8 +650,9 @@
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
- EC_ERR("Failed to clear FMMUs - slave %i did not respond.\n",
+ EC_ERR("Failed to clear FMMUs of slave %i: ",
fsm->slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -726,8 +733,9 @@
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
- EC_ERR("Failed to set sync managers - slave %i did not respond.\n",
+ EC_ERR("Failed to set sync managers of slave %i: ",
slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -941,8 +949,9 @@
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
- EC_ERR("Failed to set process data sync managers - slave %i did not"
- " respond.\n", slave->ring_position);
+ EC_ERR("Failed to set process data sync managers of slave %i: ",
+ slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
@@ -1002,8 +1011,9 @@
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_state_error;
- EC_ERR("Failed to set FMMUs - slave %i did not respond.\n",
+ EC_ERR("Failed to set FMMUs of slave %i: ",
slave->ring_position);
+ ec_datagram_print_wc_error(datagram);
return;
}
--- a/master/globals.h Fri Aug 10 15:27:08 2007 +0000
+++ b/master/globals.h Thu Sep 13 11:08:46 2007 +0000
@@ -81,6 +81,9 @@
/** size of an EtherCAT datagram footer */
#define EC_DATAGRAM_FOOTER_SIZE 2
+/** size of the EtherCAT address field */
+#define EC_ADDR_LEN 4
+
/** resulting maximum data size of a single datagram in a frame */
#define EC_MAX_DATA_SIZE (ETH_DATA_LEN - EC_FRAME_HEADER_SIZE \
- EC_DATAGRAM_HEADER_SIZE - EC_DATAGRAM_FOOTER_SIZE)
--- a/master/master.c Fri Aug 10 15:27:08 2007 +0000
+++ b/master/master.c Thu Sep 13 11:08:46 2007 +0000
@@ -50,7 +50,9 @@
#include "slave.h"
#include "device.h"
#include "datagram.h"
+#ifdef EC_EOE
#include "ethernet.h"
+#endif
/*****************************************************************************/
@@ -58,9 +60,10 @@
void ec_master_sync_io(ec_master_t *);
static int ec_master_idle_thread(ec_master_t *);
static int ec_master_operation_thread(ec_master_t *);
+#ifdef EC_EOE
void ec_master_eoe_run(unsigned long);
+#endif
void ec_master_check_sdo(unsigned long);
-int ec_master_measure_bus_time(ec_master_t *);
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
ssize_t ec_store_master_attribute(struct kobject *, struct attribute *,
const char *, size_t);
@@ -139,15 +142,17 @@
master->stats.timeouts = 0;
master->stats.corrupted = 0;
- master->stats.skipped = 0;
master->stats.unmatched = 0;
master->stats.output_jiffies = 0;
for (i = 0; i < HZ; i++) {
master->idle_cycle_times[i] = 0;
+#ifdef EC_EOE
master->eoe_cycle_times[i] = 0;
+#endif
}
master->idle_cycle_time_pos = 0;
+#ifdef EC_EOE
master->eoe_cycle_time_pos = 0;
init_timer(&master->eoe_timer);
@@ -155,6 +160,7 @@
master->eoe_timer.data = (unsigned long) master;
master->eoe_running = 0;
INIT_LIST_HEAD(&master->eoe_handlers);
+#endif
master->internal_lock = SPIN_LOCK_UNLOCKED;
master->request_cb = NULL;
@@ -178,6 +184,7 @@
// init state machine datagram
ec_datagram_init(&master->fsm_datagram);
+ snprintf(master->fsm_datagram.name, EC_DATAGRAM_NAME_SIZE, "master-fsm");
if (ec_datagram_prealloc(&master->fsm_datagram, EC_MAX_DATA_SIZE)) {
EC_ERR("Failed to allocate FSM datagram.\n");
goto out_clear_backup;
@@ -228,7 +235,9 @@
ec_master_t *master /**< EtherCAT master */
)
{
+#ifdef EC_EOE
ec_master_clear_eoe_handlers(master);
+#endif
ec_master_destroy_slaves(master);
ec_master_destroy_domains(master);
ec_fsm_master_clear(&master->fsm);
@@ -243,6 +252,7 @@
/*****************************************************************************/
+#ifdef EC_EOE
/**
* Clear and free all EoE handlers.
*/
@@ -259,6 +269,7 @@
kfree(eoe);
}
}
+#endif
/*****************************************************************************/
@@ -394,7 +405,9 @@
{
master->mode = EC_MASTER_MODE_ORPHANED;
+#ifdef EC_EOE
ec_master_eoe_stop(master);
+#endif
ec_master_thread_stop(master);
ec_master_destroy_slaves(master);
}
@@ -408,7 +421,9 @@
int ec_master_enter_operation_mode(ec_master_t *master /**< EtherCAT master */)
{
ec_slave_t *slave;
+#ifdef EC_EOE
ec_eoe_t *eoe;
+#endif
down(&master->config_sem);
master->allow_config = 0; // temporarily disable slave configuration
@@ -442,11 +457,13 @@
list_for_each_entry(slave, &master->slaves, list) {
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
}
+#ifdef EC_EOE
// ... but set EoE slaves to OP
list_for_each_entry(eoe, &master->eoe_handlers, list) {
if (ec_eoe_is_open(eoe))
ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
}
+#endif
if (master->debug_level)
EC_DBG("Switching to operation mode.\n");
@@ -475,11 +492,15 @@
/**< EtherCAT master */)
{
ec_slave_t *slave;
+#ifdef EC_EOE
ec_eoe_t *eoe;
+#endif
master->mode = EC_MASTER_MODE_IDLE;
+#ifdef EC_EOE
ec_master_eoe_stop(master);
+#endif
ec_master_thread_stop(master);
master->request_cb = ec_master_request_cb;
@@ -491,17 +512,21 @@
ec_slave_reset(slave);
ec_slave_request_state(slave, EC_SLAVE_STATE_PREOP);
}
+#ifdef EC_EOE
// ... but leave EoE slaves in OP
list_for_each_entry(eoe, &master->eoe_handlers, list) {
if (ec_eoe_is_open(eoe))
ec_slave_request_state(eoe->slave, EC_SLAVE_STATE_OP);
}
+#endif
ec_master_destroy_domains(master);
if (ec_master_thread_start(master, ec_master_idle_thread))
EC_WARN("Failed to restart master thread!\n");
+#ifdef EC_EOE
ec_master_eoe_start(master);
+#endif
master->allow_scan = 1;
master->allow_config = 1;
@@ -522,10 +547,9 @@
// check, if the datagram is already queued
list_for_each_entry(queued_datagram, &master->datagram_queue, queue) {
if (queued_datagram == datagram) {
- master->stats.skipped++;
+ datagram->skip_count++;
if (master->debug_level)
EC_DBG("skipping datagram %x.\n", (unsigned int) datagram);
- ec_master_output_stats(master);
datagram->state = EC_DATAGRAM_QUEUED;
return;
}
@@ -592,7 +616,7 @@
// EtherCAT datagram header
EC_WRITE_U8 (cur_data, datagram->type);
EC_WRITE_U8 (cur_data + 1, datagram->index);
- EC_WRITE_U32(cur_data + 2, datagram->address.logical);
+ memcpy(cur_data + 2, datagram->address, EC_ADDR_LEN);
EC_WRITE_U16(cur_data + 6, datagram->data_size & 0x7FF);
EC_WRITE_U16(cur_data + 8, 0x0000);
follows_word = cur_data + 6;
@@ -772,11 +796,6 @@
master->stats.corrupted == 1 ? "" : "s");
master->stats.corrupted = 0;
}
- if (master->stats.skipped) {
- EC_WARN("%i datagram%s SKIPPED!\n", master->stats.skipped,
- master->stats.skipped == 1 ? "" : "s");
- master->stats.skipped = 0;
- }
if (master->stats.unmatched) {
EC_WARN("%i datagram%s UNMATCHED!\n", master->stats.unmatched,
master->stats.unmatched == 1 ? "" : "s");
@@ -800,6 +819,7 @@
while (!signal_pending(current)) {
cycles_start = get_cycles();
+ ec_datagram_output_stats(&master->fsm_datagram);
if (ec_fsm_master_running(&master->fsm)) { // datagram on the way
// receive
@@ -856,6 +876,7 @@
allow_signal(SIGTERM);
while (!signal_pending(current)) {
+ ec_datagram_output_stats(&master->fsm_datagram);
if (master->injection_seq_rt != master->injection_seq_fsm ||
master->fsm_datagram.state == EC_DATAGRAM_SENT ||
master->fsm_datagram.state == EC_DATAGRAM_QUEUED)
@@ -941,7 +962,9 @@
)
{
off_t off = 0;
+#ifdef EC_EOE
ec_eoe_t *eoe;
+#endif
uint32_t cur, sum, min, max, pos, i;
off += sprintf(buffer + off, "\nMode: ");
@@ -959,6 +982,10 @@
off += sprintf(buffer + off, "\nSlaves: %i\n",
master->slave_count);
+ off += sprintf(buffer + off, "Status: %s\n",
+ master->fsm.tainted ? "TAINTED" : "sane");
+ off += sprintf(buffer + off, "PDO slaves: %s\n",
+ master->pdo_slaves_offline ? "INCOMPLETE" : "online");
off += sprintf(buffer + off, "\nDevices:\n");
@@ -986,6 +1013,7 @@
off += sprintf(buffer + off, " Idle cycle: %u / %u.%u / %u\n",
min, sum / HZ, (sum * 100 / HZ) % 100, max);
+#ifdef EC_EOE
sum = 0;
min = 0xFFFFFFFF;
max = 0;
@@ -1006,6 +1034,7 @@
eoe->dev->name, eoe->rx_rate, eoe->tx_rate,
((eoe->rx_rate + eoe->tx_rate) / 8 + 512) / 1024);
}
+#endif
off += sprintf(buffer + off, "\n");
@@ -1075,6 +1104,7 @@
/*****************************************************************************/
+#ifdef EC_EOE
/**
Starts Ethernet-over-EtherCAT processing on demand.
*/
@@ -1141,11 +1171,11 @@
if (none_open)
goto queue_timer;
+ // receive datagrams
if (master->request_cb(master->cb_data)) goto queue_timer;
-
- // receive datagrams
cycles_start = get_cycles();
ecrt_master_receive(master);
+ master->release_cb(master->cb_data);
// actual EoE processing
list_for_each_entry(eoe, &master->eoe_handlers, list) {
@@ -1153,11 +1183,16 @@
}
// send datagrams
+ if (master->request_cb(master->cb_data)) {
+ goto queue_timer;
+ }
+ list_for_each_entry(eoe, &master->eoe_handlers, list) {
+ ec_eoe_queue(eoe);
+ }
ecrt_master_send(master);
+ master->release_cb(master->cb_data);
cycles_end = get_cycles();
- master->release_cb(master->cb_data);
-
master->eoe_cycle_times[master->eoe_cycle_time_pos]
= (u32) (cycles_end - cycles_start) * 1000 / cpu_khz;
master->eoe_cycle_time_pos++;
@@ -1166,72 +1201,10 @@
queue_timer:
restart_jiffies = HZ / EC_EOE_FREQUENCY;
if (!restart_jiffies) restart_jiffies = 1;
- master->eoe_timer.expires += restart_jiffies;
+ master->eoe_timer.expires = jiffies + restart_jiffies;
add_timer(&master->eoe_timer);
}
-
-/*****************************************************************************/
-
-/**
- Measures the time, a frame is on the bus.
- \return 0 in case of success, else < 0
-*/
-
-int ec_master_measure_bus_time(ec_master_t *master)
-{
- ec_datagram_t datagram;
- uint32_t cur, sum, min, max, i;
-
- ec_datagram_init(&datagram);
-
- if (ec_datagram_brd(&datagram, 0x0130, 2)) {
- EC_ERR("Failed to allocate datagram for bus time measuring.\n");
- ec_datagram_clear(&datagram);
- return -1;
- }
-
- ecrt_master_receive(master);
-
- sum = 0;
- min = 0xFFFFFFFF;
- max = 0;
-
- for (i = 0; i < 100; i++) {
- ec_master_queue_datagram(master, &datagram);
- ecrt_master_send(master);
-
- while (1) {
- ecrt_master_receive(master);
-
- if (datagram.state == EC_DATAGRAM_RECEIVED) {
- break;
- }
- else if (datagram.state == EC_DATAGRAM_ERROR) {
- EC_WARN("Failed to measure bus time.\n");
- goto error;
- }
- else if (datagram.state == EC_DATAGRAM_TIMED_OUT) {
- EC_WARN("Timeout while measuring bus time.\n");
- goto error;
- }
- }
-
- cur = (unsigned int) (datagram.cycles_received
- - datagram.cycles_sent) * 1000 / cpu_khz;
- sum += cur;
- if (cur > max) max = cur;
- if (cur < min) min = cur;
- }
-
- EC_DBG("Bus time is (min/avg/max) %u / %u.%u / %u us.\n",
- min, sum / 100, sum % 100, max);
- ec_datagram_clear(&datagram);
- return 0;
-
- error:
- ec_datagram_clear(&datagram);
- return -1;
-}
+#endif
/*****************************************************************************/
@@ -1431,7 +1404,9 @@
}
// restart EoE process and master thread with new locking
+#ifdef EC_EOE
ec_master_eoe_stop(master);
+#endif
ec_master_thread_stop(master);
ec_master_prepare(master); // prepare asynchronous IO
@@ -1449,7 +1424,9 @@
EC_ERR("Failed to start master thread!\n");
return -1;
}
+#ifdef EC_EOE
ec_master_eoe_start(master);
+#endif
return 0;
}
--- a/master/master.h Fri Aug 10 15:27:08 2007 +0000
+++ b/master/master.h Thu Sep 13 11:08:46 2007 +0000
@@ -75,8 +75,6 @@
{
unsigned int timeouts; /**< datagram timeouts */
unsigned int corrupted; /**< corrupted frames */
- unsigned int skipped; /**< skipped datagrams (the ones that were
- requeued when not yet received) */
unsigned int unmatched; /**< unmatched datagrams (received, but not
queued any longer) */
unsigned long output_jiffies; /**< time of last output */
@@ -145,11 +143,13 @@
uint32_t idle_cycle_times[HZ]; /**< Idle cycle times ring */
unsigned int idle_cycle_time_pos; /**< time ring buffer position */
+#ifdef EC_EOE
struct timer_list eoe_timer; /**< EoE timer object */
unsigned int eoe_running; /**< non-zero, if EoE processing is active. */
struct list_head eoe_handlers; /**< Ethernet-over-EtherCAT handlers */
uint32_t eoe_cycle_times[HZ]; /**< EoE cycle times ring */
unsigned int eoe_cycle_time_pos; /**< time ring buffer position */
+#endif
spinlock_t internal_lock; /**< spinlock used in idle mode */
int (*request_cb)(void *); /**< lock request callback */
@@ -185,9 +185,11 @@
int ec_master_enter_operation_mode(ec_master_t *);
void ec_master_leave_operation_mode(ec_master_t *);
+#ifdef EC_EOE
// EoE
void ec_master_eoe_start(ec_master_t *);
void ec_master_eoe_stop(ec_master_t *);
+#endif
// datagram IO
void ec_master_receive_datagrams(ec_master_t *, const uint8_t *, size_t);
@@ -195,7 +197,9 @@
// misc.
void ec_master_output_stats(ec_master_t *);
+#ifdef EC_EOE
void ec_master_clear_eoe_handlers(ec_master_t *);
+#endif
void ec_master_destroy_slaves(ec_master_t *);
/*****************************************************************************/
--- a/script/Makefile.am Fri Aug 10 15:27:08 2007 +0000
+++ b/script/Makefile.am Thu Sep 13 11:08:46 2007 +0000
@@ -39,6 +39,6 @@
bin_SCRIPTS = lsec
-EXTRA_DIST = lsec
+EXTRA_DIST = lsec ifup-eoe.sh
#------------------------------------------------------------------------------
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/script/ifup-eoe.sh Thu Sep 13 11:08:46 2007 +0000
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+#------------------------------------------------------------------------------
+#
+# $Id$
+#
+# Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
+#
+# This file is part of the IgH EtherCAT Master.
+#
+# The IgH EtherCAT Master is free software; you can redistribute it
+# and/or modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# The IgH EtherCAT Master 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the IgH EtherCAT Master; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+# The right to use EtherCAT Technology is granted and comes free of
+# charge under condition of compatibility of product made by
+# Licensee. People intending to distribute/sell products based on the
+# code, have to sign an agreement to guarantee that products using
+# software based on IgH EtherCAT master stay compatible with the actual
+# EtherCAT specification (which are released themselves as an open
+# standard) as the (only) precondition to have the right to use EtherCAT
+# Technology, IP and trade marks.
+#
+#------------------------------------------------------------------------------
+
+# this ifup.d script adds special network interfaces to a network bridge
+
+CFGNAME=${1}
+IFNAME=${2}
+
+# customize here
+BRNAME="eoebr0"
+INTERFACES=""
+BRCTL="/sbin/brctl"
+LOGGER="logger -t ifup-eoe"
+
+# if the current interface in the list of interfaces to bridge?
+if ! echo ${INTERFACES} | grep -qw ${IFNAME}; then
+ exit 0;
+fi
+
+# does the EoE bridge already exist?
+if ! ${BRCTL} show | grep -q "^${BRNAME}"; then
+ ${LOGGER} Creating ${BRNAME}
+ ${BRCTL} addbr ${BRNAME} # create it
+fi
+
+${LOGGER} Adding ${IFNAME} to ${BRNAME}
+ip link set ${IFNAME} down
+ip addr flush dev ${IFNAME}
+${BRCTL} addif ${BRNAME} ${IFNAME}
+ip link set ${IFNAME} up
+
+#------------------------------------------------------------------------------
--- a/script/init.d/ethercat Fri Aug 10 15:27:08 2007 +0000
+++ b/script/init.d/ethercat Thu Sep 13 11:08:46 2007 +0000
@@ -102,6 +102,7 @@
{
if [ -r /etc/rc.status ]; then
rc_failed
+ rc_status -v
rc_exit
else
echo " failed"
@@ -111,6 +112,20 @@
#------------------------------------------------------------------------------
+function exit_dead()
+{
+ if [ -r /etc/rc.status ]; then
+ rc_failed
+ rc_status -v
+ rc_exit
+ else
+ echo " dead"
+ exit 1
+ fi
+}
+
+#------------------------------------------------------------------------------
+
function parse_mac_address()
{
if [ -z "${1}" ]; then
@@ -228,7 +243,7 @@
if [ ${MASTERS_RUNNING} -eq 0 -a ${MASTERS_IDLE} -eq 0 ]; then
exit_running
else
- exit_fail
+ exit_dead
fi
;;