Use application start time as a common reference for cyclic generation
authorFlorian Pose <fp@igh-essen.com>
Mon, 04 May 2009 12:11:00 +0000
changeset 1436 08eaf72409bb
parent 1435 f1df39224f49
child 1437 97c248dd1bd3
Use application start time as a common reference for cyclic generation
start times.
TODO
master/fsm_slave_config.c
master/master.c
master/master.h
--- a/TODO	Mon May 04 12:10:11 2009 +0000
+++ b/TODO	Mon May 04 12:11:00 2009 +0000
@@ -11,9 +11,7 @@
 Version 1.5.0:
 
 * Distributed clocks:
-    - Use common application time offset when setting start times.
     - Check 32/64 bit operations.
-    - Set system time offset only when application time available.
     - Use vendor correction factors when calculating transmission delays.
 * Fix unloading problem of ec_e100 driver.
 * Use ec_datagram_zero() where possible.
--- a/master/fsm_slave_config.c	Mon May 04 12:10:11 2009 +0000
+++ b/master/fsm_slave_config.c	Mon May 04 12:11:00 2009 +0000
@@ -34,6 +34,8 @@
 
 /*****************************************************************************/
 
+#include <asm/div64.h>
+
 #include "globals.h"
 #include "master.h"
 #include "mailbox.h"
@@ -1063,6 +1065,7 @@
 {
     ec_datagram_t *datagram = fsm->datagram;
     ec_slave_t *slave = fsm->slave;
+    ec_master_t *master = slave->master;
     ec_slave_config_t *config = slave->config;
     u64 start_time;
 
@@ -1092,9 +1095,38 @@
     }
 
     // set DC start time
-    start_time = slave->master->app_time +
-        config->dc_sync_shift_times[0] + 100000000ULL; // now + shift + x ns
-    if (slave->master->debug_level)
+    start_time = master->app_time + 100000000ULL; // now + X ns
+    // FIXME use slave's local system time here?
+
+    if (config->dc_sync_cycle_times[0]) {
+        // find correct phase
+        if (master->has_start_time) {
+            u32 cycle_time, shift_time, remainder;
+            u64 start, diff;
+
+            cycle_time = config->dc_sync_cycle_times[0];
+            shift_time = config->dc_sync_shift_times[0];
+            diff = start_time - master->app_start_time;
+            remainder = do_div(diff, cycle_time);
+
+            start = start_time + cycle_time - remainder + shift_time;
+
+            if (master->debug_level) {
+                EC_DBG("app_start_time=%llu\n", master->app_start_time);
+                EC_DBG("    start_time=%llu\n", start_time);
+                EC_DBG("    cycle_time=%u\n", cycle_time);
+                EC_DBG("    shift_time=%u\n", shift_time);
+                EC_DBG("     remainder=%u\n", remainder);
+                EC_DBG("         start=%llu\n", start);
+            }
+            start_time = start;
+        } else {
+            EC_WARN("No application time supplied. Cyclic start time will "
+                    "not be in phase for slave %u.", slave->ring_position);
+        }
+    }
+
+    if (master->debug_level)
         EC_DBG("Slave %u: Setting DC cyclic operation start time to %llu.\n",
                 slave->ring_position, start_time);
 
--- a/master/master.c	Mon May 04 12:10:11 2009 +0000
+++ b/master/master.c	Mon May 04 12:11:00 2009 +0000
@@ -130,6 +130,8 @@
     INIT_LIST_HEAD(&master->configs);
 
 	master->app_time = 0ULL;
+	master->app_start_time = 0ULL;
+	master->has_start_time = 0;
 
     master->scan_busy = 0;
     master->allow_scan = 1;
@@ -626,6 +628,8 @@
 #endif
 
     master->app_time = 0ULL;
+    master->app_start_time = 0ULL;
+    master->has_start_time = 0;
 
     if (ec_master_thread_start(master, ec_master_idle_thread,
                 "EtherCAT-IDLE"))
@@ -1748,6 +1752,11 @@
 void ecrt_master_application_time(ec_master_t *master, uint64_t app_time)
 {
     master->app_time = app_time;
+
+    if (unlikely(!master->has_start_time)) {
+        master->app_start_time = app_time;
+        master->has_start_time = 1;
+    }
 }
 
 /*****************************************************************************/
--- a/master/master.h	Mon May 04 12:10:11 2009 +0000
+++ b/master/master.h	Mon May 04 12:11:00 2009 +0000
@@ -118,6 +118,8 @@
     struct list_head configs; /**< List of slave configurations. */
     
     u64 app_time; /**< Time of the last ecrt_master_sync() call. */
+    u64 app_start_time; /**< Application start time. */
+    u8 has_start_time; /**< Start time already taken. */
     ec_datagram_t ref_sync_datagram; /**< Datagram used for synchronizing the
                                        reference clock to the master clock. */
     ec_datagram_t sync_datagram; /**< Datagram used for DC drift