Measure port receive times.
authorFlorian Pose <fp@igh-essen.com>
Mon, 27 Apr 2009 15:20:14 +0000
changeset 1420 5eb814732c46
parent 1419 8fc38c37d86e
child 1421 043a518831b2
Measure port receive times.
TODO
documentation/graphs/fsm_master.dot
master/cdev.c
master/fsm_master.c
master/fsm_slave_scan.c
master/globals.h
master/ioctl.h
master/slave.c
master/slave.h
tool/CommandSlaves.cpp
--- a/TODO	Mon Apr 27 11:38:03 2009 +0000
+++ b/TODO	Mon Apr 27 15:20:14 2009 +0000
@@ -14,6 +14,7 @@
     - Delay calculation.
     - Use common application time offset when setting start times.
     - Check 32/64 bit operations.
+    - Set system time offset only when application time available.
 * Fix unloading problem of ec_e100 driver.
 * Use ec_datagram_zero() where possible.
 * Fix arguments of reg_read.
--- a/documentation/graphs/fsm_master.dot	Mon Apr 27 11:38:03 2009 +0000
+++ b/documentation/graphs/fsm_master.dot	Mon Apr 27 15:20:14 2009 +0000
@@ -43,7 +43,10 @@
     acknowledge -> action_configure [weight=10]
 
     clear_addresses [fontname="Helvetica"]
-    clear_addresses -> scan_slave [weight=10]
+    clear_addresses -> dc_measure_delays [weight=10]
+
+    dc_measure_delays [fontname="Helvetica"]
+    dc_measure_delays -> scan_slave [weight=10]
 
     scan_slave [fontname="Helvetica"]
     scan_slave -> start
--- a/master/cdev.c	Mon Apr 27 11:38:03 2009 +0000
+++ b/master/cdev.c	Mon Apr 27 15:20:14 2009 +0000
@@ -257,7 +257,11 @@
     data.general_flags = slave->sii.general_flags;
     data.current_on_ebus = slave->sii.current_on_ebus;
     for (i = 0; i < EC_MAX_PORTS; i++) {
-        data.ports[i] = slave->base_ports[i];
+        data.port_descs[i] = slave->base_ports[i];
+        data.ports[i].dl_link = slave->ports[i].dl_link;
+        data.ports[i].dl_loop = slave->ports[i].dl_loop;
+        data.ports[i].dl_signal = slave->ports[i].dl_signal;
+        data.dc_receive_times[i] = slave->dc_receive_times[i];
     }
     data.fmmu_bit = slave->base_fmmu_bit_operation;
     data.dc_supported = slave->base_dc_supported;
--- a/master/fsm_master.c	Mon Apr 27 11:38:03 2009 +0000
+++ b/master/fsm_master.c	Mon Apr 27 15:20:14 2009 +0000
@@ -52,6 +52,7 @@
 void ec_fsm_master_state_acknowledge(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_dc_measure_delays(ec_fsm_master_t *);
 void ec_fsm_master_state_scan_slave(ec_fsm_master_t *);
 void ec_fsm_master_state_write_sii(ec_fsm_master_t *);
 void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *);
@@ -771,6 +772,42 @@
                 datagram->working_counter, master->slave_count);
     }
 
+    if (master->debug_level)
+        EC_DBG("Sending broadcast-write to measure transmission delays.\n");
+
+    ec_datagram_bwr(datagram, 0x0900, 1);
+    ec_datagram_zero(datagram);
+    fsm->retries = EC_FSM_RETRIES;
+    fsm->state = ec_fsm_master_state_dc_measure_delays;
+}
+
+/*****************************************************************************/
+
+/** Master state: DC MEASURE DELAYS.
+ */
+void ec_fsm_master_state_dc_measure_delays(
+        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 delay measuring datagram (state %u).\n",
+                datagram->state);
+        master->scan_busy = 0;
+        wake_up_interruptible(&master->scan_queue);
+        ec_fsm_master_restart(fsm);
+        return;
+    }
+
+    if (master->debug_level)
+        EC_DBG("%u slaves responded to delay measuring.\n",
+                datagram->working_counter);
+
     EC_INFO("Scanning bus.\n");
 
     // begin scanning of slaves
