Measure port receive times.
--- 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.
--- 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
--- 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;
--- 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
--- 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);
}
--- 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 {
--- 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;
--- 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;
--- 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. */
--- 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<string> protoList;