--- a/master/fsm_slave_config.c Fri May 07 15:26:26 2010 +0200
+++ b/master/fsm_slave_config.c Tue May 11 13:57:58 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 *);
@@ -196,10 +206,7 @@
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
- if (fsm->slave->master->debug_level) {
- EC_DBG("Configuring slave %u...\n", fsm->slave->ring_position);
- }
-
+ EC_SLAVE_DBG(fsm->slave, 1, "Configuring...\n");
ec_fsm_slave_config_enter_init(fsm);
}
@@ -224,7 +231,6 @@
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
- ec_master_t *master = fsm->slave->master;
ec_slave_t *slave = fsm->slave;
ec_datagram_t *datagram = fsm->datagram;
@@ -237,18 +243,14 @@
return;
}
- if (master->debug_level) {
- EC_DBG("Slave %u is now in INIT.\n", slave->ring_position);
- }
+ EC_SLAVE_DBG(slave, 1, "Now in INIT.\n");
if (!slave->base_fmmu_count) { // skip FMMU configuration
ec_fsm_slave_config_enter_clear_sync(fsm);
return;
}
- if (master->debug_level)
- EC_DBG("Clearing FMMU configurations of slave %u...\n",
- slave->ring_position);
+ EC_SLAVE_DBG(slave, 1, "Clearing FMMU configurations...\n");
// clear FMMU configurations
ec_datagram_fpwr(datagram, slave->station_address,
@@ -273,16 +275,14 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed receive FMMU clearing datagram for slave %u.\n",
- fsm->slave->ring_position);
+ EC_SLAVE_ERR(fsm->slave, "Failed receive FMMU clearing datagram.\n");
return;
}
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to clear FMMUs of slave %u: ",
- fsm->slave->ring_position);
+ EC_SLAVE_ERR(fsm->slave, "Failed to clear FMMUs: ");
ec_datagram_print_wc_error(datagram);
return;
}
@@ -308,9 +308,7 @@
return;
}
- if (slave->master->debug_level)
- EC_DBG("Clearing sync manager configurations of slave %u...\n",
- slave->ring_position);
+ EC_SLAVE_DBG(slave, 1, "Clearing sync manager configurations...\n");
sync_size = EC_SYNC_PAGE_SIZE * slave->base_sync_count;
@@ -336,16 +334,16 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed receive sync manager clearing datagram"
- " for slave %u.\n", fsm->slave->ring_position);
+ EC_SLAVE_ERR(fsm->slave, "Failed receive sync manager"
+ " clearing datagram.\n");
return;
}
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to clear sync manager configurations of slave %u: ",
- fsm->slave->ring_position);
+ EC_SLAVE_ERR(fsm->slave,
+ "Failed to clear sync manager configurations: ");
ec_datagram_print_wc_error(datagram);
return;
}
@@ -369,9 +367,7 @@
return;
}
- if (slave->master->debug_level)
- EC_DBG("Clearing DC assignment of slave %u...\n",
- slave->ring_position);
+ EC_SLAVE_DBG(slave, 1, "Clearing DC assignment...\n");
ec_datagram_fpwr(datagram, slave->station_address, 0x0980, 2);
ec_datagram_zero(datagram);
@@ -394,202 +390,17 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed receive DC assignment clearing datagram"
- " for slave %u.\n", fsm->slave->ring_position);
- return;
- }
-
- if (fsm->slave->master->debug_level && datagram->working_counter != 1) {
+ EC_SLAVE_ERR(fsm->slave, "Failed receive DC assignment"
+ " clearing datagram.\n");
+ return;
+ }
+
+ if (datagram->working_counter != 1) {
// clearing the DC assignment does not succeed on simple slaves
- EC_DBG("Failed to clear DC assignment of slave %u: ",
- fsm->slave->ring_position);
+ EC_SLAVE_DBG(fsm->slave, 1, "Failed to clear DC assignment: ");
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. */
- u64 correction /**< Correction. */
- )
-{
- ec_slave_t *slave = fsm->slave;
- u32 correction32, 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
- correction32 = (u32)correction;
- system_time32 -= correction32;
- time_diff = (u32) slave->master->app_time - system_time32;
-
- if (slave->master->debug_level)
- EC_DBG("Slave %u: system_time=%u (corrected with %u),"
- " app_time=%u, diff=%i\n",
- slave->ring_position, system_time32, correction32,
- (u32) slave->master->app_time, time_diff);
-
- if (EC_ABS(time_diff) > EC_SYSTEM_TIME_TOLERANCE_NS) {
- new_offset = time_diff + old_offset32;
- if (slave->master->debug_level)
- EC_DBG("Slave %u: Setting time offset to %u (was %u)\n",
- slave->ring_position, new_offset, old_offset32);
- return (u64) new_offset;
- } else {
- if (slave->master->debug_level)
- EC_DBG("Slave %u: Not touching time offset.\n",
- slave->ring_position);
- 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. */
- u64 correction /**< Correction. */
- )
-{
- ec_slave_t *slave = fsm->slave;
- u64 new_offset;
- s64 time_diff;
-
- system_time -= correction;
- time_diff = fsm->slave->master->app_time - system_time;
-
- if (slave->master->debug_level)
- EC_DBG("Slave %u: system_time=%llu (corrected with %llu),"
- " app_time=%llu, diff=%lli\n",
- slave->ring_position, 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;
- if (slave->master->debug_level)
- EC_DBG("Slave %u: Setting time offset to %llu (was %llu)\n",
- slave->ring_position, new_offset, old_offset);
- } else {
- new_offset = old_offset;
- if (slave->master->debug_level)
- EC_DBG("Slave %u: Not touching time offset.\n",
- slave->ring_position);
- }
-
- 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, correction;
- 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_ERR("Failed to receive DC times datagram for slave %u: ",
- slave->ring_position);
- ec_datagram_print_state(datagram);
- return;
- }
-
- if (datagram->working_counter != 1) {
- slave->error_flag = 1;
- fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to get DC times of slave %u: ",
- slave->ring_position);
- ec_datagram_print_wc_error(datagram);
- return;
- }
-
- system_time = EC_READ_U64(datagram->data); // 0x0910
- old_offset = EC_READ_U64(datagram->data + 16); // 0x0920
- /* correct read system time by elapsed time since read operation
- and the app_time set time */
-#ifdef EC_HAVE_CYCLES
- correction =
- (datagram->cycles_sent - slave->master->dc_cycles_app_time)
- * 1000000LL;
- do_div(correction,cpu_khz);
-#else
- correction =
- (u64) ((datagram->jiffies_sent-slave->master->dc_jiffies_app_time) * 1000 / HZ)
- * 1000000;
-#endif
-
- if (slave->base_dc_range == EC_DC_32) {
- new_offset = ec_fsm_slave_config_dc_offset32(fsm,
- system_time, old_offset, correction);
- } else {
- new_offset = ec_fsm_slave_config_dc_offset64(fsm,
- system_time, old_offset, correction);
- }
-
- // 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_ERR("Failed to receive DC system time offset datagram for"
- " slave %u: ", slave->ring_position);
- ec_datagram_print_state(datagram);
- return;
- }
-
- if (datagram->working_counter != 1) {
- slave->error_flag = 1;
- fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to set DC system time offset of slave %u: ",
- slave->ring_position);
- ec_datagram_print_wc_error(datagram);
- return;
- }
-
ec_fsm_slave_config_enter_mbox_sync(fsm);
}
@@ -601,7 +412,6 @@
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
- ec_master_t *master = fsm->slave->master;
ec_slave_t *slave = fsm->slave;
ec_datagram_t *datagram = fsm->datagram;
unsigned int i;
@@ -609,26 +419,19 @@
// slave is now in INIT
if (slave->current_state == slave->requested_state) {
fsm->state = ec_fsm_slave_config_state_end; // successful
- if (master->debug_level) {
- EC_DBG("Finished configuration of slave %u.\n",
- slave->ring_position);
- }
+ EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
return;
}
if (!slave->sii.mailbox_protocols) {
// no mailbox protocols supported
- if (master->debug_level)
- EC_DBG("Slave %u does not support mailbox communication.\n",
- slave->ring_position);
+ EC_SLAVE_DBG(slave, 1, "Slave does not support"
+ " mailbox communication.\n");
ec_fsm_slave_config_enter_boot_preop(fsm);
return;
}
- if (master->debug_level) {
- EC_DBG("Configuring mailbox sync managers of slave %u.\n",
- slave->ring_position);
- }
+ EC_SLAVE_DBG(slave, 1, "Configuring mailbox sync managers...\n");
if (slave->requested_state == EC_SLAVE_STATE_BOOT) {
ec_sync_t sync;
@@ -684,10 +487,8 @@
} else { // no mailbox sync manager configurations provided
ec_sync_t sync;
- if (master->debug_level)
- EC_DBG("Slave %u does not provide"
- " mailbox sync manager configurations.\n",
- slave->ring_position);
+ EC_SLAVE_DBG(slave, 1, "Slave does not provide"
+ " mailbox sync manager configurations.\n");
ec_datagram_fpwr(datagram, slave->station_address, 0x0800,
EC_SYNC_PAGE_SIZE * 2);
@@ -742,8 +543,8 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to receive sync manager configuration datagram for"
- " slave %u: ", slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to receive sync manager"
+ " configuration datagram: ");
ec_datagram_print_state(datagram);
return;
}
@@ -764,12 +565,11 @@
if (diff >= HZ) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Timeout while configuring mailbox sync managers of"
- " slave %u.\n", slave->ring_position);
+ EC_SLAVE_ERR(slave, "Timeout while configuring"
+ " mailbox sync managers.\n");
return;
- }
- else if (slave->master->debug_level) {
- EC_DBG("Resending after %u ms...\n",
+ } else {
+ EC_SLAVE_DBG(slave, 1, "Resending after %u ms...\n",
(unsigned int) diff * 1000 / HZ);
}
@@ -780,8 +580,7 @@
else if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to set sync managers of slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to set sync managers: ");
ec_datagram_print_wc_error(datagram);
return;
}
@@ -817,7 +616,6 @@
)
{
ec_slave_t *slave = fsm->slave;
- ec_master_t *master = fsm->slave->master;
if (ec_fsm_change_exec(fsm->fsm_change)) return;
@@ -831,18 +629,12 @@
// slave is now in BOOT or PREOP
slave->jiffies_preop = fsm->datagram->jiffies_received;
- if (master->debug_level) {
- EC_DBG("Slave %u is now in %s.\n", slave->ring_position,
- slave->requested_state != EC_SLAVE_STATE_BOOT
- ? "PREOP" : "BOOT");
- }
+ EC_SLAVE_DBG(slave, 1, "Now in %s.\n",
+ slave->requested_state != EC_SLAVE_STATE_BOOT ? "PREOP" : "BOOT");
if (slave->current_state == slave->requested_state) {
fsm->state = ec_fsm_slave_config_state_end; // successful
- if (master->debug_level) {
- EC_DBG("Finished configuration of slave %u.\n",
- slave->ring_position);
- }
+ EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
return;
}
@@ -891,8 +683,7 @@
if (ec_fsm_coe_exec(fsm->fsm_coe)) return;
if (!ec_fsm_coe_success(fsm->fsm_coe)) {
- EC_ERR("SDO configuration failed for slave %u.\n",
- fsm->slave->ring_position);
+ EC_SLAVE_ERR(fsm->slave, "SDO configuration failed.\n");
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
return;
@@ -968,8 +759,7 @@
}
if (!ec_fsm_soe_success(fsm_soe)) {
- EC_ERR("SoE configuration failed for slave %u.\n",
- fsm->slave->ring_position);
+ EC_SLAVE_ERR(slave, "SoE configuration failed.\n");
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
return;
@@ -1029,8 +819,7 @@
}
if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
- EC_WARN("PDO configuration failed on slave %u.\n",
- fsm->slave->ring_position);
+ EC_SLAVE_WARN(fsm->slave, "PDO configuration failed.\n");
}
ec_fsm_slave_config_enter_watchdog_divider(fsm);
@@ -1046,13 +835,11 @@
{
ec_slave_t *slave = fsm->slave;
ec_datagram_t *datagram = fsm->datagram;
- ec_master_t *master = slave->master;
ec_slave_config_t *config = slave->config;
if (config && config->watchdog_divider) {
- if (master->debug_level)
- EC_DBG("Setting watchdog divider to %u.\n",
- config->watchdog_divider);
+ EC_SLAVE_DBG(slave, 1, "Setting watchdog divider to %u.\n",
+ config->watchdog_divider);
ec_datagram_fpwr(datagram, slave->station_address, 0x0400, 2);
EC_WRITE_U16(datagram->data, config->watchdog_divider);
@@ -1079,16 +866,15 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to receive watchdog divider configuration datagram for"
- " slave %u: ", slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to receive watchdog divider"
+ " configuration datagram: ");
ec_datagram_print_state(datagram);
return;
}
if (datagram->working_counter != 1) {
slave->error_flag = 1;
- EC_WARN("Failed to set watchdog divider of slave %u: ",
- slave->ring_position);
+ EC_SLAVE_WARN(slave, "Failed to set watchdog divider: ");
ec_datagram_print_wc_error(datagram);
return;
}
@@ -1109,9 +895,8 @@
ec_slave_config_t *config = slave->config;
if (config && config->watchdog_intervals) {
- if (slave->master->debug_level)
- EC_DBG("Setting process data watchdog intervals to %u.\n",
- config->watchdog_intervals);
+ EC_SLAVE_DBG(slave, 1, "Setting process data"
+ " watchdog intervals to %u.\n", config->watchdog_intervals);
ec_datagram_fpwr(datagram, slave->station_address, 0x0420, 2);
EC_WRITE_U16(datagram->data, config->watchdog_intervals);
@@ -1140,15 +925,15 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to receive sync manager watchdog configuration "
- "datagram for slave %u: ", slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to receive sync manager"
+ " watchdog configuration datagram: ");
ec_datagram_print_state(datagram);
return;
}
if (datagram->working_counter != 1) {
- EC_WARN("Failed to set process data watchdog intervals of slave %u: ",
- slave->ring_position);
+ EC_SLAVE_WARN(slave, "Failed to set process data"
+ " watchdog intervals: ");
ec_datagram_print_wc_error(datagram);
}
@@ -1227,8 +1012,8 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to receive process data sync manager configuration"
- " datagram for slave %u: ", slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to receive process data sync"
+ " manager configuration datagram: ");
ec_datagram_print_state(datagram);
return;
}
@@ -1236,8 +1021,7 @@
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to set process data sync managers of slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to set process data sync managers: ");
ec_datagram_print_wc_error(datagram);
return;
}
@@ -1267,8 +1051,8 @@
if (slave->base_fmmu_count < slave->config->used_fmmus) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Slave %u has less FMMUs (%u) than requested (%u).\n",
- slave->ring_position, slave->base_fmmu_count,
+ EC_SLAVE_ERR(slave, "Slave has less FMMUs (%u)"
+ " than requested (%u).\n", slave->base_fmmu_count,
slave->config->used_fmmus);
return;
}
@@ -1287,8 +1071,8 @@
if (!(sync = ec_slave_get_sync(slave, fmmu->sync_index))) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to determine PDO sync manager for FMMU on slave"
- " %u!\n", slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to determine PDO sync manager"
+ " for FMMU!\n");
return;
}
ec_fmmu_config_page(fmmu, sync,
@@ -1315,8 +1099,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to receive FMMUs datagram for slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to receive FMMUs datagram: ");
ec_datagram_print_state(datagram);
return;
}
@@ -1324,8 +1107,7 @@
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to set FMMUs of slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to set FMMUs: ");
ec_datagram_print_wc_error(datagram);
return;
}
@@ -1352,15 +1134,12 @@
if (config->dc_assign_activate) {
if (!slave->base_dc_supported || !slave->has_dc_system_time) {
- EC_WARN("Slave %u seems not to support distributed clocks!\n",
- slave->ring_position);
+ EC_SLAVE_WARN(slave, "Slave seems not to support"
+ " distributed clocks!\n");
}
- if (slave->master->debug_level)
- EC_DBG("Slave %u: Setting DC cycle times to %u / %u.\n",
- slave->ring_position,
- config->dc_sync[0].cycle_time,
- config->dc_sync[1].cycle_time);
+ EC_SLAVE_DBG(slave, 1, "Setting DC cycle times to %u / %u.\n",
+ config->dc_sync[0].cycle_time, config->dc_sync[1].cycle_time);
// set DC cycle times
ec_datagram_fpwr(datagram, slave->station_address, 0x09A0, 8);
@@ -1384,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;
@@ -1399,8 +1223,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to receive DC cycle times datagram for slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to receive DC sync check datagram: ");
ec_datagram_print_state(datagram);
return;
}
@@ -1408,19 +1231,40 @@
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to set DC cycle times of slave %u: ",
- slave->ring_position);
+ 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;
@@ -1430,24 +1274,22 @@
start = start_time +
sync0->cycle_time - remainder + sync0->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", sync0->cycle_time);
- EC_DBG(" shift_time=%u\n", sync0->shift_time);
- EC_DBG(" remainder=%u\n", remainder);
- EC_DBG(" 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_WARN("No application time supplied. Cyclic start time will "
- "not be in phase for slave %u.\n", slave->ring_position);
+ EC_SLAVE_WARN(slave, "No application time supplied."
+ " Cyclic start time will not be in phase.\n");
}
}
- if (master->debug_level)
- EC_DBG("Slave %u: Setting DC cyclic operation start time to %llu.\n",
- slave->ring_position, start_time);
+ EC_SLAVE_DBG(slave, 1, "Setting DC cyclic operation"
+ " start time to %llu.\n", start_time);
ec_datagram_fpwr(datagram, slave->station_address, 0x0990, 8);
EC_WRITE_U64(datagram->data, start_time);
@@ -1477,8 +1319,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to receive DC start time datagram for slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to receive DC start time datagram: ");
ec_datagram_print_state(datagram);
return;
}
@@ -1486,15 +1327,13 @@
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to set DC start time of slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to set DC start time: ");
ec_datagram_print_wc_error(datagram);
return;
}
- if (slave->master->debug_level)
- EC_DBG("Slave %u: Setting DC AssignActivate to 0x%04x.\n",
- slave->ring_position, config->dc_assign_activate);
+ EC_SLAVE_DBG(slave, 1, "Setting DC AssignActivate to 0x%04x.\n",
+ config->dc_assign_activate);
// assign sync unit to EtherCAT or PDI
ec_datagram_fpwr(datagram, slave->station_address, 0x0980, 2);
@@ -1519,8 +1358,7 @@
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to receive DC activation datagram for slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to receive DC activation datagram: ");
ec_datagram_print_state(datagram);
return;
}
@@ -1528,8 +1366,7 @@
if (datagram->working_counter != 1) {
slave->error_flag = 1;
fsm->state = ec_fsm_slave_config_state_error;
- EC_ERR("Failed to set DC cyclic operation state of slave %u: ",
- slave->ring_position);
+ EC_SLAVE_ERR(slave, "Failed to activate DC: ");
ec_datagram_print_wc_error(datagram);
return;
}
@@ -1558,7 +1395,6 @@
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
- ec_master_t *master = fsm->slave->master;
ec_slave_t *slave = fsm->slave;
if (ec_fsm_change_exec(fsm->fsm_change)) return;
@@ -1572,16 +1408,11 @@
// slave is now in SAFEOP
- if (master->debug_level) {
- EC_DBG("Slave %u is now in SAFEOP.\n", slave->ring_position);
- }
+ EC_SLAVE_DBG(slave, 1, "Now in SAFEOP.\n");
if (fsm->slave->current_state == fsm->slave->requested_state) {
fsm->state = ec_fsm_slave_config_state_end; // successful
- if (master->debug_level) {
- EC_DBG("Finished configuration of slave %u.\n",
- slave->ring_position);
- }
+ EC_SLAVE_DBG(slave, 1, "Finished configuration.\n");
return;
}
@@ -1599,7 +1430,6 @@
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
- ec_master_t *master = fsm->slave->master;
ec_slave_t *slave = fsm->slave;
if (ec_fsm_change_exec(fsm->fsm_change)) return;
@@ -1613,10 +1443,7 @@
// slave is now in OP
- if (master->debug_level) {
- EC_DBG("Slave %u is now in OP.\n", slave->ring_position);
- EC_DBG("Finished configuration of slave %u.\n", slave->ring_position);
- }
+ EC_SLAVE_DBG(slave, 1, "Now in OP. Finished configuration.\n");
fsm->state = ec_fsm_slave_config_state_end; // successful
}
@@ -1629,10 +1456,8 @@
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
- if (fsm->slave->master->debug_level) {
- EC_DBG("Slave configuration for slave %u detached during "
- "configuration. Reconfiguring.", fsm->slave->ring_position);
- }
+ EC_SLAVE_DBG(fsm->slave, 1, "Slave configuration detached during "
+ "configuration. Reconfiguring.");
ec_fsm_slave_config_enter_init(fsm); // reconfigure
}