--- a/master/fsm_slave_scan.c	Mon Apr 27 11:38:03 2009 +0000
+++ b/master/fsm_slave_scan.c	Mon Apr 27 15:20:14 2009 +0000
@@ -48,6 +48,7 @@
 void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *);
+void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *);
@@ -257,11 +258,11 @@
 
 /*****************************************************************************/
 
-/**
-   Slave scan state: BASE.
-*/
-
-void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *fsm /**< slave state machine */)
+/** Slave scan state: BASE.
+ */
+void ec_fsm_slave_scan_state_base(
+        ec_fsm_slave_scan_t *fsm /**< slave state machine */
+        )
 {
     ec_datagram_t *datagram = fsm->datagram;
     ec_slave_t *slave = fsm->slave;
@@ -374,6 +375,51 @@
         return;
     }
 
+    // read DC port receive times
+    ec_datagram_fprd(datagram, slave->station_address, 0x0900, 16);
+    ec_datagram_zero(datagram);
+    fsm->retries = EC_FSM_RETRIES;
+    fsm->state = ec_fsm_slave_scan_state_dc_times;
+}
+
+/*****************************************************************************/
+
+/**
+   Slave scan state: DC TIMES.
+*/
+
+void ec_fsm_slave_scan_state_dc_times(
+        ec_fsm_slave_scan_t *fsm /**< slave state machine */
+        )
+{
+    ec_datagram_t *datagram = fsm->datagram;
+    ec_slave_t *slave = fsm->slave;
+    int i;
+
+    if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
+        return;
+
+    if (datagram->state != EC_DATAGRAM_RECEIVED) {
+        fsm->state = ec_fsm_slave_scan_state_error;
+        EC_ERR("Failed to receive system time datagram for slave %u"
+                " (datagram state %u).\n",
+               slave->ring_position, datagram->state);
+        return;
+    }
+
+    if (datagram->working_counter != 1) {
+        fsm->slave->error_flag = 1;
+        fsm->state = ec_fsm_slave_scan_state_error;
+        EC_ERR("Failed to get DC receive times of slave %u: ",
+                slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
+        return;
+    }
+
+    for (i = 0; i < EC_MAX_PORTS; i++) {
+        slave->dc_receive_times[i] = EC_READ_U32(datagram->data + 4 * i);
+    }
+
     ec_fsm_slave_scan_enter_datalink(fsm);
 }
 
--- a/master/globals.h	Mon Apr 27 11:38:03 2009 +0000
+++ b/master/globals.h	Mon Apr 27 15:20:14 2009 +0000
@@ -166,6 +166,14 @@
     EC_PORT_MII
 } ec_slave_port_desc_t;
 
+/** EtherCAT slave port information.
+ */
+typedef struct {
+    uint8_t dl_link; /**< Link detected. */
+    uint8_t dl_loop; /**< Loop closed. */
+    uint8_t dl_signal; /**< Detected signal on RX port. */
+} ec_slave_port_t;
+
 /** EtherCAT slave distributed clocks range.
  */
 typedef enum {
--- a/master/ioctl.h	Mon Apr 27 11:38:03 2009 +0000
+++ b/master/ioctl.h	Mon Apr 27 15:20:14 2009 +0000
@@ -165,11 +165,13 @@
     ec_sii_coe_details_t coe_details;
     ec_sii_general_flags_t general_flags;
     int16_t current_on_ebus;
-    ec_slave_port_desc_t ports[EC_MAX_PORTS];
+    ec_slave_port_desc_t port_descs[EC_MAX_PORTS];
+    ec_slave_port_t ports[EC_MAX_PORTS];
     uint8_t fmmu_bit;
     uint8_t dc_supported;
     ec_slave_dc_range_t dc_range;
     uint8_t has_dc_system_time;
+    uint32_t dc_receive_times[EC_MAX_PORTS];
     uint8_t al_state;
     uint8_t error_flag;
     uint8_t sync_count;
--- a/master/slave.c	Mon Apr 27 11:38:03 2009 +0000
+++ b/master/slave.c	Mon Apr 27 15:20:14 2009 +0000
@@ -95,6 +95,8 @@
         slave->ports[i].dl_loop = 0;
         slave->ports[i].dl_signal = 0;
         slave->sii.physical_layer[i] = 0xFF;
+
+        slave->dc_receive_times[i] = 0U;
     }
 
     slave->base_fmmu_bit_operation = 0;
