Use application start time as a common reference for cyclic generation

start times.
This commit is contained in:
Florian Pose 2009-05-04 12:11:00 +00:00
parent 4c1c3fe289
commit 6935cbb247
4 changed files with 46 additions and 5 deletions

2
TODO
View File

@ -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.

View File

@ -34,6 +34,8 @@
/*****************************************************************************/
#include <asm/div64.h>
#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);

View File

@ -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;
}
}
/*****************************************************************************/

View File

@ -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