# HG changeset patch # User Florian Pose # Date 1189681726 0 # Node ID 07fd94c5119dd2f4fe6bc34aff24ec8fa39740e2 # Parent 7bc131b92039b60b86fc4a3118b7e970a8758893 MERGE -r908:HEAD svn://yak/vol/projekte/msr_messen_steuern_regeln/ethercat/rep/trunk (1.3.1 changes) diff -r 7bc131b92039 -r 07fd94c5119d Makefile.am --- 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 diff -r 7bc131b92039 -r 07fd94c5119d NEWS --- 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. diff -r 7bc131b92039 -r 07fd94c5119d README.EoE --- /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. + +------------------------------------------------------------------------------- diff -r 7bc131b92039 -r 07fd94c5119d TODO --- 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 _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. diff -r 7bc131b92039 -r 07fd94c5119d configure.ac --- 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 #------------------------------------------------------------------------------ diff -r 7bc131b92039 -r 07fd94c5119d documentation/graphs/Makefile --- 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) diff -r 7bc131b92039 -r 07fd94c5119d documentation/graphs/fsm_master.dot --- /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 +} diff -r 7bc131b92039 -r 07fd94c5119d include/ecdb.h --- 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 diff -r 7bc131b92039 -r 07fd94c5119d include/ecrt.h --- 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) /** diff -r 7bc131b92039 -r 07fd94c5119d master/Kbuild --- 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 diff -r 7bc131b92039 -r 07fd94c5119d master/datagram.c --- 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; + } + } +} + +/*****************************************************************************/ diff -r 7bc131b92039 -r 07fd94c5119d master/datagram.h --- 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 diff -r 7bc131b92039 -r 07fd94c5119d master/domain.c --- 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; } diff -r 7bc131b92039 -r 07fd94c5119d master/ethernet.c --- 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 eoes, 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[as], 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; } diff -r 7bc131b92039 -r 07fd94c5119d master/ethernet.h --- 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 *); /*****************************************************************************/ diff -r 7bc131b92039 -r 07fd94c5119d master/fsm_change.c --- 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; } diff -r 7bc131b92039 -r 07fd94c5119d master/fsm_coe.c --- 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; } diff -r 7bc131b92039 -r 07fd94c5119d master/fsm_master.c --- 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); diff -r 7bc131b92039 -r 07fd94c5119d master/fsm_sii.c --- 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; } diff -r 7bc131b92039 -r 07fd94c5119d master/fsm_slave.c --- 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; } diff -r 7bc131b92039 -r 07fd94c5119d master/globals.h --- 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) diff -r 7bc131b92039 -r 07fd94c5119d master/master.c --- 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; } diff -r 7bc131b92039 -r 07fd94c5119d master/master.h --- 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 *); /*****************************************************************************/ diff -r 7bc131b92039 -r 07fd94c5119d script/Makefile.am --- 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 #------------------------------------------------------------------------------ diff -r 7bc131b92039 -r 07fd94c5119d script/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 + +#------------------------------------------------------------------------------ diff -r 7bc131b92039 -r 07fd94c5119d script/init.d/ethercat --- 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 ;;