--- a/master/slave.h	Mon Apr 27 11:38:03 2009 +0000
+++ b/master/slave.h	Mon Apr 27 15:20:14 2009 +0000
@@ -92,16 +92,6 @@
 
 /*****************************************************************************/
 
-/** EtherCAT slave port information.
- */
-typedef struct {
-    uint8_t dl_link; /**< Link detected. */
-    uint8_t dl_loop; /**< Loop closed. */
-    uint8_t dl_signal; /**< Detected signal on RX port. */
-} ec_slave_port_t;
-
-/*****************************************************************************/
-
 /** EtherCAT slave.
  */
 struct ec_slave
@@ -136,6 +126,8 @@
     uint8_t has_dc_system_time; /**< The slave supports the DC system time
                                   register. Otherwise it can only be used for
                                   delay measurement. */
+    uint32_t dc_receive_times[EC_MAX_PORTS]; /**< Port receive times for delay
+                                               measurement. */
 
     // data link status
     ec_slave_port_t ports[EC_MAX_PORTS]; /**< Port link status. */
--- a/tool/CommandSlaves.cpp	Mon Apr 27 11:38:03 2009 +0000
+++ b/tool/CommandSlaves.cpp	Mon Apr 27 15:20:14 2009 +0000
@@ -241,28 +241,6 @@
             << "  Serial number:   0x"
             << setw(8) << si->serial_number << endl;
 
-        cout << "Ports:" << endl;
-        for (i = 0; i < EC_MAX_PORTS; i++) {
-            cout << "  " << i << ": ";
-            switch (si->ports[i]) {
-                case EC_PORT_NOT_IMPLEMENTED:
-                    cout << "Not implemented.";
-                    break;
-                case EC_PORT_NOT_CONFIGURED:
-                    cout << "Not configured.";
-                    break;
-                case EC_PORT_EBUS:
-                    cout << "EBUS.";
-                    break;
-                case EC_PORT_MII:
-                    cout << "MII.";
-                    break;
-                default:
-                    cout << "???";
-            }
-            cout << endl;
-        }
-
         cout << "DL information:" << endl
             << "  FMMU bit operation: "
             << (si->fmmu_bit ? "yes" : "no") << endl
@@ -280,13 +258,62 @@
                     default:
                         cout << "???";
                 }
+                cout << endl;
             } else {
-                cout << "yes, delay measurement only";
+                cout << "yes, delay measurement only" << endl;
             }
         } else {
-            cout << "no";
-        }
+            cout << "no" << endl;
+        }
+
+        cout << "Port  Type  Link  Loop    Signal";
+        if (si->dc_supported)
+            cout << "  RxTime      Diff";
         cout << endl;
+            
+        for (i = 0; i < EC_MAX_PORTS; i++) {
+            cout << "   " << i << "  " << setfill(' ') << left << setw(4);
+            switch (si->port_descs[i]) {
+                case EC_PORT_NOT_IMPLEMENTED:
+                    cout << "N/A";
+                    break;
+                case EC_PORT_NOT_CONFIGURED:
+                    cout << "N/C";
+                    break;
+                case EC_PORT_EBUS:
+                    cout << "EBUS";
+                    break;
+                case EC_PORT_MII:
+                    cout << "MII";
+                    break;
+                default:
+                    cout << "???";
+            }
+
+            cout << "  " << setw(4)
+                << (si->ports[i].dl_link ? "up" : "down")
+                << "  " << setw(6)
+                << (si->ports[i].dl_loop ? "closed" : "open")
+                << "  " << setw(3)
+                << (si->ports[i].dl_signal ? "yes" : "no");
+            
+            if (si->dc_supported) {
+                cout << "     " << setw(10) << right;
+                if (si->ports[i].dl_signal) {
+                    cout << dec << si->dc_receive_times[i];
+                } else {
+                    cout << "-";
+                }
+                cout << "  " << setw(10);
+                if (si->ports[i].dl_signal) {
+                    cout << si->dc_receive_times[i] - si->dc_receive_times[0];
+                } else {
+                    cout << "-";
+                }
+            }
+
+            cout << endl;
+        }
 
         if (si->mailbox_protocols) {
             list<string> protoList;