Determine type of DC implementation (full or delay meas. only); update scan FSM graph.
authorFlorian Pose <fp@igh-essen.com>
Mon, 27 Apr 2009 11:38:03 +0000
changeset 1419 8fc38c37d86e
parent 1418 8b10ba4d3302
child 1420 5eb814732c46
Determine type of DC implementation (full or delay meas. only); update scan FSM graph.
documentation/graphs/fsm_slave_scan.dot
master/cdev.c
master/fsm_slave_config.c
master/fsm_slave_scan.c
master/ioctl.h
master/master.c
master/slave.c
master/slave.h
tool/CommandSlaves.cpp
--- a/documentation/graphs/fsm_slave_scan.dot	Fri Apr 24 13:43:51 2009 +0000
+++ b/documentation/graphs/fsm_slave_scan.dot	Mon Apr 27 11:38:03 2009 +0000
@@ -14,7 +14,14 @@
     state -> base [weight=10]
 
     base [fontname="Helvetica"]
-    base -> datalink [weight=10]
+    base -> dc_cap [weight=10]
+    base -> enter_datalink [fontname="Helvetica", label="DC not\nsupported"]
+
+    dc_cap [fontname="Helvetica"]
+    dc_cap -> enter_datalink [weight=10]
+
+    enter_datalink [shape=point, label=""]
+    enter_datalink -> datalink [weight=10]
 
     datalink [fontname="Helvetica"]
     datalink -> sii_size [weight=10]
@@ -23,10 +30,21 @@
     sii_size -> sii_data [weight=10]
 
     sii_data [fontname="Helvetica"]
-    sii_data -> preop [weight=10]
+    sii_data -> end [fontname="Helvetica", label="No category\ndata"]
+    sii_data -> enter_preop [weight=10]
+
+    enter_preop [shape=point, label=""]
+    enter_preop -> preop [fontname="Helvetica", label="Not in\nPREOP"]
+    enter_preop -> sync [weight=10]
 
     preop [fontname="Helvetica"]
-    preop -> pdos [weight=10]
+    preop -> enter_pdos [weight=10]
+
+    sync [fontname="Helvetica"]
+    sync -> enter_pdos [weight=10]
+
+    enter_pdos [shape=point, label=""]
+    enter_pdos -> pdos [weight=10]
 
     pdos [fontname="Helvetica"]
     pdos -> end [weight=10]
--- a/master/cdev.c	Fri Apr 24 13:43:51 2009 +0000
+++ b/master/cdev.c	Mon Apr 27 11:38:03 2009 +0000
@@ -262,6 +262,7 @@
     data.fmmu_bit = slave->base_fmmu_bit_operation;
     data.dc_supported = slave->base_dc_supported;
     data.dc_range = slave->base_dc_range;
+    data.has_dc_system_time = slave->has_dc_system_time;
     data.al_state = slave->current_state;
     data.error_flag = slave->error_flag;
 
--- a/master/fsm_slave_config.c	Fri Apr 24 13:43:51 2009 +0000
+++ b/master/fsm_slave_config.c	Mon Apr 27 11:38:03 2009 +0000
@@ -348,7 +348,7 @@
     ec_slave_t *slave = fsm->slave;
     ec_datagram_t *datagram = fsm->datagram;
 
-    if (!slave->base_dc_supported) {
+    if (!slave->base_dc_supported || !slave->has_dc_system_time) {
         ec_fsm_slave_config_enter_mbox_sync(fsm);
         return;
     }
@@ -1035,7 +1035,7 @@
     }
 
     if (config->dc_assign_activate) {
-        if (!slave->base_dc_supported) {
+        if (!slave->base_dc_supported || !slave->has_dc_system_time) {
             EC_WARN("Slave %u seems not to support distributed clocks!\n",
                     slave->ring_position);
         }
--- a/master/fsm_slave_scan.c	Fri Apr 24 13:43:51 2009 +0000
+++ b/master/fsm_slave_scan.c	Mon Apr 27 11:38:03 2009 +0000
@@ -47,6 +47,7 @@
 void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *);
 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_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 *);
@@ -57,6 +58,7 @@
 void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *);
 
+void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *);
 void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *);
 
@@ -316,6 +318,78 @@
     slave->base_dc_supported = (octet >> 2) & 0x01;
     slave->base_dc_range = ((octet >> 3) & 0x01) ? EC_DC_64 : EC_DC_32;
 
