# HG changeset patch # User Florian Pose # Date 1240845614 0 # Node ID 5eb814732c46e7d8614bfdbd64ba3589310df35b # Parent 8fc38c37d86e427815b5371db360efc71f04878b Measure port receive times. diff -r 8fc38c37d86e -r 5eb814732c46 TODO --- a/TODO Mon Apr 27 11:38:03 2009 +0000 +++ b/TODO Mon Apr 27 15:20:14 2009 +0000 @@ -14,6 +14,7 @@ - Delay calculation. - Use common application time offset when setting start times. - Check 32/64 bit operations. + - Set system time offset only when application time available. * Fix unloading problem of ec_e100 driver. * Use ec_datagram_zero() where possible. * Fix arguments of reg_read. diff -r 8fc38c37d86e -r 5eb814732c46 documentation/graphs/fsm_master.dot --- a/documentation/graphs/fsm_master.dot Mon Apr 27 11:38:03 2009 +0000 +++ b/documentation/graphs/fsm_master.dot Mon Apr 27 15:20:14 2009 +0000 @@ -43,7 +43,10 @@ acknowledge -> action_configure [weight=10] clear_addresses [fontname="Helvetica"] - clear_addresses -> scan_slave [weight=10] + clear_addresses -> dc_measure_delays [weight=10] + + dc_measure_delays [fontname="Helvetica"] + dc_measure_delays -> scan_slave [weight=10] scan_slave [fontname="Helvetica"] scan_slave -> start diff -r 8fc38c37d86e -r 5eb814732c46 master/cdev.c --- a/master/cdev.c Mon Apr 27 11:38:03 2009 +0000 +++ b/master/cdev.c Mon Apr 27 15:20:14 2009 +0000 @@ -257,7 +257,11 @@ data.general_flags = slave->sii.general_flags; data.current_on_ebus = slave->sii.current_on_ebus; for (i = 0; i < EC_MAX_PORTS; i++) { - data.ports[i] = slave->base_ports[i]; + data.port_descs[i] = slave->base_ports[i]; + data.ports[i].dl_link = slave->ports[i].dl_link; + data.ports[i].dl_loop = slave->ports[i].dl_loop; + data.ports[i].dl_signal = slave->ports[i].dl_signal; + data.dc_receive_times[i] = slave->dc_receive_times[i]; } data.fmmu_bit = slave->base_fmmu_bit_operation; data.dc_supported = slave->base_dc_supported; diff -r 8fc38c37d86e -r 5eb814732c46 master/fsm_master.c --- a/master/fsm_master.c Mon Apr 27 11:38:03 2009 +0000 +++ b/master/fsm_master.c Mon Apr 27 15:20:14 2009 +0000 @@ -52,6 +52,7 @@ void ec_fsm_master_state_acknowledge(ec_fsm_master_t *); void ec_fsm_master_state_configure_slave(ec_fsm_master_t *); 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_write_sii(ec_fsm_master_t *); void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *); @@ -771,6 +772,42 @@ datagram->working_counter, master->slave_count); } + if (master->debug_level) + EC_DBG("Sending broadcast-write to measure transmission delays.\n"); + + ec_datagram_bwr(datagram, 0x0900, 1); + ec_datagram_zero(datagram); + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_master_state_dc_measure_delays; +} + +/*****************************************************************************/ + +/** Master state: DC MEASURE DELAYS. + */ +void ec_fsm_master_state_dc_measure_delays( + ec_fsm_master_t *fsm /**< Master state machine. */ + ) +{ + ec_master_t *master = fsm->master; + ec_datagram_t *datagram = fsm->datagram; + + if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) + return; + + if (datagram->state != EC_DATAGRAM_RECEIVED) { + EC_ERR("Failed to receive delay measuring datagram (state %u).\n", + datagram->state); + master->scan_busy = 0; + wake_up_interruptible(&master->scan_queue); + ec_fsm_master_restart(fsm); + return; + } + + if (master->debug_level) + EC_DBG("%u slaves responded to delay measuring.\n", + datagram->working_counter); + EC_INFO("Scanning bus.\n"); // begin scanning of slaves diff -r 8fc38c37d86e -r 5eb814732c46 master/fsm_slave_scan.c --- a/master/fsm_slave_scan.c Mon Apr 27 11:38:03 2009 +0000 +++ b/master/fsm_slave_scan.c Mon Apr 27 15:20:14 2009 +0000 @@ -48,6 +48,7 @@ void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_dc_cap(ec_fsm_slave_scan_t *); +void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *); @@ -257,11 +258,11 @@ /*****************************************************************************/ -/** - Slave scan state: BASE. -*/ - -void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *fsm /**< slave state machine */) +/** Slave scan state: BASE. + */ +void ec_fsm_slave_scan_state_base( + ec_fsm_slave_scan_t *fsm /**< slave state machine */ + ) { ec_datagram_t *datagram = fsm->datagram; ec_slave_t *slave = fsm->slave; @@ -374,6 +375,51 @@ return; } + // read DC port receive times + ec_datagram_fprd(datagram, slave->station_address, 0x0900, 16); + ec_datagram_zero(datagram); + fsm->retries = EC_FSM_RETRIES; + fsm->state = ec_fsm_slave_scan_state_dc_times; +} + +/*****************************************************************************/ + +/** + Slave scan state: DC TIMES. +*/ + +void ec_fsm_slave_scan_state_dc_times( + ec_fsm_slave_scan_t *fsm /**< slave state machine */ + ) +{ + ec_datagram_t *datagram = fsm->datagram; + ec_slave_t *slave = fsm->slave; + int i; + + if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) + return; + + if (datagram->state != EC_DATAGRAM_RECEIVED) { + fsm->state = ec_fsm_slave_scan_state_error; + EC_ERR("Failed to receive system time datagram for slave %u" + " (datagram state %u).\n", + slave->ring_position, datagram->state); + return; + } + + if (datagram->working_counter != 1) { + fsm->slave->error_flag = 1; + fsm->state = ec_fsm_slave_scan_state_error; + EC_ERR("Failed to get DC receive times of slave %u: ", + slave->ring_position); + ec_datagram_print_wc_error(datagram); + return; + } + + for (i = 0; i < EC_MAX_PORTS; i++) { + slave->dc_receive_times[i] = EC_READ_U32(datagram->data + 4 * i); + } + ec_fsm_slave_scan_enter_datalink(fsm); } diff -r 8fc38c37d86e -r 5eb814732c46 master/globals.h --- a/master/globals.h Mon Apr 27 11:38:03 2009 +0000 +++ b/master/globals.h Mon Apr 27 15:20:14 2009 +0000 @@ -166,6 +166,14 @@ EC_PORT_MII } ec_slave_port_desc_t; +/** EtherCAT slave port information. + */ +typedef struct { + uint8_t dl_link; /**< Link detected. */ + uint8_t dl_loop; /**< Loop closed. */ + uint8_t dl_signal; /**< Detected signal on RX port. */ +} ec_slave_port_t; + /** EtherCAT slave distributed clocks range. */ typedef enum { diff -r 8fc38c37d86e -r 5eb814732c46 master/ioctl.h --- a/master/ioctl.h Mon Apr 27 11:38:03 2009 +0000 +++ b/master/ioctl.h Mon Apr 27 15:20:14 2009 +0000 @@ -165,11 +165,13 @@ ec_sii_coe_details_t coe_details; ec_sii_general_flags_t general_flags; int16_t current_on_ebus; - ec_slave_port_desc_t ports[EC_MAX_PORTS]; + ec_slave_port_desc_t port_descs[EC_MAX_PORTS]; + ec_slave_port_t ports[EC_MAX_PORTS]; uint8_t fmmu_bit; uint8_t dc_supported; ec_slave_dc_range_t dc_range; uint8_t has_dc_system_time; + uint32_t dc_receive_times[EC_MAX_PORTS]; uint8_t al_state; uint8_t error_flag; uint8_t sync_count; diff -r 8fc38c37d86e -r 5eb814732c46 master/slave.c --- a/master/slave.c Mon Apr 27 11:38:03 2009 +0000 +++ b/master/slave.c Mon Apr 27 15:20:14 2009 +0000 @@ -95,6 +95,8 @@ slave->ports[i].dl_loop = 0; slave->ports[i].dl_signal = 0; slave->sii.physical_layer[i] = 0xFF; + + slave->dc_receive_times[i] = 0U; } slave->base_fmmu_bit_operation = 0; diff -r 8fc38c37d86e -r 5eb814732c46 master/slave.h --- a/master/slave.h Mon Apr 27 11:38:03 2009 +0000 +++ b/master/slave.h Mon Apr 27 15:20:14 2009 +0000 @@ -92,16 +92,6 @@ /*****************************************************************************/ -/** EtherCAT slave port information. - */ -typedef struct { - uint8_t dl_link; /**< Link detected. */ - uint8_t dl_loop; /**< Loop closed. */ - uint8_t dl_signal; /**< Detected signal on RX port. */ -} ec_slave_port_t; - -/*****************************************************************************/ - /** EtherCAT slave. */ struct ec_slave @@ -136,6 +126,8 @@ uint8_t has_dc_system_time; /**< The slave supports the DC system time register. Otherwise it can only be used for delay measurement. */ + uint32_t dc_receive_times[EC_MAX_PORTS]; /**< Port receive times for delay + measurement. */ // data link status ec_slave_port_t ports[EC_MAX_PORTS]; /**< Port link status. */ diff -r 8fc38c37d86e -r 5eb814732c46 tool/CommandSlaves.cpp --- a/tool/CommandSlaves.cpp Mon Apr 27 11:38:03 2009 +0000 +++ b/tool/CommandSlaves.cpp Mon Apr 27 15:20:14 2009 +0000 @@ -241,28 +241,6 @@ << " Serial number: 0x" << setw(8) << si->serial_number << endl; - cout << "Ports:" << endl; - for (i = 0; i < EC_MAX_PORTS; i++) { - cout << " " << i << ": "; - switch (si->ports[i]) { - case EC_PORT_NOT_IMPLEMENTED: - cout << "Not implemented."; - break; - case EC_PORT_NOT_CONFIGURED: - cout << "Not configured."; - break; - case EC_PORT_EBUS: - cout << "EBUS."; - break; - case EC_PORT_MII: - cout << "MII."; - break; - default: - cout << "???"; - } - cout << endl; - } - cout << "DL information:" << endl << " FMMU bit operation: " << (si->fmmu_bit ? "yes" : "no") << endl @@ -280,13 +258,62 @@ default: cout << "???"; } + cout << endl; } else { - cout << "yes, delay measurement only"; + cout << "yes, delay measurement only" << endl; } } else { - cout << "no"; - } + cout << "no" << endl; + } + + cout << "Port Type Link Loop Signal"; + if (si->dc_supported) + cout << " RxTime Diff"; cout << endl; + + for (i = 0; i < EC_MAX_PORTS; i++) { + cout << " " << i << " " << setfill(' ') << left << setw(4); + switch (si->port_descs[i]) { + case EC_PORT_NOT_IMPLEMENTED: + cout << "N/A"; + break; + case EC_PORT_NOT_CONFIGURED: + cout << "N/C"; + break; + case EC_PORT_EBUS: + cout << "EBUS"; + break; + case EC_PORT_MII: + cout << "MII"; + break; + default: + cout << "???"; + } + + cout << " " << setw(4) + << (si->ports[i].dl_link ? "up" : "down") + << " " << setw(6) + << (si->ports[i].dl_loop ? "closed" : "open") + << " " << setw(3) + << (si->ports[i].dl_signal ? "yes" : "no"); + + if (si->dc_supported) { + cout << " " << setw(10) << right; + if (si->ports[i].dl_signal) { + cout << dec << si->dc_receive_times[i]; + } else { + cout << "-"; + } + cout << " " << setw(10); + if (si->ports[i].dl_signal) { + cout << si->dc_receive_times[i] - si->dc_receive_times[0]; + } else { + cout << "-"; + } + } + + cout << endl; + } if (si->mailbox_protocols) { list protoList;