# HG changeset patch # User Florian Pose # Date 1273138972 -7200 # Node ID 29161abef052ff83bb3cdad010639c6987232e68 # Parent 2917b262554b43c99f1cffaf0829c168ed3814b1 Write DC system time offsets right after slave scan / config change. Wait for DC clock discipline. diff -r 2917b262554b -r 29161abef052 TODO --- a/TODO Thu May 06 11:41:25 2010 +0200 +++ b/TODO Thu May 06 11:42:52 2010 +0200 @@ -41,6 +41,7 @@ * Log SoE IDNs with real name ([SP]-x-yyyy). * Output SoE IDN configurations in 'ethercat config'. * Fix casting away constness during expected WC calculation. +* Only set system time offset, if application time is present. * Read AL status code on spontaneous state change. Future issues: diff -r 2917b262554b -r 29161abef052 master/fsm_master.c --- a/master/fsm_master.c Thu May 06 11:41:25 2010 +0200 +++ b/master/fsm_master.c Thu May 06 11:42:52 2010 +0200 @@ -46,6 +46,12 @@ /*****************************************************************************/ +/** Time difference [ns] to tolerate without setting a new system time offset. + */ +#define EC_SYSTEM_TIME_TOLERANCE_NS 100000000 + +/*****************************************************************************/ + void ec_fsm_master_state_start(ec_fsm_master_t *); void ec_fsm_master_state_broadcast(ec_fsm_master_t *); void ec_fsm_master_state_read_state(ec_fsm_master_t *); @@ -54,11 +60,14 @@ 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_dc_read_offset(ec_fsm_master_t *); +void ec_fsm_master_state_dc_write_offset(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 *); void ec_fsm_master_state_sdo_request(ec_fsm_master_t *); void ec_fsm_master_state_reg_request(ec_fsm_master_t *); +void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *); /*****************************************************************************/ @@ -290,13 +299,25 @@ } if (master->slave_count) { - // fetch state from first slave - fsm->slave = master->slaves; - ec_datagram_fprd(fsm->datagram, fsm->slave->station_address, - 0x0130, 2); - ec_datagram_zero(datagram); - fsm->retries = EC_FSM_RETRIES; - fsm->state = ec_fsm_master_state_read_state; + + // application applied configurations + if (master->config_changed) { + master->config_changed = 0; + + EC_MASTER_DBG(master, 1, "Configuration changed.\n"); + + fsm->slave = master->slaves; // begin with first slave + ec_fsm_master_enter_write_system_times(fsm); + + } else { + // fetch state from first slave + fsm->slave = master->slaves; + ec_datagram_fprd(fsm->datagram, fsm->slave->station_address, + 0x0130, 2); + ec_datagram_zero(datagram); + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_master_state_read_state; + } } else { ec_fsm_master_restart(fsm); } @@ -787,7 +808,12 @@ ec_master_eoe_start(master); #endif - ec_fsm_master_restart(fsm); + if (master->slave_count) { + fsm->slave = master->slaves; // begin with first slave + ec_fsm_master_enter_write_system_times(fsm); + } else { + ec_fsm_master_restart(fsm); + } } /*****************************************************************************/ @@ -821,6 +847,208 @@ /*****************************************************************************/ +/** Start writing DC system times. + */ +void ec_fsm_master_enter_write_system_times( + ec_fsm_master_t *fsm /**< Master state machine. */ + ) +{ + ec_master_t *master = fsm->master; + + EC_MASTER_DBG(master, 1, "Writing system time offsets...\n"); + + if (master->has_app_time) { + while (fsm->slave < master->slaves + master->slave_count) { + if (!fsm->slave->base_dc_supported + || !fsm->slave->has_dc_system_time) { + fsm->slave++; + continue; + } + + // read DC system time (0x0910, 64 bit) + // gap (64 bit) + // and time offset (0x0920, 64 bit) + ec_datagram_fprd(fsm->datagram, fsm->slave->station_address, + 0x0910, 24); + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_master_state_dc_read_offset; + return; + } + } else { + EC_MASTER_DBG(master, 1, "No app_time received up to now.\n"); + } + + ec_master_request_op(master); + ec_fsm_master_restart(fsm); +} + +/*****************************************************************************/ + +/** Configure 32 bit time offset. + */ +u64 ec_fsm_master_dc_offset32( + ec_fsm_master_t *fsm, /**< Master state machine. */ + u64 system_time, /**< System time register. */ + u64 old_offset, /**< Time offset register. */ + unsigned long jiffies_since_read /**< Jiffies for correction. */ + ) +{ + ec_slave_t *slave = fsm->slave; + u32 correction, system_time32, old_offset32, new_offset; + s32 time_diff; + + system_time32 = (u32) system_time; + old_offset32 = (u32) old_offset; + + // correct read system time by elapsed time since read operation + correction = jiffies_since_read * 1000 / HZ * 1000000; + system_time32 += correction; + time_diff = (u32) slave->master->app_time - system_time32; + + EC_SLAVE_DBG(slave, 1, "DC system time offset calculation:" + " system_time=%u (corrected with %u)," + " app_time=%u, diff=%i\n", + system_time32, correction, + (u32) slave->master->app_time, time_diff); + + if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) { + new_offset = time_diff + old_offset32; + EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n", + new_offset, old_offset32); + return (u64) new_offset; + } else { + EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n"); + return old_offset; + } +} + +/*****************************************************************************/ + +/** Configure 64 bit time offset. + */ +u64 ec_fsm_master_dc_offset64( + ec_fsm_master_t *fsm, /**< Master state machine. */ + u64 system_time, /**< System time register. */ + u64 old_offset, /**< Time offset register. */ + unsigned long jiffies_since_read /**< Jiffies for correction. */ + ) +{ + ec_slave_t *slave = fsm->slave; + u64 new_offset, correction; + s64 time_diff; + + // correct read system time by elapsed time since read operation + correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000; + system_time += correction; + time_diff = fsm->slave->master->app_time - system_time; + + EC_SLAVE_DBG(slave, 1, "DC system time offset calculation:" + " system_time=%llu (corrected with %llu)," + " app_time=%llu, diff=%lli\n", + system_time, correction, + slave->master->app_time, time_diff); + + if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) { + new_offset = time_diff + old_offset; + EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n", + new_offset, old_offset); + } else { + new_offset = old_offset; + EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n"); + } + + return new_offset; +} + +/*****************************************************************************/ + +/** Master state: DC READ OFFSET. + */ +void ec_fsm_master_state_dc_read_offset( + ec_fsm_master_t *fsm /**< Master state machine. */ + ) +{ + ec_datagram_t *datagram = fsm->datagram; + ec_slave_t *slave = fsm->slave; + u64 system_time, old_offset, new_offset; + unsigned long jiffies_since_read; + + if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) + return; + + if (datagram->state != EC_DATAGRAM_RECEIVED) { + EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: "); + ec_datagram_print_state(datagram); + fsm->slave++; + ec_fsm_master_enter_write_system_times(fsm); + return; + } + + if (datagram->working_counter != 1) { + EC_SLAVE_WARN(slave, "Failed to get DC times: "); + ec_datagram_print_wc_error(datagram); + fsm->slave++; + ec_fsm_master_enter_write_system_times(fsm); + return; + } + + system_time = EC_READ_U64(datagram->data); // 0x0910 + old_offset = EC_READ_U64(datagram->data + 16); // 0x0920 + jiffies_since_read = jiffies - datagram->jiffies_sent; + + if (slave->base_dc_range == EC_DC_32) { + new_offset = ec_fsm_master_dc_offset32(fsm, + system_time, old_offset, jiffies_since_read); + } else { + new_offset = ec_fsm_master_dc_offset64(fsm, + system_time, old_offset, jiffies_since_read); + } + + // set DC system time offset and transmission delay + ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12); + EC_WRITE_U64(datagram->data, new_offset); + EC_WRITE_U32(datagram->data + 8, slave->transmission_delay); + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_master_state_dc_write_offset; +} + +/*****************************************************************************/ + +/** Master state: DC WRITE OFFSET. + */ +void ec_fsm_master_state_dc_write_offset( + ec_fsm_master_t *fsm /**< Master 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) { + EC_SLAVE_ERR(slave, + "Failed to receive DC system time offset datagram: "); + ec_datagram_print_state(datagram); + fsm->slave++; + ec_fsm_master_enter_write_system_times(fsm); + return; + } + + if (datagram->working_counter != 1) { + EC_SLAVE_ERR(slave, "Failed to set DC system time offset: "); + ec_datagram_print_wc_error(datagram); + fsm->slave++; + ec_fsm_master_enter_write_system_times(fsm); + return; + } + + fsm->slave++; + ec_fsm_master_enter_write_system_times(fsm); +} + +/*****************************************************************************/ + /** Master state: WRITE SII. */ void ec_fsm_master_state_write_sii( diff -r 2917b262554b -r 29161abef052 master/fsm_slave_config.c --- a/master/fsm_slave_config.c Thu May 06 11:41:25 2010 +0200 +++ b/master/fsm_slave_config.c Thu May 06 11:42:52 2010 +0200 @@ -44,9 +44,20 @@ /*****************************************************************************/ -/** Time difference [ns] to tolerate without setting a new system time offset. - */ -#define EC_SYSTEM_TIME_TOLERANCE_NS 100000000 +/** Maximum clock difference (in ns) before going to SAFEOP. + * + * Wait for DC time difference to drop under this absolute value before + * requesting SAFEOP. + */ +#define EC_DC_MAX_SYNC_DIFF_NS 5000 + +/** Maximum time (in ms) to wait for clock discipline. + */ +#define EC_DC_SYNC_WAIT_MS 5000 + +/** Time offset (in ns), that is added to cyclic start time. + */ +#define EC_DC_START_OFFSET 100000000ULL /*****************************************************************************/ @@ -55,8 +66,6 @@ void ec_fsm_slave_config_state_clear_fmmus(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_clear_sync(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_dc_clear_assign(ec_fsm_slave_config_t *); -void ec_fsm_slave_config_state_dc_read_offset(ec_fsm_slave_config_t *); -void ec_fsm_slave_config_state_dc_write_offset(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_mbox_sync(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_boot_preop(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *); @@ -67,6 +76,7 @@ void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_fmmu(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_dc_cycle(ec_fsm_slave_config_t *); +void ec_fsm_slave_config_state_dc_sync_check(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_dc_start(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_dc_assign(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_safeop(ec_fsm_slave_config_t *); @@ -391,172 +401,6 @@ ec_datagram_print_wc_error(datagram); } - // read DC system time (0x0910, 64 bit) - // gap (64 bit) - // and time offset (0x0920, 64 bit) - ec_datagram_fprd(fsm->datagram, fsm->slave->station_address, 0x0910, 24); - fsm->retries = EC_FSM_RETRIES; - fsm->state = ec_fsm_slave_config_state_dc_read_offset; -} - -/*****************************************************************************/ - -/** Configure 32 bit time offset. - */ -u64 ec_fsm_slave_config_dc_offset32( - ec_fsm_slave_config_t *fsm, /**< slave state machine */ - u64 system_time, /**< System time register. */ - u64 old_offset, /**< Time offset register. */ - unsigned long jiffies_since_read /**< Jiffies for correction. */ - ) -{ - ec_slave_t *slave = fsm->slave; - u32 correction, system_time32, old_offset32, new_offset; - s32 time_diff; - - system_time32 = (u32) system_time; - old_offset32 = (u32) old_offset; - - // correct read system time by elapsed time since read operation - correction = jiffies_since_read * 1000 / HZ * 1000000; - system_time32 += correction; - time_diff = (u32) slave->master->app_time - system_time32; - - EC_SLAVE_DBG(slave, 1, "Calculating DC time offset (32 bit):" - " system_time=%u (corrected with %u), app_time=%u, diff=%i\n", - system_time32, correction, - (u32) slave->master->app_time, time_diff); - - if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) { - new_offset = time_diff + old_offset32; - EC_SLAVE_DBG(slave, 1, "Setting time offset to %u (was %u)\n", - new_offset, old_offset32); - return (u64) new_offset; - } else { - EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n"); - return old_offset; - } -} - -/*****************************************************************************/ - -/** Configure 64 bit time offset. - */ -u64 ec_fsm_slave_config_dc_offset64( - ec_fsm_slave_config_t *fsm, /**< slave state machine */ - u64 system_time, /**< System time register. */ - u64 old_offset, /**< Time offset register. */ - unsigned long jiffies_since_read /**< Jiffies for correction. */ - ) -{ - ec_slave_t *slave = fsm->slave; - u64 new_offset, correction; - s64 time_diff; - - // correct read system time by elapsed time since read operation - correction = (u64) (jiffies_since_read * 1000 / HZ) * 1000000; - system_time += correction; - time_diff = fsm->slave->master->app_time - system_time; - - EC_SLAVE_DBG(slave, 1, "Calculating DC time offset (64 bit):" - " system_time=%llu (corrected with %llu)," - " app_time=%llu, diff=%lli\n", - system_time, correction, - slave->master->app_time, time_diff); - - if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) { - new_offset = time_diff + old_offset; - EC_SLAVE_DBG(slave, 1, "Setting time offset to %llu (was %llu)\n", - new_offset, old_offset); - } else { - new_offset = old_offset; - EC_SLAVE_DBG(slave, 1, "Not touching time offset.\n"); - } - - return new_offset; -} - -/*****************************************************************************/ - -/** Slave configuration state: DC READ OFFSET. - */ -void ec_fsm_slave_config_state_dc_read_offset( - ec_fsm_slave_config_t *fsm /**< slave state machine */ - ) -{ - ec_datagram_t *datagram = fsm->datagram; - ec_slave_t *slave = fsm->slave; - u64 system_time, old_offset, new_offset; - unsigned long jiffies_since_read; - - if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) - return; - - if (datagram->state != EC_DATAGRAM_RECEIVED) { - fsm->state = ec_fsm_slave_config_state_error; - EC_SLAVE_ERR(slave, "Failed to receive DC times datagram: "); - ec_datagram_print_state(datagram); - return; - } - - if (datagram->working_counter != 1) { - slave->error_flag = 1; - fsm->state = ec_fsm_slave_config_state_error; - EC_SLAVE_ERR(slave, "Failed to get DC times: "); - ec_datagram_print_wc_error(datagram); - return; - } - - system_time = EC_READ_U64(datagram->data); // 0x0910 - old_offset = EC_READ_U64(datagram->data + 16); // 0x0920 - jiffies_since_read = jiffies - datagram->jiffies_sent; - - if (slave->base_dc_range == EC_DC_32) { - new_offset = ec_fsm_slave_config_dc_offset32(fsm, - system_time, old_offset, jiffies_since_read); - } else { - new_offset = ec_fsm_slave_config_dc_offset64(fsm, - system_time, old_offset, jiffies_since_read); - } - - // set DC system time offset and transmission delay - ec_datagram_fpwr(datagram, slave->station_address, 0x0920, 12); - EC_WRITE_U64(datagram->data, new_offset); - EC_WRITE_U32(datagram->data + 8, slave->transmission_delay); - fsm->retries = EC_FSM_RETRIES; - fsm->state = ec_fsm_slave_config_state_dc_write_offset; -} - -/*****************************************************************************/ - -/** Slave configuration state: DC WRITE OFFSET. - */ -void ec_fsm_slave_config_state_dc_write_offset( - ec_fsm_slave_config_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_config_state_error; - EC_SLAVE_ERR(slave, "Failed to receive DC system time offset" - " datagram: "); - ec_datagram_print_state(datagram); - return; - } - - if (datagram->working_counter != 1) { - slave->error_flag = 1; - fsm->state = ec_fsm_slave_config_state_error; - EC_SLAVE_ERR(slave, "Failed to set DC system time offset: "); - ec_datagram_print_wc_error(datagram); - return; - } - ec_fsm_slave_config_enter_mbox_sync(fsm); } @@ -1319,8 +1163,53 @@ { ec_datagram_t *datagram = fsm->datagram; ec_slave_t *slave = fsm->slave; + ec_slave_config_t *config = slave->config; + + if (!config) { // config removed in the meantime + ec_fsm_slave_config_reconfigure(fsm); + return; + } + + if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) + return; + + if (datagram->state != EC_DATAGRAM_RECEIVED) { + fsm->state = ec_fsm_slave_config_state_error; + EC_SLAVE_ERR(slave, "Failed to receive DC cycle times datagram: "); + ec_datagram_print_state(datagram); + return; + } + + if (datagram->working_counter != 1) { + slave->error_flag = 1; + fsm->state = ec_fsm_slave_config_state_error; + EC_SLAVE_ERR(slave, "Failed to set DC cycle times: "); + ec_datagram_print_wc_error(datagram); + return; + } + + EC_SLAVE_DBG(slave, 1, "Checking for synchrony.\n"); + + fsm->jiffies_start = jiffies; + ec_datagram_fprd(datagram, slave->station_address, 0x092c, 4); + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_slave_config_state_dc_sync_check; +} + +/*****************************************************************************/ + +/** Slave configuration state: DC SYNC CHECK. + */ +void ec_fsm_slave_config_state_dc_sync_check( + ec_fsm_slave_config_t *fsm /**< slave state machine */ + ) +{ + 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; + uint32_t abs_sync_diff; + unsigned long diff_ms; ec_sync_signal_t *sync0 = &config->dc_sync[0]; u64 start_time; @@ -1334,7 +1223,7 @@ if (datagram->state != EC_DATAGRAM_RECEIVED) { fsm->state = ec_fsm_slave_config_state_error; - EC_SLAVE_ERR(slave, "Failed to receive DC cycle times datagram: "); + EC_SLAVE_ERR(slave, "Failed to receive DC sync check datagram: "); ec_datagram_print_state(datagram); return; } @@ -1342,18 +1231,40 @@ if (datagram->working_counter != 1) { slave->error_flag = 1; fsm->state = ec_fsm_slave_config_state_error; - EC_SLAVE_ERR(slave, "Failed to set DC cycle times: "); + EC_SLAVE_ERR(slave, "Failed to check DC synchrony: "); ec_datagram_print_wc_error(datagram); return; } + abs_sync_diff = EC_READ_U32(datagram->data) & 0x7fffffff; + diff_ms = (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; + + if (abs_sync_diff > EC_DC_MAX_SYNC_DIFF_NS) { + + if (diff_ms >= EC_DC_SYNC_WAIT_MS) { + EC_SLAVE_WARN(slave, "Slave did not sync after %u ms.\n", + (u32) diff_ms); + } else { + EC_SLAVE_DBG(slave, 1, "Sync after %4u ms: %10u ns\n", + (u32) diff_ms, abs_sync_diff); + + // check synchrony again + ec_datagram_fprd(datagram, slave->station_address, 0x092c, 4); + fsm->retries = EC_FSM_RETRIES; + return; + } + } else { + EC_SLAVE_DBG(slave, 1, "%u ns difference after %u ms.\n", + abs_sync_diff, (u32) diff_ms); + } + // set DC start time - start_time = master->app_time + 100000000ULL; // now + X ns + start_time = master->app_time + EC_DC_START_OFFSET; // now + X ns // FIXME use slave's local system time here? if (sync0->cycle_time) { // find correct phase - if (master->has_start_time) { + if (master->has_app_time) { u64 diff, start; u32 remainder; @@ -1363,20 +1274,13 @@ start = start_time + sync0->cycle_time - remainder + sync0->shift_time; - if (master->debug_level) { - EC_SLAVE_DBG(slave, 1, "app_start_time=%llu\n", - master->app_start_time); - EC_SLAVE_DBG(slave, 1, " start_time=%llu\n", - start_time); - EC_SLAVE_DBG(slave, 1, " cycle_time=%u\n", - sync0->cycle_time); - EC_SLAVE_DBG(slave, 1, " shift_time=%u\n", - sync0->shift_time); - EC_SLAVE_DBG(slave, 1, " remainder=%u\n", - remainder); - EC_SLAVE_DBG(slave, 1, " start=%llu\n", - start); - } + EC_SLAVE_DBG(slave, 1, "app_start_time=%llu\n", + master->app_start_time); + EC_SLAVE_DBG(slave, 1, " start_time=%llu\n", start_time); + EC_SLAVE_DBG(slave, 1, " cycle_time=%u\n", sync0->cycle_time); + EC_SLAVE_DBG(slave, 1, " shift_time=%u\n", sync0->shift_time); + EC_SLAVE_DBG(slave, 1, " remainder=%u\n", remainder); + EC_SLAVE_DBG(slave, 1, " start=%llu\n", start); start_time = start; } else { EC_SLAVE_WARN(slave, "No application time supplied." diff -r 2917b262554b -r 29161abef052 master/master.c --- a/master/master.c Thu May 06 11:41:25 2010 +0200 +++ b/master/master.c Thu May 06 11:42:52 2010 +0200 @@ -139,6 +139,7 @@ master->phase = EC_ORPHANED; master->active = 0; + master->config_changed = 0; master->injection_seq_fsm = 0; master->injection_seq_rt = 0; @@ -149,7 +150,7 @@ master->app_time = 0ULL; master->app_start_time = 0ULL; - master->has_start_time = 0; + master->has_app_time = 0; master->scan_busy = 0; master->allow_scan = 1; @@ -1824,6 +1825,37 @@ ec_master_calc_transmission_delays(master); } +/*****************************************************************************/ + +/** Request OP state for configured slaves. + */ +void ec_master_request_op( + ec_master_t *master /**< EtherCAT master. */ + ) +{ + unsigned int i; + ec_slave_t *slave; + + if (!master->active) + return; + + EC_MASTER_DBG(master, 1, "Requesting OP...\n"); + + // request OP for all configured slaves + for (i = 0; i < master->slave_count; i++) { + slave = master->slaves + i; + if (slave->config) { + ec_slave_request_state(slave, EC_SLAVE_STATE_OP); + } + } + + // always set DC reference clock to OP + if (master->dc_ref_clock) { + ec_slave_request_state(master->dc_ref_clock, + EC_SLAVE_STATE_OP); + } +} + /****************************************************************************** * Application interface *****************************************************************************/ @@ -1906,11 +1938,6 @@ domain_offset += domain->data_size; } - // always set DC reference clock to OP - if (master->dc_ref_clock) { - ec_slave_request_state(master->dc_ref_clock, EC_SLAVE_STATE_OP); - } - up(&master->master_sem); // restart EoE process and master thread with new locking @@ -1945,6 +1972,10 @@ master->allow_config = 1; // request the current configuration master->allow_scan = 1; // allow re-scanning on topology change master->active = 1; + + // notify state machine, that the configuration shall now be applied + master->config_changed = 1; + return 0; } @@ -2004,7 +2035,7 @@ master->app_time = 0ULL; master->app_start_time = 0ULL; - master->has_start_time = 0; + master->has_app_time = 0; #ifdef EC_EOE if (eoe_was_running) { @@ -2258,9 +2289,9 @@ { master->app_time = app_time; - if (unlikely(!master->has_start_time)) { + if (unlikely(!master->has_app_time)) { master->app_start_time = app_time; - master->has_start_time = 1; + master->has_app_time = 1; } } diff -r 2917b262554b -r 29161abef052 master/master.h --- a/master/master.h Thu May 06 11:41:25 2010 +0200 +++ b/master/master.h Thu May 06 11:42:52 2010 +0200 @@ -164,6 +164,7 @@ ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */ ec_master_phase_t phase; /**< Master phase. */ unsigned int active; /**< Master has been activated. */ + unsigned int config_changed; /**< The configuration changed. */ unsigned int injection_seq_fsm; /**< Datagram injection sequence number for the FSM side. */ unsigned int injection_seq_rt; /**< Datagram injection sequence number @@ -177,7 +178,7 @@ 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. */ + u8 has_app_time; /**< Application time is valid. */ 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 @@ -306,6 +307,7 @@ uint16_t, uint32_t, uint32_t); void ec_master_calc_dc(ec_master_t *); +void ec_master_request_op(ec_master_t *); void ec_master_internal_send_cb(void *); void ec_master_internal_receive_cb(void *);