+    if (slave->base_dc_supported) {
+        // read DC capabilities
+        ec_datagram_fprd(datagram, slave->station_address, 0x0910,
+                slave->base_dc_range == EC_DC_64 ? 8 : 4);
+        ec_datagram_zero(datagram);
+        fsm->retries = EC_FSM_RETRIES;
+        fsm->state = ec_fsm_slave_scan_state_dc_cap;
+    } else {
+        ec_fsm_slave_scan_enter_datalink(fsm);
+    }
+}
+
+/*****************************************************************************/
+
+/**
+   Slave scan state: DC CAPABILITIES.
+*/
+
+void ec_fsm_slave_scan_state_dc_cap(
+        ec_fsm_slave_scan_t *fsm /**< slave state machine */
+        )
+{
+    ec_datagram_t *datagram = fsm->datagram;
+    ec_slave_t *slave = fsm->slave;
+
+    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) {
+        slave->has_dc_system_time = 1;
+        if (slave->master->debug_level) {
+            EC_DBG("Slave %u has the System Time register.\n",
+                    slave->ring_position);
+        }
+    } else if (datagram->working_counter == 0) {
+        if (slave->master->debug_level) {
+            EC_DBG("Slave %u has no System Time register; delay "
+                    "measurement only.\n", slave->ring_position);
+        }
+    } else {
+        fsm->slave->error_flag = 1;
+        fsm->state = ec_fsm_slave_scan_state_error;
+        EC_ERR("Failed to determine, if system time register is "
+                "supported by slave %u: ", slave->ring_position);
+        ec_datagram_print_wc_error(datagram);
+        return;
+    }
+
+    ec_fsm_slave_scan_enter_datalink(fsm);
+}
+
+/*****************************************************************************/
+
+/**
+   Slave scan entry function: DATALINK.
+*/
+
+void ec_fsm_slave_scan_enter_datalink(
+        ec_fsm_slave_scan_t *fsm /**< slave state machine */
+        )
+{
+    ec_datagram_t *datagram = fsm->datagram;
+    ec_slave_t *slave = fsm->slave;
+
     // read data link status
     ec_datagram_fprd(datagram, slave->station_address, 0x0110, 2);
     ec_datagram_zero(datagram);
--- a/master/ioctl.h	Fri Apr 24 13:43:51 2009 +0000
+++ b/master/ioctl.h	Mon Apr 27 11:38:03 2009 +0000
@@ -169,6 +169,7 @@
     uint8_t fmmu_bit;
     uint8_t dc_supported;
     ec_slave_dc_range_t dc_range;
+    uint8_t has_dc_system_time;
     uint8_t al_state;
     uint8_t error_flag;
     uint8_t sync_count;
--- a/master/master.c	Fri Apr 24 13:43:51 2009 +0000
+++ b/master/master.c	Mon Apr 27 11:38:03 2009 +0000
@@ -1363,7 +1363,7 @@
     for (slave = master->slaves;
             slave < master->slaves + master->slave_count;
             slave++) {
-		if (slave->base_dc_supported) {
+		if (slave->base_dc_supported && slave->has_dc_system_time) {
 			ref_clock_addr = slave->station_address;
 			break;
 		}
--- a/master/slave.c	Fri Apr 24 13:43:51 2009 +0000
+++ b/master/slave.c	Mon Apr 27 11:38:03 2009 +0000
@@ -100,6 +100,7 @@
     slave->base_fmmu_bit_operation = 0;
     slave->base_dc_supported = 0;
     slave->base_dc_range = EC_DC_32;
+    slave->has_dc_system_time = 0;
 
     slave->sii_words = NULL;
     slave->sii_nwords = 0;
--- a/master/slave.h	Fri Apr 24 13:43:51 2009 +0000
+++ b/master/slave.h	Mon Apr 27 11:38:03 2009 +0000
@@ -133,6 +133,9 @@
     uint8_t base_fmmu_bit_operation; /**< FMMU bit operation is supported. */
     uint8_t base_dc_supported; /**< Distributed clocks are supported. */
     ec_slave_dc_range_t base_dc_range; /**< DC range. */
+    uint8_t has_dc_system_time; /**< The slave supports the DC system time
+                                  register. Otherwise it can only be used for
+                                  delay measurement. */
 
     // data link status
     ec_slave_port_t ports[EC_MAX_PORTS]; /**< Port link status. */
--- a/tool/CommandSlaves.cpp	Fri Apr 24 13:43:51 2009 +0000
+++ b/tool/CommandSlaves.cpp	Mon Apr 27 11:38:03 2009 +0000
@@ -268,18 +268,21 @@
             << (si->fmmu_bit ? "yes" : "no") << endl
             << "  Distributed clocks: ";
         if (si->dc_supported) {
-            cout << "yes (";
-            switch (si->dc_range) {
-                case EC_DC_32:
-                    cout << "32 bit";
-                    break;
-                case EC_DC_64:
-                    cout << "64 bit";
-                    break;
-                default:
-                    cout << "???";
-            }
-            cout << ")";
+            if (si->has_dc_system_time) {
+                cout << "yes, ";
+                switch (si->dc_range) {
+                    case EC_DC_32:
+                        cout << "32 bit";
+                        break;
+                    case EC_DC_64:
+                        cout << "64 bit";
+                        break;
+                    default:
+                        cout << "???";
+                }
+            } else {
+                cout << "yes, delay measurement only";
+            }
         } else {
             cout << "no";
         }