From 6935cbb247bfb18691f9fbe978dc30650d3f21d8 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Mon, 4 May 2009 12:11:00 +0000 Subject: [PATCH] Use application start time as a common reference for cyclic generation start times. --- TODO | 2 -- master/fsm_slave_config.c | 38 +++++++++++++++++++++++++++++++++++--- master/master.c | 9 +++++++++ master/master.h | 2 ++ 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/TODO b/TODO index 833cdf60..1053d8ef 100644 --- a/TODO +++ b/TODO @@ -11,9 +11,7 @@ vim700: spelllang=en spell 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. diff --git a/master/fsm_slave_config.c b/master/fsm_slave_config.c index 4954c638..5eb8938c 100644 --- a/master/fsm_slave_config.c +++ b/master/fsm_slave_config.c @@ -34,6 +34,8 @@ /*****************************************************************************/ +#include + #include "globals.h" #include "master.h" #include "mailbox.h" @@ -1063,6 +1065,7 @@ void ec_fsm_slave_config_state_dc_cycle( { 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 @@ void ec_fsm_slave_config_state_dc_cycle( } // 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); diff --git a/master/master.c b/master/master.c index 62df6525..2776c157 100644 --- a/master/master.c +++ b/master/master.c @@ -130,6 +130,8 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */ 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 @@ void ec_master_leave_operation_phase(ec_master_t *master #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_state(const ec_master_t *master, ec_master_state_t *state) 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; + } } /*****************************************************************************/ diff --git a/master/master.h b/master/master.h index bf4ddfa3..37ee44a8 100644 --- a/master/master.h +++ b/master/master.h @@ -118,6 +118,8 @@ struct ec_master { 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